pax_global_header00006660000000000000000000000064147670435310014524gustar00rootroot0000000000000052 comment=ae1889822d872eddd572a43ad0a4a3674fa5a9fa pappl-1.4.9/000077500000000000000000000000001476704353100126535ustar00rootroot00000000000000pappl-1.4.9/BUILD.md000066400000000000000000000055701476704353100140430ustar00rootroot00000000000000Build Instructions ================== PAPPL requires Microsoft® Windows® 10 or higher or a POSIX-compliant host operating system such as Linux®, macOS®, QNX®, or VxWorks®. On Windows, the provided project files require Visual Studio 2019 or higher. For POSIX hosts, a "make" utility that supports the `include` directive (like GNU make), a C99-compatible C compiler such as GCC or Clang, and the "pkg-config" utility are required along with the following support libraries: - Avahi (0.8 or later) or mDNSResponder for mDNS/DNS-SD support - CUPS (2.2 or later) or libcups (3.0 or later) for the CUPS libraries - GNU TLS (3.0 or later), LibreSSL (3.0 or later), or OpenSSL (1.1 or later) for TLS support - JPEGLIB (8 or later) or libjpeg-turbo (2.0 or later) for JPEG image support (optional for B&W printers) - LIBPNG (1.6 or later) for PNG image support (optional) - LIBPAM for authentication support (optional) - LIBUSB (1.0 or later) for USB printing support (optional) - PAM for authentication support (optional) - ZLIB (1.1 or later) for compression support Getting Prerequisites --------------------- CentOS 8/Fedora 23+/RHEL 8: sudo dnf groupinstall 'Development Tools' sudo dnf install avahi-devel cups-devel libjpeg-turbo-devel \ libpng-devel libssl-devel libusbx-devel pam-devel zlib-devel Debian/Raspbian/Ubuntu: sudo apt-get install build-essential libavahi-client-dev libcups2-dev \ libcupsimage2-dev libjpeg-dev libpam-dev libpng-dev libssl-dev \ libusb-1.0-0-dev zlib1g-dev macOS (after installing Xcode from the AppStore): (install brew if necessary from ) brew install libjpeg brew install libpng brew install libusb brew install openssl@3 or download, build, and install libjpeg, libpng, libusb, and OpenSSL or LibreSSL from source. Windows (after installing Visual Studio 2019 or later) will automatically install the prerequisites via NuGet packages. Building PAPPL -------------- PAPPL uses the usual `configure` script to generate a `make` file: ./configure [options] make Use `./configure --help` to see a full list of options. There is also an Xcode project under the `xcode` directory that can be used on macOS: open xcode/pappl.xcodeproj and a Visual Studio solution under the `vcnet` directory that must be used on Windows. You can test the build by running the PAPPL test program: testsuite/testpappl Installing PAPPL ---------------- Once you have successfully built PAPPL, install it using: sudo make install By default everything will be installed under `/usr/local`. Use the `--prefix` configure option to override the base installation directory. Set the `DESTDIR`, `DSTROOT`, or `RPM_BUILD_ROOT` environment variables to redirect the installation to a staging area, as is typically done for most software packaging systems (using one of those environment variables...) pappl-1.4.9/CHANGES.md000066400000000000000000000117261476704353100142540ustar00rootroot00000000000000Changes in PAPPL ================ Changes in v1.4.9 (2025-03-20) ------------------------------ - Fixed a bug in job event notifications. - Fixed a bug that would delay shutdown by 60 seconds. - Fixed some notification bugs. - Fixed validation error checking bug in `papplPrinterCreate` (Issue #385) - Fixed page number that is passed to the raster endpage function. - Disabled raw socket support on Windows. Changes in v1.4.8 (2024-11-14) ------------------------------ - SECURITY: The web interface password didn't work properly (Issue #373) - Now use the "listen-hostname" hostname as system hostname if a name is specified (Issue #369) Changes in v1.4.7 (2024-08-15) ------------------------------ - PAM-based authentication did not work on Linux due to a glibc incompatibility (Issue #343) - Fixed the web interface for setting the admin and print groups (Issue #356) - Fixed the web interface for adding network printers on non-standard port numbers (Issue #360) - Fixed some USB gadget error conditions. - Fixed the Wi-Fi configuration web page. - Fixed a logging deadlock issue. - Fixed some threading issues. - Fixed how PAPPL responds to an unsupported request character set. - Fixed the "no-tls" server option. Changes in v1.4.6 (2024-02-09) ------------------------------ - Fixed reporting of "printer-strings-languages-supported" attribute (Issue #328) - Fixed saving of "print-darkness-default" and "print-speed-default" values (Issue #330 and #337) - Fixed incoming "raw" print socket support (Issue #331 and #338) - Fixed web interface support for "printer-darkness" (Issue #333) - Fixed some issues discovered by OpenScanHub (Issue #335) - Fixed localization of command-line (main loop) interface. Changes in v1.4.5 (2024-01-26) ------------------------------ - Fixed `--disable-libpam` configure option. - Fixed support for "finishings", "output-bin", and "sides" options. - Fixed IEEE-1284 device ID generation code. - Fixed crash in retrofit printer application (Issue #322) - Fixed some Coverity-detected threading issues. Changes in v1.4.4 (2023-12-21) ------------------------------ - Fixed "printer-settable-attributes-supported" value (Issue #311) - Fixed `-n` support for setting number of copies (Issue #312) - Fixed `papplPrinterSetDriverDefaults` didn't set the "orientation-requested-default" value (Issue #313) - Fixed job file preservation logic. - Fixed builds against current libcups3. Changes in v1.4.3 (2023-11-15) ------------------------------ - Added "smi55357-device-uri" and "smi55357-driver" Printer Status attributes to Get-Printer-Attributes responses. - Fixed missing mutex unlock in DNS-SD code (Issue #299) - Fixed "printer-id" value for new printers (Issue #301) - Fixed DNS-SD device list crash (Issue #302) - Fixed Set-Printer-Attributes for "output-bin-default" and "sides-default" (Issue #305) - Fixed default "copies" value with `papplJobCreateWithFile`. Changes in v1.4.2 (2024-10-16) ------------------------------ - Fixed potential crash while listing devices (Issue #296) - Fixed potential deadlock issue (Issue #297) - Fixed loading of previous state (Issue #298) Changes in v1.4.1 (2024-10-10) ------------------------------ - Fixed typos in the names of the `papplJobResume` and `papplJobSuspend` functions (Issue #295) Changes in v1.4.0 (2024-09-28) ------------------------------ - Added support for "job-retain-until" (Issue #14) - Added new PAPPL-Create-Printers operation, and the PAPPL mainloop API now auto-adds local printers the first time a server is run (Issue #245) - Added new `papplDeviceRemoveScheme` and `papplDeviceRemoveTypes` APIs to disable unwanted device types (Issue #259) - Added support for suspending and resuming jobs at copy boundaries (Issue #266) - Added support for server configuration files (Issue #279) - Now preserve the paused state of printers (Issue #286) - Fixed reporting of "xxx-k-octet-supported" attributes. - Fixed printing of 1/2/4-bit grayscale PNG images (Issue #267) - Fixed USB serial number for DYMO printers (Issue #271) - Fixed a potential buffer overflow in the logging code (Issue #272) - Fixed DNS-SD advertisements when the server name is set to "localhost" (Issue #274) - Fixed hostname change detection when using mDNSResponder (Issue #282) - Fixed authentication cookie comparisons for simple password mode. - Fixed a potential time-of-use issue with PAPPL-created directories. - Fixed handling of trailing '%' in log format strings. - Updated the `options` sub-command to list vendor options and values (Issue #255) - Updated web interface to show the age of jobs (Issue #256) - Updated "devices" sub-command to have the PAPPL server find the devices instead of doing it directly (Issue #262) - Updated default logging to be less chatty (Issue #270) - Updated the Wi-Fi configuration page to support hidden networks. - Updated the Wi-Fi configuration page reload time to 30 seconds. - Updated TLS certificate generation to support more types of certificates and to use modern OpenSSL/GNU TLS APIs. pappl-1.4.9/CODE_OF_CONDUCT.md000066400000000000000000000007471476704353100154620ustar00rootroot00000000000000Code of Conduct =============== My goal is to provide quality open source software that everyone can use. While I may not be able to address every request or accept every contribution to this project, I will do my best to develop and maintain it for the common good. As part of the open source community, I expect everyone to: - Be friendly and patient. - Be respectful, even if we disagree. - Be honest. - Be accepting of all people. - Fully explain your concerns, issues, or ideas. pappl-1.4.9/CONTRIBUTING.md000066400000000000000000000515701476704353100151140ustar00rootroot00000000000000Contributing to PAPPL ===================== PAPPL is developed and distributed as open source software under the Apache License, Version 2.0. Contributions should be submitted as pull requests on the Github site: http://github.com/michaelrsweet/pappl/pulls Contents -------- - [Build System](#build-system) - [Version Numbering](#version-numbering) - [Coding Guidelines](#coding-guidelines) - [Source Files](#source-files) - [Header Files](#header-files) - [Comments](#comments) - [Indentation](#indentation) - [Spacing](#spacing) - [Return Values](#return-values) - [Functions](#functions) - [Variables](#variables) - [Types](#types) - [Structures](#structures) - [Constants](#constants) - [Shell Script Guidelines](#shell-script-guidelines) - [Makefile Guidelines](#makefile-guidelines) - [General Organization](#general-organization) - [Makefile Documentation](#makefile-documentation) - [Portable Makefile Construction](#portable-makefile-construction) - [Standard Variables](#standard-variables) - [Standard Targets](#standard-targets) - [Object Files](#object-files) - [Programs](#programs) - [Static Libraries](#static-libraries) - [Shared Libraries](#shared-libraries) - [Dependencies](#dependencies) - [Install/Uninstall Support](#installuninstall-support) Build System ------------ The build system uses GNU autoconf to tailor the library to the local operating system. Visual Studio and Xcode projects are also provided in the "vcnet" and "xcode" directories for Windows and macOS, respectively. To improve portability, makefiles *must not* make use of features unique to GNU make. See the [Makefile Guidelines](#makefile-guidelines) section for a description of the allowed make features and makefile guidelines. Additional GNU build programs such as GNU automake and GNU libtool *must not* be used. GNU automake produces non-portable makefiles which depend on GNU-specific extensions, and GNU libtool is not portable or reliable enough for PAPPL. Version Numbering ----------------- PAPPL uses a three-part version number separated by periods to represent the major, minor, and patch release numbers. Major release numbers indicate large design changes or backwards-incompatible changes to the library. Minor release numbers indicate new features and other smaller changes which are backwards- compatible with previous releases. Patch numbers indicate bug fixes to the previous feature or patch release. > Note: > > When we talk about compatibility, we are talking about binary compatibility > for public APIs and output format compatibility for program interfaces. > Changes to configuration file formats or the default behavior of programs > are not generally considered incompatible as the upgrade process can > normally address such changes gracefully. Production releases use the plain version numbers: MAJOR.MINOR.PATCH 1.0.0 1.0.1 1.0.2 ... 1.1.0 ... 2.0.0 The first production release in a MAJOR.MINOR series (MAJOR.MINOR.0) is called a feature release. Feature releases are the only releases that may contain new features. Subsequent production releases in a MAJOR.MINOR series may only contain bug fixes. Beta-test releases are identified by appending the letter B to the major and minor version numbers followed by the beta release number: MAJOR.MINORbNUMBER 1.0b1 Release candidates are identified by appending the letters RC to the major and minor version numbers followed by the release candidate number: MAJOR.MINORrcNUMBER 1.0rc1 Coding Guidelines ----------------- Contributed source code must follow the guidelines below. While the examples are for C source files, source code for other languages should conform to the same guidelines as allowed by the language. PAPPL requires at least C99 support for all C code. Aside from adding the `bool` type and `//` comments, C99 also clarifies the `NULL` behavior of certain standard functions such as `free` and `realloc`. ### Source Files All source files names must be 16 characters or less in length to ensure compatibility with older UNIX filesystems. Source files containing functions have an extension of ".c" for C files and ".m" for Objective C files. All "include" files have an extension of ".h". Tabs are set to 8 characters or columns. The top of each source file contains a header giving the purpose or nature of the source file and the copyright and licensing notice: // // Description of file contents. // // Copyright YYYY by AUTHOR. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // ### Header Files Private API header files must be named with the suffix "-private", for example the "pappl.h" header file defines all of the public APIs while the "pappl-private.h" header file defines all of the private APIs. Typically a private API header file will include the corresponding public API header file. ### Comments All source code utilizes block comments within functions to describe the operations being performed by a group of statements; avoid putting a comment per line unless absolutely necessary, and then consider refactoring the code so that it is not necessary. C source files use the C99 comment format ("// comment"): // Clear the state array before we begin... for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++) array[i] = PAPPL_STATE_IDLE; // Wait for state changes on another thread... do { for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++) if (array[i] != PAPPL_STATE_IDLE) break; if (i == (sizeof(array) / sizeof(array[0]))) sleep(1); } while (i == (sizeof(array) / sizeof(array[0]))); ### Indentation All code blocks enclosed by brackets begin with the opening brace on a new line. The code then follows starting on a new line after the brace and is indented 2 spaces. The closing brace is then placed on a new line following the code at the original indentation: { int i; // Looping var // Process foobar values from 0 to 999... for (i = 0; i < 1000; i ++) { do_this(i); do_that(i); } } Single-line statements following "do", "else", "for", "if", and "while" are indented 2 spaces as well. Blocks of code in a "switch" block are indented 4 spaces after each "case" and "default" case: switch (array[i]) { case PAPPL_STATE_IDLE : do_this(i); do_that(i); break; default : do_nothing(i); break; } ### Spacing A space follows each reserved word such as `if`, `while`, etc. Spaces are not inserted between a function name and the arguments in parenthesis. ### Return Values Parenthesis surround values returned from a function: return (PAPPL_STATE_IDLE); ### Functions Functions with a global scope have a lowercase prefix followed by capitalized words, e.g., `papplDoThis`, `papplDoThat`, `papplDoSomethingElse`, etc. Private global functions begin with a leading underscore, e.g., `_papplDoThis`, `_papplDoThat`, etc. Functions with a local scope are declared static with lowercase names and underscores between words, e.g., `do_this`, `do_that`, `do_something_else`, etc. Function names follow the following pattern: - "papplFooCreate" to create a Foo object, - "papplFooDelete" to destroy (free) a Foo object, - "papplFooGetBar" to get data element Bar from object Foo, - "papplFooIsBar" to test condition Bar for object Foo, and - "papplFooSetBar" to set data element Bar in object Foo. - "papplFooVerb" to take an action with object Foo. Each function begins with a comment header describing what the function does, the possible input limits (if any), the possible output values (if any), and any special information needed: // // 'papplDoThis()' - Short description of function. // // Longer documentation for function with examples using a subset of // markdown. This is a bulleted list: // // - One fish // - Two fish // - Red fish // - Blue fish // // > *Note:* Special notes for developer should be markdown block quotes. // float // O - Inverse power value, 0.0 <= y <= 1.1 papplDoThis(float x) // I - Power value (0.0 <= x <= 1.1) { ... return (y); } Return/output values are indicated using an "O" prefix, input values are indicated using the "I" prefix, and values that are both input and output use the "IO" prefix for the corresponding in-line comment. The [`codedoc` documentation generator][1] also understands the following special text in the function description comment: @deprecated@ - Marks the function as deprecated (not recommended for new development and scheduled for removal) @since version@ - Marks the function as new in the specified version. @private@ - Marks the function as private (same as starting the function name with an underscore) [1]: https://www.msweet.org/codedoc ### Variables Variables with a global scope are capitalized, e.g., `ThisVariable`, `ThatVariable`, `ThisStateVariable`, etc. Globals *must not* be used in the PAPPL library. Variables with a local scope are lowercase with underscores between words, e.g., `this_variable`, `that_variable`, etc. Any "local global" variables shared by functions within a source file are declared static. Each variable is declared on a separate line and is immediately followed by a comment block describing the variable: int ThisVariable; // The current state of this static int that_variable; // The current state of that ### Types All type names are lowercase with underscores between words and `_t` appended to the end of the name, e.g., `pappl_this_type_t`, `pappl_that_type_t`, etc. Type names start with the "pappl\_" prefix to avoid conflicts with system types. Private type names start with an underscore, e.g., `_pappl_this_t`, `_pappl_that_t`, etc. Each type has a comment block immediately after the typedef: typedef int pappl_this_type_t; // This type is for foobar options. ### Structures All structure names are lowercase with underscores between words and `_s` appended to the end of the name, e.g., `pappl_this_s`, `pappl_that_s`, etc. Structure names start with the "pappl\_" prefix to avoid conflicts with system types. Private structure names start with an underscore, e.g., `_pappl_this_s`, `_pappl_that_s`, etc. Each structure has a comment block immediately after the struct and each member is documented similar to the variable naming policy above: struct pappl_this_struct_s // This structure is for foobar options. { int this_member; // Current state for this int that_member; // Current state for that }; One common design pattern is to define a private structure with a public typedef, for example: // In public header typedef struct _pappl_foo_s pappl_foo_t // Foo object // In private header struct _pappl_foo_s // Foo object { int this_member; // Current state for this int that_member; // Current state for that }; ### Constants All constant names are uppercase with underscores between words, e.g., `PAPPL_THIS_CONSTANT`, `PAPPL_THAT_CONSTANT`, etc. Constants begin with the "PAPPL\_" prefix to avoid conflicts with system constants. Private constants start with an underscore, e.g., `_PAPPL_THIS_CONSTANT`, `_PAPPL_THAT_CONSTANT`, etc. Typed enumerations should be used whenever possible to allow for type checking by the compiler. The constants for typed enumerations must match the type name in uppercase, for example a `pappl_foo_e` enumeration has constant names starting with `PAPPL_FOO_`. Comment blocks immediately follow each constant: typedef enum pappl_tray_e // Tray enumerations { PAPPL_TRAY_THIS, // This tray PAPPL_TRAY_THAT // That tray } pappl_tray_t; Shell Script Guidelines ----------------------- All shell scripts in PAPPL must conform to the [POSIX shell][POSIX-SHELL] command language and should restrict their dependence on non-POSIX utility commands. [POSIX-SHELL]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18 Makefile Guidelines ------------------- The following is a guide to the [POSIX makefile-based][POSIX-MAKE] build system. These standards have been developed over the years to allow the PAPPL to be built on as many systems and environments as possible. [POSIX-MAKE]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html ### General Organization The source code is organized functionally into a top-level makefile, include file, and subdirectories each with their own makefile and dependencies files. The ".in" files are template files for the autoconf software and are used to generate a static version of the corresponding file. ### Makefile Documentation Each makefile starts with the standard header containing the description of the file, and PAPPL copyright and license notice: # # Makefile for ... # # Copyright YYYY by AUTHOR. # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # ### Portable Makefile Construction We use a common subset of make program syntax to ensure that the software can be compiled "out of the box" on as many systems as possible. The following is a list of assumptions we follow when constructing makefiles: - Targets; we assume that the make program supports the notion of simple targets of the form "name:" that perform tab-indented commands that follow the target, e.g.: target: TAB target commands - Dependencies; we assume that the make program supports recursive dependencies on targets, e.g.: target: foo bar TAB target commands foo: bla TAB foo commands bar: TAB bar commands bla: TAB bla commands - Variable Definition; we assume that the make program supports variable definition on the command-line or in the makefile using the following form: name=value - Variable Substitution; we assume that the make program supports variable substitution using the following forms: - `$(name)`; substitutes the value of "name", - `$(name:.old=.new)`; substitutes the value of "name" with the filename extension ".old" changed to ".new", - `$(MAKEFLAGS)`; substitutes the command-line options passed to the program without the leading hyphen (-), - `$$`; substitutes a single $ character, - `$<`; substitutes the current source file or dependency, and - `$@`; substitutes the current target name. - Suffixes; we assume that the make program supports filename suffixes with assumed dependencies, e.g.: .SUFFIXES: .c .o .c.o: TAB $(CC) $(CFLAGS) -o $@ -c $< - Include Files; we assume that the make program supports POSIX include lines, e.g.: include ../Makedefs include Dependencies - Comments; we assume that comments begin with a # character and proceed to the end of the current line. - Line Length; we assume that there is no practical limit to the length of lines. - Continuation of long lines; we assume that the `\` character may be placed at the end of a line to concatenate two or more lines in a makefile to form a single long line. - Shell; we assume a POSIX-compatible shell is present on the build system. ### Standard Variables The following variables are defined in the "Makedefs" file generated by the autoconf software: - `AR`; the static library archiver command, - `ARFLAGS`; options for the static library archiver command, - `BUILDROOT`; optional installation prefix (defaults to `DESTDIR`, `DSTROOT`, or `RPM_BUILD_ROOT`, as defined in the environment), - `CC`; the C compiler command, - `CFLAGS`; options for the C compiler command, - `CODE_SIGN`: the code signing utility, - `CODESIGN_IDENTITY`: the code signing identity, - `CPPFLAGS`; options for the C preprocessor, - `CSFLAGS`; options for the code signing utility, - `DSOFLAGS`; options for the shared library building command, - `INSTALL`; the install command, - `LIBPAPPL`; the name of the PAPPL library file, - `LIBPAPPL_STATIC`; the name of the PAPPL static library file (if different from `LIBPAPPL`), - `LDFLAGS`; options for the linker, - `LIBS`; libraries for all programs, - `LN`; the ln command, - `MKDIR`; the mkdir command, - `OPTIM`; common compiler optimization options, - `PAPPL_VERSION`; the full PAPPL version number, - `PAPPL_VERSION_MAJOR`; the major number from the PAPPL version, - `PAPPL_VERSION_MINOR`; the minor number from the PAPPL version, - `RANLIB`; the static library indexing command, - `RM`; the rm command, - `RMDIR`; the rmdir command, - `SHELL`; the sh (POSIX shell) command, - `SYSTEM_STATUS`; the native system status UI plug-in (if any), - `WARNINGS`; common compiler warning options, - `bindir`; the user command installation directory, - `datadir`; the data file installation directory, - `datarootdir`; the root data file installation directory, - `exec_prefix`; the executable installation prefix directory, - `includedir`; the public header file installation directory, - `libdir`; the library installation directory, - `libexecdir`; the library executables installation directory, - `localestatedir`; the local state directory, - `mandir`; the man page installation directory, - `oldincludedir`; a historical variable required for autoconf, - `prefix`; the installation prefix directory, - `sbindir`; the administrative command installation directory, - `sharedstatedir`; the shared state directory, - `srcdir`; the source directory, - `sysconfdir`; the system configuration directory, and - `top_srcdir`; the top-level source directory. ### Standard Targets The following standard targets are defined in each makefile: - `all`; creates all target programs, libraries, and documentation files, - `clean`; removes all target programs libraries, documentation files, and object files, - `depend`; generates automatic dependencies for any C source files (also see "DEPENDENCIES"), - `distclean`; removes autoconf-generated files in addition to those removed by the "clean" target, - `install`; installs all distribution files in their corresponding locations (also see "INSTALL/UNINSTALL SUPPORT"), - `test`; performs all unit and combined tests, and - `uninstall`; removes all distribution files from their corresponding locations (also see "INSTALL/UNINSTALL SUPPORT"). ### Object Files Object files (the result of compiling a C source file) have the extension ".o". ### Programs Program files are the result of linking object files and libraries together to form an executable file. A typical program target looks like: program: $(OBJS) TAB echo Linking $@... TAB $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) TAB $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.$@ $@ ### Static Libraries Static libraries have a prefix of "lib" and the extension ".a". A typical static library target looks like: libname.a: $(OBJECTS) TAB echo Creating $@... TAB $(RM) $@ TAB $(AR) $(ARFLAGS) $@ $(OBJECTS) TAB $(RANLIB) $@ ### Shared Libraries Shared libraries have a prefix of "lib" and the extension ".dylib" or ".so" depending on the operating system. A typical shared library is composed of several targets that look like: libname.so.1: $(OBJECTS) TAB echo $(CC) $(DSOFLAGS) -o $@ ... TAB $(CC) $(DSOFLAGS) -o $@ $(OBJECTS) TAB $(RM) `basename $@ .1` TAB $(LN) $@ `basename $@ .1` libname.1.dylib: $(OBJECTS) TAB echo $(CC) $(DSOFLAGS) -o $@ ... TAB $(CC) $(DSOFLAGS) -o $@ \ TAB TAB -install_name $(libdir)/$@ \ TAB TAB -current_version 1.0.0 \ TAB TAB -compatibility_version 1 \ TAB TAB $(OBJECTS) $(LIBS) TAB $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.`basename $@ .1.dylib` $@ TAB $(RM) `basename $@ .1.dylib`.dylib TAB $(LN) $@ `basename $@ .1.dylib`.dylib ### Dependencies Static dependencies are expressed in each makefile following the target, for example: foo: bar Static dependencies are only used when it is not possible to automatically generate them. Automatic dependencies are stored in a file named "Dependencies" and included at the end of the makefile. The following "depend" target rule is used to create the automatic dependencies: depend: TAB $(CC) -MM $(CFLAGS) $(OBJS:.o=.c) | \ TAB TAB sed -e '1,$$s/ \/usr\/include\/[^ ]*//g' \ TAB TAB -e '1,$$s/ \/usr\/local\/include\/[^ ]*//g' >Dependencies ### Install/Uninstall Support All makefiles contains install and uninstall rules which install or remove the corresponding software. These rules must use the $(BUILDROOT) variable as a prefix to any installation directory so that PAPPL can be installed in a temporary location for packaging by programs like `rpmbuild`. The `$(RANLIB)` command must be run on any static libraries after installation since the symbol table is invalidated when the library is copied on some platforms. pappl-1.4.9/EMBEDDED.md000066400000000000000000000040431476704353100143270ustar00rootroot00000000000000Using PAPPL on Embedded Linux ============================= PAPPL has been developed for use on embedded Linux as well as traditional desktop/server environments. Yocto Recipe ------------ The [recipes-pappl](https://github.com/michaelrsweet/recipes-pappl) project provides a Yocto recipe for the current stable release of PAPPL. You can add it to your meta layer with: ``` git submodule add https://github.com/michaelrsweet/recipes-pappl.git ``` USB Printer Gadget Kernel Patch ------------------------------- Until Linux kernel 5.12, there is a bug in the USB printer gadget functional driver (the one that uses configfs) that can prevent the gadget from working due to a lack of buffers with the default configuration. Since udev is so helpful in keeping kernel drivers loaded, it can become impossible to unload the `f_printer` module in order to get a new configuration of the `q_len` parameter applied. The following kernel patch applies cleanly to 4.19 through 5.11, was submitted to (and approved by) the Linux USB kernel developers, and is included in Linux kernel 5.12 and later. You'll need to use this patch if you want to use PAPPL to provide a USB printer interface to your project with an version of Linux kernel prior to 5.12. ``` diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 9c7ed2539ff7..4f3161005e4f 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -50,6 +50,8 @@ #define GET_PORT_STATUS 1 #define SOFT_RESET 2 +#define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */ + static int major, minors; static struct class *usb_gadget_class; static DEFINE_IDA(printer_ida); @@ -1317,6 +1319,9 @@ static struct usb_function_instance *gprinter_alloc_inst(void) opts->func_inst.free_func_inst = gprinter_free_inst; ret = &opts->func_inst; + /* Make sure q_len is initialized, otherwise the bound device can't support read/write! */ + opts->q_len = DEFAULT_Q_LEN; + mutex_lock(&printer_ida_lock); if (ida_is_empty(&printer_ida)) { ``` pappl-1.4.9/LICENSE000066400000000000000000000261361476704353100136700ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. pappl-1.4.9/Makedefs.in000066400000000000000000000031201476704353100147160ustar00rootroot00000000000000# # Make definitions for the Printer Application Framework # # Copyright © 2019-2022 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # # Be silent... .SILENT: # Version numbers... PAPPL_VERSION = @PAPPL_VERSION@ PAPPL_VERSION_MAJOR = @PAPPL_VERSION_MAJOR@ PAPPL_VERSION_MINOR = @PAPPL_VERSION_MINOR@ # Programs and options... AR = @AR@ ARFLAGS = @ARFLAGS@ CC = @CC@ CFLAGS = @CFLAGS@ $(CPPFLAGS) $(OPTIM) $(WARNINGS) CODE_SIGN = @CODE_SIGN@ CODESIGN_IDENTITY = - CPPFLAGS = -I.. @CPPFLAGS@ CSFLAGS = -s "$(CODESIGN_IDENTITY)" @CSFLAGS@ --timestamp DSOFLAGS = @DSOFLAGS@ $(CFLAGS) INSTALL = @INSTALL@ LDFLAGS = @LDFLAGS@ $(OPTIM) LIBS = @LIBS@ LN = @LN@ MKDIR = @MKDIR@ -p OPTIM = @OPTIM@ RANLIB = @RANLIB@ RM = @RM@ -f RMDIR = @RMDIR@ SHELL = /bin/sh SYSTEM_STATUS = @SYSTEM_STATUS@ WARNINGS = @WARNINGS@ # Targets LIBPAPPL = @LIBPAPPL@ LIBPAPPL_STATIC = @LIBPAPPL_STATIC@ # Directories... bindir = @bindir@ datadir = @datadir@ datarootdir = @datarootdir@ exec_prefix = @exec_prefix@ includedir = @includedir@ infodir = @infodir@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ top_srcdir = @top_srcdir@ BUILDROOT = $(DSTROOT)$(RPM_BUILD_ROOT)$(DESTDIR) # Build commands... .SUFFIXES: .c .h .m .o .c.o: echo Compiling $<... $(CC) $(CFLAGS) -c -o $@ $< .m.o: echo Compiling $<... $(CC) $(CFLAGS) -c -o $@ $< pappl-1.4.9/Makefile000066400000000000000000000026331476704353100143170ustar00rootroot00000000000000# # Top-level makefile for the Printer Application Framework # # Copyright © 2020-2022 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # include Makedefs # Source directories... DIRS = \ doc \ man \ pappl \ testsuite # Make all targets... all: echo Using CC="$(CC)" echo Using CFLAGS="$(CFLAGS)" echo Using DSOFLAGS="$(DSOFLAGS)" echo Using LDFLAGS="$(LDFLAGS)" echo Using LIBS="$(LIBS)" for dir in $(DIRS); do \ echo Making all in $$dir...; \ (cd $$dir; $(MAKE) $(MFLAGS) all) || exit 1; \ done # Remove object and target files... clean: $(RM) testpappl.state for dir in $(DIRS); do \ echo Cleaning all in $$dir...; \ (cd $$dir; $(MAKE) $(MFLAGS) clean) || exit 1; \ done # Remove all non-distribution files... distclean: clean $(RM) Makedefs config.h config.log config.status pappl/pappl.pc -$(RM) -r autom4te*.cache # Make dependencies depend: for dir in $(DIRS); do \ echo Updating dependencies in $$dir...; \ (cd $$dir; $(MAKE) $(MFLAGS) depend) || exit 1; \ done # Install everything... install: for dir in $(DIRS); do \ echo Installing in $$dir...; \ (cd $$dir; $(MAKE) $(MFLAGS) install) || exit 1; \ done # Test everything... test: for dir in $(DIRS); do \ echo Testing in $$dir...; \ (cd $$dir; $(MAKE) $(MFLAGS) test) || exit 1; \ done # Don't run top-level build targets in parallel... .NOTPARALLEL: pappl-1.4.9/NOTICE000066400000000000000000000021111476704353100135520ustar00rootroot00000000000000PAPPL - Printer Application Library Copyright © 2020-2025 by Michael R Sweet. Copyright © 2007-2019 by Apple Inc. Copyright © 1997-2007 by Easy Software Products. (Optional) Exceptions to the Apache 2.0 License: ================================================ As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. pappl-1.4.9/README.md000066400000000000000000000116661476704353100141440ustar00rootroot00000000000000PAPPL - Printer Application Framework ===================================== ![Version](https://img.shields.io/github/v/release/michaelrsweet/pappl?include_prereleases) ![Apache 2.0](https://img.shields.io/github/license/michaelrsweet/pappl) ![Build](https://github.com/michaelrsweet/pappl/workflows/Build/badge.svg) [![Coverity Scan Status](https://img.shields.io/coverity/scan/22385.svg)](https://scan.coverity.com/projects/michaelrsweet-pappl) PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. It was specifically developed to support [LPrint][1] and a future [Gutenprint][2] Printer Application but is sufficiently general purpose to support any kind of printer or driver that can be used on desktops, servers, and in embedded environments. PAPPL supports JPEG, PNG, PWG Raster, Apple Raster, and "raw" printing to printers connected via USB and network (AppSocket/JetDirect) connections. PAPPL provides an embedded [IPP Everywhere™][3] service that provides access to printers locally or on your whole network. PAPPL is licensed under the Apache License Version 2.0 with an exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used freely in any project you'd like. If you want to support the development of this framework financially, please consider sponsoring me through [Github][4]. I am also available to do consulting and/or development through my company Lakeside Robotics (). PAPPL is helping to accelerate the adoption of IPP Everywhere™ and is making it easier for developers to support other IPP-based licensing programs like [AirPrint™][5] and [Mopria®][6]. Requirements ------------ PAPPL requires Microsoft® Windows® 10 or higher or a POSIX-compliant host operating system such as Linux®, macOS®, QNX®, or VxWorks®. On Windows, the provided project files require Visual Studio 2019 or higher. For POSIX hosts, a "make" utility that supports the `include` directive (like GNU make), a C99-compatible C compiler such as GCC or Clang, and the "pkg-config" utility are required along with the following support libraries: - Avahi (0.8 or later) or mDNSResponder for mDNS/DNS-SD support - CUPS (2.2 or later) or libcups (3.0 or later) for the CUPS libraries - GNU TLS (3.0 or later), LibreSSL (3.0 or later), or OpenSSL (1.1 or later) for TLS support - JPEGLIB (8 or later) or libjpeg-turbo (2.0 or later) for JPEG image support (optional for B&W printers) - LIBPNG (1.6 or later) for PNG image support (optional) - LIBPAM for authentication support (optional) - LIBUSB (1.0 or later) for USB printing support (optional) - PAM for authentication support (optional) - ZLIB (1.1 or later) for compression support Most development happens on Intel and Apple Silicon Macs, with testing on various Linux distributions, Windows 10+, and a [Raspberry Pi Zero W][7] to ensure that memory and CPU requirements remain low. Documentation and Examples -------------------------- Documentation can be found in the "doc" and "man" directories. The OpenPrinting group has [written a tutorial][8] showing how to migrate the `rastertohp` driver from CUPS to a Printer Application using PAPPL, which can be used as a recipe for migrating any CUPS driver. This example is available in the [hp-printer-app][9] project and is also discussed in the PAPPL documentation. The OpenPrinting group has also developed a [PostScript printer application][10] using PAPPL to support the many otherwise unsupported PostScript and Ghostscript-based printers. Contributing Code and Translations ---------------------------------- Code contributions should be submitted as pull requests on the Github site: http://github.com/michaelrsweet/pappl/pulls See the file "CONTRIBUTING.md" for more details. PAPPL uses [Weblate][11] to manage the localization of the web interface and IPP attributes and values shared by all printer applications, and those likewise end up as pull requests on Github. Legal Stuff ----------- PAPPL is Copyright © 2019-2025 by Michael R Sweet. This software is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS). See the files "LICENSE" and "NOTICE" for more information. This software is based loosely on the "ippeveprinter.c" code from [CUPS][12]. [1]: https://github.com/michaelrsweet/lprint [2]: http://gutenprint.sf.net/ [3]: https://www.pwg.org/ipp/everywhere.html [4]: https://github.com/sponsors/michaelrsweet [5]: https://support.apple.com/en-us/HT201311 [6]: https://mopria.org/ [7]: https://www.raspberrypi.org/products/raspberry-pi-zero-w/ [8]: https://openprinting.github.io/documentation/02-designing-printer-drivers/ [9]: https://github.com/michaelrsweet/hp-printer-app [10]: https://github.com/openprinting/ps-printer-app [11]: https://hosted.weblate.org [12]: https://openprinting.github.io/cups pappl-1.4.9/SECURITY.md000066400000000000000000000134041476704353100144460ustar00rootroot00000000000000Security Policy =============== This file describes how security issues are reported and handled, and what the expectations are for security issues reported to this project. Reporting a Security Bug ------------------------ For the purposes of this project, a security bug is a software defect that allows a *local or remote user* to gain unauthorized access or privileges on the host computer or to cause the software to crash. Such defects should be reported to the project security advisory page at . Alternately, security bugs can be reported to "security AT msweet.org" using the PGP public key below. Expect a response within 5 business days. Any proposed embargo date should be at least 30 days and no more than 90 days in the future. > *Note:* If you've found a software defect that allows a *program* to gain > unauthorized access or privileges on the host computer or causes the program > to crash, that defect should be reported as an ordinary project issue at > . Responsible Disclosure ---------------------- With *responsible disclosure*, a security issue (and its fix) is disclosed only after a mutually-agreed period of time (the "embargo date"). The issue and fix are shared amongst and reviewed by the key stakeholders (Linux distributions, OS vendors, etc.) and the CERT/CC. Fixes are released to the public on the agreed-upon date. > Responsible disclosure applies only to production releases. A security > vulnerability that only affects unreleased code can be fixed immediately > without coordination. Vendors *should not* package and release unstable > snapshots, beta releases, or release candidates of this software. Supported Versions ------------------ All production releases of this software are subject to this security policy. A production release is tagged and given a semantic version number of the form: MAJOR.MINOR.PATCH where "MAJOR" is an integer starting at 1 and "MINOR" and "PATCH" are integers starting at 0. A feature release has a "PATCH" value of 0, for example: 1.0.0 1.1.0 2.0.0 Beta releases and release candidates are *not* production releases and use semantic version numbers of the form: MAJOR.MINORbNUMBER MAJOR.MINORrcNUMBER where "MAJOR" and "MINOR" identify the new feature release version number and "NUMBER" identifies a beta or release candidate number starting at 1, for example: 1.0b1 1.0b2 1.0rc1 PGP Public Key -------------- The following PGP public key can be used for signing security messages. ``` -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: GPGTools - https://gpgtools.org mQINBF6L0RgBEAC8FTqc/1Al+pWW+ULE0OB2qdbiA2NBjEm0X0WhvpjkqihS1Oih ij3fzFxKJ+DgutQyDb4QFD8tCFL0f0rtNL1Iz8TtiAJjvlhL4kG5cdq5HYEchO10 qFeZ1DqvnHXB4pbKouEQ7Q/FqB1PG+m6y2q1ntgW+VPKm/nFUWBCmhTQicY3FOEG q9r90enc8vhQGOX4p01KR0+izI/g+97pWgMMj5N4zHuXV/GrPhlVgo3Wn1OfEuX4 9vmv7GX4G17Me3E3LOo0c6fmPHJsrRG5oifLpvEJXVZW/RhJR3/pKMPSI5gW8Sal lKAkNeV7aZG3U0DCiIVL6E4FrqXP4PPj1KBixtxOHqzQW8EJwuqbszNN3vp9w6jM GvGtl8w5Qrw/BwnGC6Dmw+Qv04p9JRY2lygzZYcKuwZbLzBdC2CYy7P2shoKiymX ARv+i+bUl6OmtDe2aYaqRkNDgJkpuVInBlMHwOyLP6fN2o7ETXQZ+0a1vQsgjmD+ Mngkc44HRnzsIJ3Ga4WwW8ggnAwUzJ/DgJFYOSbRUF/djBT4/EFoU+/kjXRqq8/d c8HjZtz2L27njmMw68/bYmY1TliLp50PXGzJA/KeY90stwKtTI0ufwAyi9i9BaYq cGbdq5jnfSNMDdKW2kLCNTQeUWSSytMTsdU0Av3Jrv5KQF8x5GaXcpCOTwARAQAB tExNaWNoYWVsIFN3ZWV0IChzZWN1cml0eUBtc3dlZXQub3JnKSAoU2VjdXJpdHkg UEdQIEtleSkgPHNlY3VyaXR5QG1zd2VldC5vcmc+iQJUBBMBCgA+FiEEOElfSXYU h91AF0sBpZiItz2feQIFAl6L0RgCGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQAC HgECF4AACgkQpZiItz2feQIhjhAAqZHuQJkPBsAKUvJtPiyunpR6JENTUIDxnVXG nue+Zev+B7PzQ7C4CAx7vXwuWTt/BXoyQFKRUrm+YGiBTvLYQ8fPqudDnycSaf/A n01Ushdlhyg1wmCBGHTgt29IkEZphNj6BebRd675RTOSD5y14jrqUb+gxRNuNDa5 ZiZBlBE4A8TV6nvlCyLP5oXyTvKQRFCh4dEiL5ZvpoxnhNvJpSe1ohL8iJ9aeAd5 JdakOKi8MmidRPYC5IldXwduW7VC7dtqSiPqT5aSN0GJ8nIhSpn/ZkOEAPHAtxxa 0VgjltXwUDktu74MUUghdg2vC1df2Z+PqHLsGEqOmxoBIJYXroIqSEpO3Ma7hz0r Xg1AWHMR/xxiLXLxgaZRvTp7AlaNjbqww8JDG8g+nDIeGsgIwWN/6uPczledvDQa HtlMfN97i+rt6sCu13UMZHpBKOGg7eAGRhgpOwpUqmlW1b+ojRHGkmZ8oJSE7sFT gzSGNkmfVgA1ILl0mi8OBVZ4jlUg6EgVsiPlzolH92iscK7g50PdjzpQe0m3gmcL dpOmSL8Fti05dPfamJzIvJd28kMZ6yMnACKj9rq/VpfgYBLK8dbNUjEOQ2oq7PyR Ye/LE1OmAJwfZQkyQNI8yAFXoRJ8u3/bRb3SPvGGWquGBDKHv2K1XiCW65uyLe5B RNJWmme5Ag0EXovRGAEQAJZMFeIMt/ocLskrp89ZyBTTiavFKn9+QW7C2Mb36A73 J2g9vRFBSRizb+t8lSzP/T1GbKS0cEmfEpQppWImTbOMV6ZgxrM0IUy1Yd7Kyc0K oNMZvykRYwVMzxB5hiQ88kCLfqTNCveIvu1xcB9pWkf+cuDmGCxA3I+yc3Eh/SOP urDsHObt7fyEmJpSxCXlMFHRCuWyGXhMNvhR186t9mANW0PyxKJ8efr+2Vhm1+pA Vk9JESac/lREvx9PVFmlPdqgqRkQ0TQB5+ROo9Wy77cxQr5+rvSZZff630I1YgZf Ph6xOV1/q6vJ3RBNA2nPSTjPeeWQ7pTn7PZGJwCjIUjhMbO+EJVKUJNOAEg033mG tLfbFUYdhA/dRgFuKz90loCMfsnf3e4o/TFydSHUuwBUtOWkL1BBWEbk95M/Zr00 w5fD9knas1u5Lc4ogXzTFPnvJ6hM1RAFJEd+FYzJZIvzwrIx4Ag1DOKViVBpeLTu HWj+xckEgvxEBglplALzfSIJ0CLQSNL8iMFbzCnPeUoQfPkqu37KHrB9syAA06Tb qw1Ax0qBqKInGIgBd0w6dFLF3s04xVcPAXWyJ0w4I7h2bs+aD6YwwK6xxCtXxtN5 Q1LQM8s3tKNXER3mZ8zfwgwjsdLVwhXhysFi6Dlkvk/Vrbn1QDfJnzq+F9LsGRGb ABEBAAGJAjwEGAEKACYWIQQ4SV9JdhSH3UAXSwGlmIi3PZ95AgUCXovRGAIbDAUJ B4YfgAAKCRClmIi3PZ95AhDZD/40fShzDS/smZZL0oXN4GgZ62FrXWBdLjontkXo d8hDh1wJZwqsLVbtO2Gu0CPeH9GclQ3bYsR19sGMM4FDgjMu57O/TU6GZl2Ywcjh ayhRTHyAq/BKZn71AM0N7LS8MdNTaLbTbzEu5oGbAmOVv5f0SUnQoGxbeF8ih5bo hR3ZcORujWMgnymL3+cerNyIDQAtfMAUTfpVcwem4CvquA9Wjtur8YN1t+N7I3o2 eMTNSyNUL9Yx3NxbyJ0yrrMvASo+ZVRaPW5+ET9Iqd68ILSY04Gnar3URJssggX8 +cuyEbP9bAG8qYqcr2aSC2dW84mL/RnZGR//1dfS0Ugk6Osj0LSF5i+mz0CbIjYQ PKgLlgpycuGZBC5kG3RWWfanM0HxPDx10a7vEWA1A5Q+csx4yi3CW/giC1zAdhUO cJ1l4Uj/oxpGeLN7BnT/2NzU/px2fpbaG+xU4HlwjzFM2cIOUIohHFhdvFZbFIIA mePqTBnEB3HtXYRTgMoYDXLWhlOXjyVnMR45WDfvEA3KqbAz6sNMtaOJ6rHBWnR1 1YbpvDWUeaGSLXBoGyo3RgTrN9jON8lE/oUxFobnEdfZGD+uwIniylc5rw3+VkBU +QGZDfgPgxjSmKsWq1cK6rNfBacGYrdyqf90VemEsvR8r0Ump0RPzBMlAAq0Xkup WkiKlA== =0GzT -----END PGP PUBLIC KEY BLOCK----- ``` pappl-1.4.9/config.guess000077500000000000000000001414221476704353100151770ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-09-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case $UNAME_VERSION in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-pc-managarm-mlibc" ;; *:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __i386__ ABI=x86 #else #ifdef __ILP32__ ABI=x32 #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in x86) CPU=i686 ;; x32) LIBCABI=${LIBC}x32 ;; esac fi GUESS=$CPU-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; ppc:Haiku:*:*) # Haiku running on Apple PowerPC GUESS=powerpc-apple-haiku ;; *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "${cputype-}" = 386; then UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pappl-1.4.9/config.h.in000066400000000000000000000021271476704353100147000ustar00rootroot00000000000000// // Configuration header file for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Version numbers #define PAPPL_VERSION "" #define PAPPL_VERSION_MAJOR 0 #define PAPPL_VERSION_MINOR 0 // Location of PAPPL state and spool data (when run as root) #define PAPPL_STATEDIR "/usr/local/var" // Location of PAPPL domain socket (when run as root) #define PAPPL_SOCKDIR "/usr/local/var/run" // Location of CUPS config files #define CUPS_SERVERROOT "/etc/cups" // DNS-SD (mDNSResponder or Avahi) #undef HAVE_DNSSD #undef HAVE_MDNSRESPONDER #undef HAVE_AVAHI // GNU TLS, LibreSSL/OpenSSL #undef HAVE_GNUTLS #undef HAVE_OPENSSL // libjpeg #undef HAVE_LIBJPEG // libpng #undef HAVE_LIBPNG // libusb #undef HAVE_LIBUSB // libpam #undef HAVE_LIBPAM #undef HAVE_SECURITY_PAM_APPL_H #undef HAVE_PAM_PAM_APPL_H // String functions #undef HAVE_STRLCPY // Random number support #undef HAVE_SYS_RANDOM_H #undef HAVE_ARC4RANDOM #undef HAVE_GETRANDOM #undef HAVE_GNUTLS_RND pappl-1.4.9/config.sub000077500000000000000000001057531476704353100146510ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-09-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) ;; uclinux-uclibc* ) ;; managarm-mlibc* | managarm-kernel* ) ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; -kernel* ) echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 exit 1 ;; *-kernel* ) echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: pappl-1.4.9/configure000077500000000000000000005477321476704353100146040ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for pappl 1.4.9. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: https://github.com/michaelrsweet/pappl/issues about $0: your system, including any error possibly output before $0: this message. Then install a modern shell, or manually $0: run the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pappl' PACKAGE_TARNAME='pappl' PACKAGE_VERSION='1.4.9' PACKAGE_STRING='pappl 1.4.9' PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pappl/issues' PACKAGE_URL='https://www.msweet.org/pappl' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS LIBOBJS WARNINGS CSFLAGS LIBPAPPL_STATIC LIBPAPPL SYSTEM_STATUS PKGCONFIG_LIBUSB PKGCONFIG_LIBPNG PKGCONFIG_LIBJPEG PKGCONFIG_TLS PKGCONFIG_AVAHI CUPSCONFIG PKGCONFIG_REQUIRES PKGCONFIG_LIBS_PRIVATE PKGCONFIG_LIBS PKGCONFIG_CFLAGS PKGCONFIG INSTALL ARFLAGS LN RMDIR RM MKDIR CODE_SIGN AR RANLIB OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC OPTIM DSOFLAGS host_os host_vendor host_cpu host build_os build_vendor build_cpu build PAPPL_VERSION_MINOR PAPPL_VERSION_MAJOR PAPPL_VERSION target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_dnssd with_tls enable_libjpeg enable_libpng enable_libusb enable_libpam enable_static enable_shared enable_debug enable_debug_printfs enable_maintainer enable_sanitizer enable_tsanitizer with_dsoflags with_ldflags with_papplstatedir with_papplsockdir ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures pappl 1.4.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/pappl] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of pappl 1.4.9:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-libjpeg use libjpeg for JPEG printing, default=auto --enable-libpng use libpng for PNG printing, default=auto --enable-libusb use libusb for USB printing, default=auto --enable-libpam use libpam for authentication, default=auto --disable-static do not install static library --disable-shared do not install shared library --enable-debug turn on debugging, default=no --enable-debug-printfs turn on debug messages, default=no --enable-maintainer turn on maintainer mode, default=no --enable-sanitizer build with AddressSanitizer, default=no --enable-tsanitizer build with ThreadSanitizer, default=no Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-dnssd=LIBRARY set DNS-SD library (auto, avahi, mdnsresponder) --with-tls=... use gnutls or openssl/libressl for TLS support --with-dsoflags=... Specify additional DSOFLAGS --with-ldflags=... Specify additional LDFLAGS --with-papplstatedir specify default location of printer application state and spool files (default=LOCALSTATEDIR) --with-papplsockdir specify default location of printer application domain sockets (default=/run or /private/var/run) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . pappl home page: . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF pappl configure 1.4.9 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by pappl $as_me 1.4.9, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Auxiliary files required by this configure script. ac_aux_files="config.guess config.sub" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" PAPPL_VERSION="1.4.9" PAPPL_VERSION_MAJOR="`echo 1.4.9 | awk -F. '{print $1}'`" PAPPL_VERSION_MINOR="`echo 1.4.9 | awk -F. '{printf("%d\n",$2);}'`" printf "%s\n" "#define PAPPL_VERSION \"$PAPPL_VERSION\"" >>confdefs.h printf "%s\n" "#define PAPPL_VERSION_MAJOR $PAPPL_VERSION_MAJOR" >>confdefs.h printf "%s\n" "#define PAPPL_VERSION_MINOR $PAPPL_VERSION_MINOR" >>confdefs.h # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac host_os_name="$(echo $host_os | sed -e '1,$s/[0-9.]*$//g')" host_os_version="$(echo $host_os | sed -e '1,$s/^[^0-9.]*//g' | awk -F. '{print $1 $2}')" # Linux often does not yield an OS version we can use... if test "x$host_os_version" = x then : host_os_version="0" fi CFLAGS="${CFLAGS:=}" CPPFLAGS="${CPPFLAGS:=}" DSOFLAGS="${DSOFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LIBS:=}" OPTIM="${OPTIM:=}" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_AR+y} then : printf %s "(cached) " >&6 else $as_nop case $AR in [\\/]* | ?:[\\/]*) ac_cv_path_AR="$AR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_AR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AR=$ac_cv_path_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi for ac_prog in codesign true do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_CODE_SIGN+y} then : printf %s "(cached) " >&6 else $as_nop case $CODE_SIGN in [\\/]* | ?:[\\/]*) ac_cv_path_CODE_SIGN="$CODE_SIGN" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_CODE_SIGN="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CODE_SIGN=$ac_cv_path_CODE_SIGN if test -n "$CODE_SIGN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CODE_SIGN" >&5 printf "%s\n" "$CODE_SIGN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CODE_SIGN" && break done # Extract the first word of "mkdir", so it can be a program name with args. set dummy mkdir; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MKDIR+y} then : printf %s "(cached) " >&6 else $as_nop case $MKDIR in [\\/]* | ?:[\\/]*) ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_MKDIR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MKDIR=$ac_cv_path_MKDIR if test -n "$MKDIR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5 printf "%s\n" "$MKDIR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "rm", so it can be a program name with args. set dummy rm; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_RM+y} then : printf %s "(cached) " >&6 else $as_nop case $RM in [\\/]* | ?:[\\/]*) ac_cv_path_RM="$RM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_RM="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RM=$ac_cv_path_RM if test -n "$RM"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 printf "%s\n" "$RM" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "rmdir", so it can be a program name with args. set dummy rmdir; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_RMDIR+y} then : printf %s "(cached) " >&6 else $as_nop case $RMDIR in [\\/]* | ?:[\\/]*) ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_RMDIR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RMDIR=$ac_cv_path_RMDIR if test -n "$RMDIR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RMDIR" >&5 printf "%s\n" "$RMDIR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "ln", so it can be a program name with args. set dummy ln; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_LN+y} then : printf %s "(cached) " >&6 else $as_nop case $LN in [\\/]* | ?:[\\/]*) ac_cv_path_LN="$LN" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_LN="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LN=$ac_cv_path_LN if test -n "$LN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LN" >&5 printf "%s\n" "$LN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "$ac_cv_prog_ranlib" = ":" then : ARFLAGS="crs" else $as_nop ARFLAGS="cr" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for install-sh script" >&5 printf %s "checking for install-sh script... " >&6; } INSTALL="$(pwd)/install-sh" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using $INSTALL" >&5 printf "%s\n" "using $INSTALL" >&6; } if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKGCONFIG=$ac_cv_path_PKGCONFIG if test -n "$PKGCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 printf "%s\n" "$PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKGCONFIG"; then ac_pt_PKGCONFIG=$PKGCONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG if test -n "$ac_pt_PKGCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 printf "%s\n" "$ac_pt_PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKGCONFIG" = x; then PKGCONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKGCONFIG=$ac_pt_PKGCONFIG fi else PKGCONFIG="$ac_cv_path_PKGCONFIG" fi PKGCONFIG_CFLAGS="-I\${includedir}" PKGCONFIG_LIBS="-L\${libdir} -lpappl" PKGCONFIG_LIBS_PRIVATE="-lm" PKGCONFIG_REQUIRES="" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cups-config", so it can be a program name with args. set dummy ${ac_tool_prefix}cups-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_CUPSCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $CUPSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_CUPSCONFIG="$CUPSCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_CUPSCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CUPSCONFIG=$ac_cv_path_CUPSCONFIG if test -n "$CUPSCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CUPSCONFIG" >&5 printf "%s\n" "$CUPSCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_CUPSCONFIG"; then ac_pt_CUPSCONFIG=$CUPSCONFIG # Extract the first word of "cups-config", so it can be a program name with args. set dummy cups-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_CUPSCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_CUPSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_CUPSCONFIG="$ac_pt_CUPSCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_CUPSCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_CUPSCONFIG=$ac_cv_path_ac_pt_CUPSCONFIG if test -n "$ac_pt_CUPSCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CUPSCONFIG" >&5 printf "%s\n" "$ac_pt_CUPSCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_CUPSCONFIG" = x; then CUPSCONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CUPSCONFIG=$ac_pt_CUPSCONFIG fi else CUPSCONFIG="$ac_cv_path_CUPSCONFIG" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CUPS library v2.2 or higher" >&5 printf %s "checking for CUPS library v2.2 or higher... " >&6; } if $PKGCONFIG --exists cups3 then : CUPS_VERSION="$($PKGCONFIG --modversion cups3)" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, v$CUPS_VERSION" >&5 printf "%s\n" "yes, v$CUPS_VERSION" >&6; } CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags cups3)" LIBS="$LIBS $($PKGCONFIG --libs cups3)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($PKGCONFIG --cflags cups3)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($PKGCONFIG --libs cups3)" if test x$host_os_name = xdarwin then : CUPS_SERVERROOT="/private/etc/cups" else $as_nop if test "x$($PKGCONFIG --variable=prefix cups3)" = x/usr then : CUPS_SERVERROOT="/etc/cups" else $as_nop CUPS_SERVERROOT="$($PKGCONFIG --variable=prefix cups3)/etc/cups" fi fi elif $PKGCONFIG --exists cups then : CUPS_VERSION="$($PKGCONFIG --modversion cups)" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, v$CUPS_VERSION" >&5 printf "%s\n" "yes, v$CUPS_VERSION" >&6; } CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags cups)" LIBS="$LIBS $($PKGCONFIG --libs cups)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($PKGCONFIG --cflags cups)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($PKGCONFIG --libs cups)" CUPS_SERVERROOT="$($PKGCONFIG --variable=cups_serverroot cups)" if test "x$CUPS_SERVERROOT" = x then : if test x$host_os_name = xdarwin then : CUPS_SERVERROOT="/private/etc/cups" else $as_nop if test "x$($PKGCONFIG --variable=prefix cups)" = x/usr then : CUPS_SERVERROOT="/etc/cups" else $as_nop CUPS_SERVERROOT="$($PKGCONFIG --variable=prefix cups)/etc/cups" fi fi fi else $as_nop if test "x$CUPSCONFIG" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "Sorry, this software requires libcups-dev." "$LINENO" 5 fi CUPS_VERSION="$($CUPSCONFIG --api-version)" case "$CUPS_VERSION" in #( 1.* | 2.0 | 2.1) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "Sorry, you need CUPS 2.2.0 or higher." "$LINENO" 5 ;; #( *) : ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, v$CUPS_VERSION" >&5 printf "%s\n" "yes, v$CUPS_VERSION" >&6; } CPPFLAGS="$CPPFLAGS $($CUPSCONFIG --cflags)" DSOFLAGS="$DSOFLAGS $($CUPSCONFIG --ldflags)" LDFLAGS="$LDFLAGS $($CUPSCONFIG --ldflags)" LIBS="$LIBS $($CUPSCONFIG --image --libs)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($CUPSCONFIG --cflags)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($CUPSCONFIG --image --libs)" CUPS_SERVERROOT="$($CUPSCONFIG --serverroot)" fi printf "%s\n" "#define CUPS_SERVERROOT \"$CUPS_SERVERROOT\"" >>confdefs.h ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes then : printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h fi ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes then : fi if test x$ac_cv_header_pthread_h != xyes then : as_fn_error $? "Sorry, this software requires POSIX threading support." "$LINENO" 5 fi for flag in -lpthreads -lpthread -pthread; do { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create using $flag" >&5 printf %s "checking for pthread_create using $flag... " >&6; } SAVELIBS="$LIBS" LIBS="$flag $LIBS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_create(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : have_pthread=yes PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $flag" else $as_nop LIBS="$SAVELIBS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test x$have_pthread = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -D_REENTRANT" break else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi done # Check whether --with-dnssd was given. if test ${with_dnssd+y} then : withval=$with_dnssd; fi PKGCONFIG_AVAHI="" if test "x$with_dnssd" != xmdnsresponder -a "x$with_dnssd" != xno -a "x$PKGCONFIG" != x -a x$host_os_name != xdarwin then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Avahi" >&5 printf %s "checking for Avahi... " >&6; } if $PKGCONFIG --exists avahi-client then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags avahi-client)" LIBS="$LIBS $($PKGCONFIG --libs avahi-client)" PKGCONFIG_AVAHI="avahi-client" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs avahi-client)" printf "%s\n" "#define HAVE_DNSSD 1" >>confdefs.h printf "%s\n" "#define HAVE_AVAHI 1" >>confdefs.h else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test x$with_dnssd = xavahi then : as_fn_error $? "libavahi-client-dev needed for --with-dnssd=avahi." "$LINENO" 5 fi fi elif test x$with_dnssd = xavahi then : as_fn_error $? "pkgconfig and libavahi-client-dev needed for --with-dnssd=avahi." "$LINENO" 5 elif test x$with_dnssd != xavahi -a "x$with_dnssd" != xno then : ac_fn_c_check_header_compile "$LINENO" "dns_sd.h" "ac_cv_header_dns_sd_h" "$ac_includes_default" if test "x$ac_cv_header_dns_sd_h" = xyes then : case "$host_os_name" in #( darwin*) : # Darwin and macOS... printf "%s\n" "#define HAVE_DNSSD 1" >>confdefs.h printf "%s\n" "#define HAVE_MDNSRESPONDER 1" >>confdefs.h LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework CoreFoundation -framework SystemConfiguration" ;; #( *) : # All others... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for current version of dns_sd library" >&5 printf %s "checking for current version of dns_sd library... " >&6; } SAVELIBS="$LIBS" LIBS="$LIBS -ldns_sd" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int constant = kDNSServiceFlagsShareConnection; unsigned char txtRecord[100]; uint8_t valueLen; TXTRecordGetValuePtr(sizeof(txtRecord), txtRecord, "value", &valueLen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_DNSSD 1" >>confdefs.h printf "%s\n" "#define HAVE_MDNSRESPONDER 1" >>confdefs.h PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -ldns_sd" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } LIBS="$SAVELIBS" if test x$with_dnssd = xmdnsresponder then : as_fn_error $? "mDNSResponder required for --with-dnssd=mdnsresponder." "$LINENO" 5 fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; #( *) : ;; esac fi fi PKGCONFIG_TLS="" # Check whether --with-tls was given. if test ${with_tls+y} then : withval=$with_tls; fi if test "x$with_tls" = x then : with_tls="yes" elif test "$with_tls" != gnutls -a "$with_tls" != libressl -a "$with_tls" != openssl -a "$with_tls" != yes then : as_fn_error $? "Unsupported --with-tls value \"$with_tls\" specified." "$LINENO" 5 fi have_tls="0" if test $with_tls = yes -o $with_tls = libressl -o $with_tls = openssl then : if test "x$PKGCONFIG" != x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL/LibreSSL package" >&5 printf %s "checking for OpenSSL/LibreSSL package... " >&6; } if $PKGCONFIG --exists openssl then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } have_tls="1" printf "%s\n" "#define HAVE_OPENSSL 1" >>confdefs.h CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags openssl)" LIBS="$LIBS $($PKGCONFIG --libs openssl)" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs openssl)" PKGCONFIG_TLS="openssl," else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test $have_tls = 0 then : if test $with_tls = yes -o $with_tls = gnutls then : if test "x$PKGCONFIG" != x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU TLS package" >&5 printf %s "checking for GNU TLS package... " >&6; } if $PKGCONFIG --exists gnutls then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } have_tls="1" printf "%s\n" "#define HAVE_GNUTLS 1" >>confdefs.h CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags gnutls`" LIBS="$LIBS `$PKGCONFIG --libs gnutls`" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs gnutls)" PKGCONFIG_TLS="gnutls >= 3.0," else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi fi if test $have_tls = 0 then : as_fn_error $? "TLS support is required." "$LINENO" 5 fi ac_fn_c_check_header_compile "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default" if test "x$ac_cv_header_sys_random_h" = xyes then : printf "%s\n" "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" if test "x$ac_cv_func_arc4random" = xyes then : printf "%s\n" "#define HAVE_ARC4RANDOM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getrandom" "ac_cv_func_getrandom" if test "x$ac_cv_func_getrandom" = xyes then : printf "%s\n" "#define HAVE_GETRANDOM 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "gnutls_rnd" "ac_cv_func_gnutls_rnd" if test "x$ac_cv_func_gnutls_rnd" = xyes then : printf "%s\n" "#define HAVE_GNUTLS_RND 1" >>confdefs.h fi # Check whether --enable-libjpeg was given. if test ${enable_libjpeg+y} then : enableval=$enable_libjpeg; fi PKGCONFIG_LIBJPEG="" if test x$enable_libjpeg != xno then : have_jpeg=no if test "x$PKGCONFIG" != x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libjpeg via pkg-config" >&5 printf %s "checking for libjpeg via pkg-config... " >&6; } if $PKGCONFIG --exists libjpeg then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; }; printf "%s\n" "#define HAVE_LIBJPEG 1" >>confdefs.h CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libjpeg`" LIBS="$LIBS `$PKGCONFIG --libs libjpeg`" PKGCONFIG_LIBJPEG="libjpeg," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libjpeg)" have_jpeg=yes else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; }; fi fi if test $have_jpeg = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing jpeg_start_decompress" >&5 printf %s "checking for library containing jpeg_start_decompress... " >&6; } if test ${ac_cv_search_jpeg_start_decompress+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char jpeg_start_decompress (); int main (void) { return jpeg_start_decompress (); ; return 0; } _ACEOF for ac_lib in '' turbojpeg jpeg do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_jpeg_start_decompress=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_jpeg_start_decompress+y} then : break fi done if test ${ac_cv_search_jpeg_start_decompress+y} then : else $as_nop ac_cv_search_jpeg_start_decompress=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_jpeg_start_decompress" >&5 printf "%s\n" "$ac_cv_search_jpeg_start_decompress" >&6; } ac_res=$ac_cv_search_jpeg_start_decompress if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" printf "%s\n" "#define HAVE_LIBJPEG 1" >>confdefs.h PKGCONFIG_LIB_PRIVATE="$PKGCONFIG_LIB_PRIVATE -l$ac_cv_search_jpeg_start_decompress" have_jpeg=yes fi fi if test x$enable_libjpeg = xyes -a $have_jpeg = no then : as_fn_error $? "libjpeg-dev 8 or later required for --enable-libjpeg." "$LINENO" 5 fi fi # Check whether --enable-libpng was given. if test ${enable_libpng+y} then : enableval=$enable_libpng; fi PKGCONFIG_LIBPNG="" if test "x$PKGCONFIG" != x -a x$enable_libpng != xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libpng-1.6.x" >&5 printf %s "checking for libpng-1.6.x... " >&6; } if $PKGCONFIG --exists libpng16 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; }; printf "%s\n" "#define HAVE_LIBPNG 1" >>confdefs.h CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libpng16`" LIBS="$LIBS `$PKGCONFIG --libs libpng16` -lz" PKGCONFIG_LIBPNG="libpng >= 1.6," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libpng16)" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; }; if test x$enable_libpng = xyes then : as_fn_error $? "libpng-dev 1.6 or later required for --enable-libpng." "$LINENO" 5 fi fi elif test x$enable_libpng = xyes then : as_fn_error $? "libpng-dev 1.6 or later required for --enable-libpng." "$LINENO" 5 fi # Check whether --enable-libusb was given. if test ${enable_libusb+y} then : enableval=$enable_libusb; fi PKGCONFIG_LIBUSB="" if test "x$PKGCONFIG" != x -a x$enable_libusb != xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libusb-1.0" >&5 printf %s "checking for libusb-1.0... " >&6; } if $PKGCONFIG --exists libusb-1.0 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_LIBUSB 1" >>confdefs.h CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libusb-1.0`" LIBS="$LIBS `$PKGCONFIG --libs libusb-1.0`" PKGCONFIG_LIBUSB="libusb-1.0 >= 1.0," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libusb-1.0)" if test "x$host_os_name" = xdarwin then : LIBS="$LIBS -framework IOKit" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework IOKit" fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test x$enable_libusb = xyes then : as_fn_error $? "libusb-1.0-0-dev required for --enable-libusb." "$LINENO" 5 fi fi elif test x$enable_libusb = xyes then : as_fn_error $? "pkgconfig and libusb-1.0-0-dev required for --enable-libusb." "$LINENO" 5 fi # Check whether --enable-libpam was given. if test ${enable_libpam+y} then : enableval=$enable_libpam; fi if test x$enable_libpam != xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h LIBS="-ldl $LIBS" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pam_start in -lpam" >&5 printf %s "checking for pam_start in -lpam... " >&6; } if test ${ac_cv_lib_pam_pam_start+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pam_start (); int main (void) { return pam_start (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pam_pam_start=yes else $as_nop ac_cv_lib_pam_pam_start=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_start" >&5 printf "%s\n" "$ac_cv_lib_pam_pam_start" >&6; } if test "x$ac_cv_lib_pam_pam_start" = xyes then : printf "%s\n" "#define HAVE_LIBPAM 1" >>confdefs.h LIBS="$LIBS -lpam" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -lpam" fi ac_fn_c_check_header_compile "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_security_pam_appl_h" = xyes then : printf "%s\n" "#define HAVE_SECURITY_PAM_APPL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "pam/pam_appl.h" "ac_cv_header_pam_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_pam_pam_appl_h" = xyes then : printf "%s\n" "#define HAVE_PAM_PAM_APPL_H 1" >>confdefs.h fi if test x$ac_pam_start = xno -a x$enable_libpam = xyes then : as_fn_error $? "libpam-dev required for --enable-libpam." "$LINENO" 5 fi fi if test "$host_os_name" = darwin then : LIBS="-framework AppKit $LIBS" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework AppKit" SYSTEM_STATUS="system-status-macos.o" # else $as_nop # AS_IF([$PKGCONFIG --exists gnome-desktop-3.0], [ # CPPFLAGS="$($PKGCONFIG --cflags gnome-desktop-3.0) $CPPFLAGS" # LIBS="$($PKGCONFIG --libs gnome-desktop-3.0) $LIBS" # PKGCONFIG_LIBS_PRIVATE="$($PKGCONFIG --libs gnome-desktop-3.0) $PKGCONFIG_LIBS_PRIVATE" # SYSTEM_STATUS="system-status-gnome.o" # ], [ # SYSTEM_STATUS="system-status-dummy.o" # ]) fi # Check whether --enable-static was given. if test ${enable_static+y} then : enableval=$enable_static; fi # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; fi if test x$enable_shared != xno then : if test "$host_os_name" = darwin then : LIBPAPPL="libpappl.1.dylib" else $as_nop LIBPAPPL="libpappl.so.1" fi if test x$enable_static != xno then : LIBPAPPL_STATIC="libpappl.a" else $as_nop LIBPAPPL_STATIC="" fi else $as_nop LIBPAPPL="libpappl.a" LIBPAPPL_STATIC="" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $PKGCONFIG_LIBS_PRIVATE" PKGCONFIG_LIBS_PRIVATE="" fi # Check whether --enable-debug was given. if test ${enable_debug+y} then : enableval=$enable_debug; fi # Check whether --enable-debug_printfs was given. if test ${enable_debug_printfs+y} then : enableval=$enable_debug_printfs; fi # Check whether --enable-maintainer was given. if test ${enable_maintainer+y} then : enableval=$enable_maintainer; fi # Check whether --enable-sanitizer was given. if test ${enable_sanitizer+y} then : enableval=$enable_sanitizer; fi # Check whether --enable-tsanitizer was given. if test ${enable_tsanitizer+y} then : enableval=$enable_tsanitizer; fi if test x$enable_debug = xyes then : OPTIM="$OPTIM -g" CSFLAGS="" else $as_nop OPTIM="$OPTIM -g -Os" CSFLAGS="-o runtime" fi if test x$enable_debug_printfs = xyes then : OPTIM="$OPTIM -DDEBUG" fi WARNINGS="" if test -n "$GCC" then : if test x$enable_sanitizer = xyes then : # Use -fsanitize=address with debugging... OPTIM="$OPTIM -fsanitize=address" if test x$enable_tsanitizer = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring --enable-tsanitizer since --enable-sanitizer was specified." >&5 printf "%s\n" "$as_me: WARNING: Ignoring --enable-tsanitizer since --enable-sanitizer was specified." >&2;} fi elif test x$enable_tsanitizer = xyes then : # Use -fsanitize=thread with debugging... OPTIM="$OPTIM -fsanitize=address" else $as_nop # Otherwise use the Fortify enhancements to catch any unbounded # string operations... CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" fi WARNINGS="-Wall -Wunused" for warning in char-subscripts format-truncation format-y2k switch unused-result; do { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wno-$warning" >&5 printf %s "checking whether compiler supports -Wno-$warning... " >&6; } OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-$warning -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } WARNINGS="$WARNINGS -Wno-$warning" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS="$OLDCFLAGS" done if test x$enable_maintainer = xyes then : WARNINGS="$WARNINGS -Werror -Wno-error=deprecated" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fPIE" >&5 printf %s "checking whether compiler supports -fPIE... " >&6; } OLDCFLAGS="$CFLAGS" case "$host_os_name" in #( darwin*) : CFLAGS="$CFLAGS -fPIC -fPIE -Wl,-pie" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -Wl,-pie $LDFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; #( *) : CFLAGS="$CFLAGS -fPIC -fPIE -pie" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -pie $LDFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; #( *) : ;; esac CFLAGS="$OLDCFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OS-specific compiler options" >&5 printf %s "checking for OS-specific compiler options... " >&6; } case "$host_os_name" in #( linux*) : # Make sure we get the full set of 64-bit Linux APIs from the headers... CPPFLAGS="$CPPFLAGS -D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" # Mark read-only sections as relocatable to random addresses... LDFLAGS="$LDFLAGS -Wl,-z,relro,-z,now" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: -D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -Wl,-z,relro,-z,now" >&5 printf "%s\n" "-D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -Wl,-z,relro,-z,now" >&6; } ;; #( darwin*) : # When not building for debug, target macOS 11 or later, "universal" # binaries when possible... if echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-arch " then : # Don't add architecture/min-version flags if they are already present { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } elif echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-mmacosx-version-" then : # Don't add architecture/min-version flags if they are already present { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } elif test "$host_os_version" -ge 200 -a x$enable_debug != xyes then : # macOS 11.0 and higher support the Apple Silicon (arm64) CPUs OPTIM="$OPTIM -mmacosx-version-min=11.0 -arch x86_64 -arch arm64" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: -mmacosx-version-min=11.0 -arch x86_64 -arch arm64" >&5 printf "%s\n" "-mmacosx-version-min=11.0 -arch x86_64 -arch arm64" >&6; } else $as_nop # Don't add architecture/min-version flags if debug enabled { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } fi ;; #( *) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } ;; #( *) : ;; esac fi # Check whether --with-dsoflags was given. if test ${with_dsoflags+y} then : withval=$with_dsoflags; DSOFLAGS="$withval $DSOFLAGS" fi # Check whether --with-ldflags was given. if test ${with_ldflags+y} then : withval=$with_ldflags; LDFLAGS="$withval $LDFLAGS" fi if test "$prefix" = NONE then : # Default prefix isn't bound until AC_OUTPUT... realprefix="/usr/local" else $as_nop realprefix="$prefix" fi if test "$localstatedir" = "\${prefix}/var" then : # Default localstatedir isn't bound until AC_OUTPUT, but the GNU default # doesn't match FHS or macOS/Darwin guidance... if test "$host_os_name" = darwin then : localstatedir="/private/var" else $as_nop localstatedir="/var" fi fi # Check whether --with-papplstatedir was given. if test ${with_papplstatedir+y} then : withval=$with_papplstatedir; papplstatedir="$withval" else $as_nop papplstatedir="$localstatedir" fi printf "%s\n" "#define PAPPL_STATEDIR \"$papplstatedir\"" >>confdefs.h # Check whether --with-papplsockdir was given. if test ${with_papplsockdir+y} then : withval=$with_papplsockdir; papplsockdir="$withval" else $as_nop if test "$host_os_name" = darwin then : papplsockdir="/private/var/run" else $as_nop papplsockdir="/run" fi fi printf "%s\n" "#define PAPPL_SOCKDIR \"$papplsockdir\"" >>confdefs.h ac_config_files="$ac_config_files Makedefs pappl/pappl.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by pappl $as_me 1.4.9, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to . pappl home page: ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ pappl config.status 1.4.9 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makedefs") CONFIG_FILES="$CONFIG_FILES Makedefs" ;; "pappl/pappl.pc") CONFIG_FILES="$CONFIG_FILES pappl/pappl.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi pappl-1.4.9/configure.ac000066400000000000000000000517551476704353100151560ustar00rootroot00000000000000dnl dnl Configuration script for the Printer Application Framework dnl dnl Copyright © 2019-2025 by Michael R Sweet dnl dnl Licensed under Apache License v2.0. See the file "LICENSE" for more dnl information. dnl dnl *********************************************************************** dnl dnl Note: Using autoheader or automake on this project will break the PAPPL dnl build system. Use "autoconf -f" to regenerate the configure script if dnl you make changes to this file. dnl dnl *********************************************************************** dnl We need at least autoconf 2.70 for --runstatedir... AC_PREREQ([2.70]) dnl Package name and version... AC_INIT([pappl], [1.4.9], [https://github.com/michaelrsweet/pappl/issues], [pappl], [https://www.msweet.org/pappl]) AC_CONFIG_HEADERS([config.h]) PAPPL_VERSION="AC_PACKAGE_VERSION" PAPPL_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`" PAPPL_VERSION_MINOR="`echo AC_PACKAGE_VERSION | awk -F. '{printf("%d\n",$2);}'`" AC_SUBST([PAPPL_VERSION]) AC_SUBST([PAPPL_VERSION_MAJOR]) AC_SUBST([PAPPL_VERSION_MINOR]) AC_DEFINE_UNQUOTED([PAPPL_VERSION], "$PAPPL_VERSION", [Version number]) AC_DEFINE_UNQUOTED([PAPPL_VERSION_MAJOR], $PAPPL_VERSION_MAJOR, [Major version number]) AC_DEFINE_UNQUOTED([PAPPL_VERSION_MINOR], $PAPPL_VERSION_MINOR, [Minor version number]) dnl This line is provided to ensure that you don't run the autoheader program dnl against this project. Doing so is completely unsupported and WILL cause dnl problems! AH_TOP([#error "Somebody ran autoheader on this project which is unsupported and WILL cause problems."]) dnl Get the build and host platforms and split the host_os value AC_CANONICAL_BUILD AC_CANONICAL_HOST [host_os_name="$(echo $host_os | sed -e '1,$s/[0-9.]*$//g')"] [host_os_version="$(echo $host_os | sed -e '1,$s/^[^0-9.]*//g' | awk -F. '{print $1 $2}')"] # Linux often does not yield an OS version we can use... AS_IF([test "x$host_os_version" = x], [ host_os_version="0" ]) dnl Compiler options... CFLAGS="${CFLAGS:=}" CPPFLAGS="${CPPFLAGS:=}" DSOFLAGS="${DSOFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LIBS:=}" OPTIM="${OPTIM:=}" AC_SUBST([DSOFLAGS]) AC_SUBST([OPTIM]) dnl Standard programs... AC_PROG_CC AC_PROG_RANLIB AC_PATH_PROG([AR], [ar]) AC_PATH_PROGS([CODE_SIGN], [codesign true]) AC_PATH_PROG([MKDIR], [mkdir]) AC_PATH_PROG([RM], [rm]) AC_PATH_PROG([RMDIR], [rmdir]) AC_PATH_PROG([LN], [ln]) dnl Figure out the correct "ar" command flags... AS_IF([test "$ac_cv_prog_ranlib" = ":"], [ ARFLAGS="crs" ], [ ARFLAGS="cr" ]) AC_SUBST([ARFLAGS]) dnl install-sh AC_MSG_CHECKING([for install-sh script]) INSTALL="$(pwd)/install-sh" AC_SUBST([INSTALL]) AC_MSG_RESULT([using $INSTALL]) dnl Check for pkg-config, which is used for some other tests later on... AC_PATH_TOOL([PKGCONFIG], [pkg-config]) PKGCONFIG_CFLAGS="-I\${includedir}" PKGCONFIG_LIBS="-L\${libdir} -lpappl" PKGCONFIG_LIBS_PRIVATE="-lm" PKGCONFIG_REQUIRES="" AC_SUBST([PKGCONFIG_CFLAGS]) AC_SUBST([PKGCONFIG_LIBS]) AC_SUBST([PKGCONFIG_LIBS_PRIVATE]) AC_SUBST([PKGCONFIG_REQUIRES]) dnl CUPS AC_PATH_TOOL([CUPSCONFIG], [cups-config]) AC_MSG_CHECKING([for CUPS library v2.2 or higher]) AS_IF([$PKGCONFIG --exists cups3], [ CUPS_VERSION="$($PKGCONFIG --modversion cups3)" AC_MSG_RESULT([yes, v$CUPS_VERSION]) CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags cups3)" LIBS="$LIBS $($PKGCONFIG --libs cups3)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($PKGCONFIG --cflags cups3)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($PKGCONFIG --libs cups3)" AS_IF([test x$host_os_name = xdarwin], [ CUPS_SERVERROOT="/private/etc/cups" ], [ AS_IF([test "x$($PKGCONFIG --variable=prefix cups3)" = x/usr], [ CUPS_SERVERROOT="/etc/cups" ], [ CUPS_SERVERROOT="$($PKGCONFIG --variable=prefix cups3)/etc/cups" ]) ]) ], [$PKGCONFIG --exists cups], [ CUPS_VERSION="$($PKGCONFIG --modversion cups)" AC_MSG_RESULT([yes, v$CUPS_VERSION]) CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags cups)" LIBS="$LIBS $($PKGCONFIG --libs cups)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($PKGCONFIG --cflags cups)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($PKGCONFIG --libs cups)" CUPS_SERVERROOT="$($PKGCONFIG --variable=cups_serverroot cups)" AS_IF([test "x$CUPS_SERVERROOT" = x], [ AS_IF([test x$host_os_name = xdarwin], [ CUPS_SERVERROOT="/private/etc/cups" ], [ AS_IF([test "x$($PKGCONFIG --variable=prefix cups)" = x/usr], [ CUPS_SERVERROOT="/etc/cups" ], [ CUPS_SERVERROOT="$($PKGCONFIG --variable=prefix cups)/etc/cups" ]) ]) ]) ], [ AS_IF([test "x$CUPSCONFIG" = x], [ AC_MSG_RESULT(no) AC_MSG_ERROR([Sorry, this software requires libcups-dev.]) ]) CUPS_VERSION="$($CUPSCONFIG --api-version)" AS_CASE(["$CUPS_VERSION"], [1.* | 2.0 | 2.1], [ AC_MSG_RESULT(no) AC_MSG_ERROR([Sorry, you need CUPS 2.2.0 or higher.]) ]) AC_MSG_RESULT([yes, v$CUPS_VERSION]) CPPFLAGS="$CPPFLAGS $($CUPSCONFIG --cflags)" DSOFLAGS="$DSOFLAGS $($CUPSCONFIG --ldflags)" LDFLAGS="$LDFLAGS $($CUPSCONFIG --ldflags)" LIBS="$LIBS $($CUPSCONFIG --image --libs)" PKGCONFIG_CFLAGS="$PKGCONFIG_CFLAGS $($CUPSCONFIG --cflags)" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $($CUPSCONFIG --image --libs)" CUPS_SERVERROOT="$($CUPSCONFIG --serverroot)" ]) AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT", [Location of CUPS config files]) dnl String functions... AC_CHECK_FUNCS([strlcpy]) dnl POSIX threads... AC_CHECK_HEADER([pthread.h]) AS_IF([test x$ac_cv_header_pthread_h != xyes], [ AC_MSG_ERROR([Sorry, this software requires POSIX threading support.]) ]) for flag in -lpthreads -lpthread -pthread; do AC_MSG_CHECKING([for pthread_create using $flag]) SAVELIBS="$LIBS" LIBS="$flag $LIBS" AC_LANG([C]) AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],[pthread_create(0, 0, 0, 0);])], [ have_pthread=yes PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $flag" ], [ LIBS="$SAVELIBS" ]) AS_IF([test x$have_pthread = xyes], [ AC_MSG_RESULT([yes]) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE -D_REENTRANT" break ], [ AC_MSG_RESULT([no]) ]) done dnl DNS-SD support... AC_ARG_WITH([dnssd], AS_HELP_STRING([--with-dnssd=LIBRARY], [set DNS-SD library (auto, avahi, mdnsresponder)])) PKGCONFIG_AVAHI="" AS_IF([test "x$with_dnssd" != xmdnsresponder -a "x$with_dnssd" != xno -a "x$PKGCONFIG" != x -a x$host_os_name != xdarwin], [ AC_MSG_CHECKING([for Avahi]) AS_IF([$PKGCONFIG --exists avahi-client], [ AC_MSG_RESULT([yes]) CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags avahi-client)" LIBS="$LIBS $($PKGCONFIG --libs avahi-client)" PKGCONFIG_AVAHI="avahi-client" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs avahi-client)" AC_DEFINE([HAVE_DNSSD], 1, [Have DNS-SD support?]) AC_DEFINE([HAVE_AVAHI], 1, [Have Avahi?]) ], [ AC_MSG_RESULT([no]) AS_IF([test x$with_dnssd = xavahi], AC_MSG_ERROR([libavahi-client-dev needed for --with-dnssd=avahi.])) ]) ], [test x$with_dnssd = xavahi], [ AC_MSG_ERROR([pkgconfig and libavahi-client-dev needed for --with-dnssd=avahi.]) ], [test x$with_dnssd != xavahi -a "x$with_dnssd" != xno], [ AC_CHECK_HEADER(dns_sd.h, [ AS_CASE(["$host_os_name"], [darwin*], [ # Darwin and macOS... AC_DEFINE([HAVE_DNSSD], 1, [Have DNS-SD support?]) AC_DEFINE([HAVE_MDNSRESPONDER], 1, [Have mDNSResponder?)]) LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework CoreFoundation -framework SystemConfiguration" ], [*], [ # All others... AC_MSG_CHECKING(for current version of dns_sd library) SAVELIBS="$LIBS" LIBS="$LIBS -ldns_sd" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ int constant = kDNSServiceFlagsShareConnection; unsigned char txtRecord[100]; uint8_t valueLen; TXTRecordGetValuePtr(sizeof(txtRecord), txtRecord, "value", &valueLen);]]) ],[ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_DNSSD], 1, [Have DNS-SD support?]) AC_DEFINE([HAVE_MDNSRESPONDER], 1, [Have mDNSResponder?)]) PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -ldns_sd" ],[ AC_MSG_RESULT([no]) LIBS="$SAVELIBS" AS_IF([test x$with_dnssd = xmdnsresponder], AC_MSG_ERROR([mDNSResponder required for --with-dnssd=mdnsresponder.])) ]) ]) ]) ]) AC_SUBST([PKGCONFIG_AVAHI]) dnl TLS support... PKGCONFIG_TLS="" AC_SUBST([PKGCONFIG_TLS]) AC_ARG_WITH([tls], AS_HELP_STRING([--with-tls=...], [use gnutls or openssl/libressl for TLS support])) AS_IF([test "x$with_tls" = x], [ with_tls="yes" ], [test "$with_tls" != gnutls -a "$with_tls" != libressl -a "$with_tls" != openssl -a "$with_tls" != yes], [ AC_MSG_ERROR([Unsupported --with-tls value "$with_tls" specified.]) ]) have_tls="0" dnl First look for OpenSSL/LibreSSL... AS_IF([test $with_tls = yes -o $with_tls = libressl -o $with_tls = openssl], [ AS_IF([test "x$PKGCONFIG" != x], [ AC_MSG_CHECKING([for OpenSSL/LibreSSL package]) AS_IF([$PKGCONFIG --exists openssl], [ AC_MSG_RESULT([yes]) have_tls="1" AC_DEFINE([HAVE_OPENSSL], [1], [Do we have the OpenSSL/LibreSSL library?]) CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags openssl)" LIBS="$LIBS $($PKGCONFIG --libs openssl)" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs openssl)" PKGCONFIG_TLS="openssl," ], [ AC_MSG_RESULT([no]) ]) ]) ]) AS_IF([test $have_tls = 0], [ AS_IF([test $with_tls = yes -o $with_tls = gnutls], [ AS_IF([test "x$PKGCONFIG" != x], [ AC_MSG_CHECKING([for GNU TLS package]) AS_IF([$PKGCONFIG --exists gnutls], [ AC_MSG_RESULT([yes]) have_tls="1" AC_DEFINE(HAVE_GNUTLS, 1, [Have GNU TLS?]) CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags gnutls`" LIBS="$LIBS `$PKGCONFIG --libs gnutls`" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs gnutls)" PKGCONFIG_TLS="gnutls >= 3.0," ], [ AC_MSG_RESULT([no]) ]) ]) ]) ]) AS_IF([test $have_tls = 0], [ AC_MSG_ERROR([TLS support is required.]) ]) dnl Random number support... AC_CHECK_HEADER([sys/random.h], [ AC_DEFINE([HAVE_SYS_RANDOM_H], 1, [Have header?]) ]) AC_CHECK_FUNCS([arc4random getrandom gnutls_rnd]) dnl libjpeg... AC_ARG_ENABLE([libjpeg], AS_HELP_STRING([--enable-libjpeg], [use libjpeg for JPEG printing, default=auto])) PKGCONFIG_LIBJPEG="" AC_SUBST([PKGCONFIG_LIBJPEG]) AS_IF([test x$enable_libjpeg != xno], [ have_jpeg=no AS_IF([test "x$PKGCONFIG" != x], [ AC_MSG_CHECKING([for libjpeg via pkg-config]) AS_IF([$PKGCONFIG --exists libjpeg], [ AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_LIBJPEG], 1, [Have JPEG library?]) CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libjpeg`" LIBS="$LIBS `$PKGCONFIG --libs libjpeg`" PKGCONFIG_LIBJPEG="libjpeg," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libjpeg)" have_jpeg=yes ], [ AC_MSG_RESULT([no]); ]) ]) AS_IF([test $have_jpeg = no], [ AC_SEARCH_LIBS(jpeg_start_decompress, turbojpeg jpeg, [ AC_DEFINE([HAVE_LIBJPEG], 1, [Have JPEG library?]) PKGCONFIG_LIB_PRIVATE="$PKGCONFIG_LIB_PRIVATE -l$ac_cv_search_jpeg_start_decompress" have_jpeg=yes ]) ]) AS_IF([test x$enable_libjpeg = xyes -a $have_jpeg = no], [ AC_MSG_ERROR([libjpeg-dev 8 or later required for --enable-libjpeg.]) ]) ]) dnl libpng... AC_ARG_ENABLE([libpng], AS_HELP_STRING([--enable-libpng], [use libpng for PNG printing, default=auto])) PKGCONFIG_LIBPNG="" AC_SUBST([PKGCONFIG_LIBPNG]) AS_IF([test "x$PKGCONFIG" != x -a x$enable_libpng != xno], [ AC_MSG_CHECKING([for libpng-1.6.x]) AS_IF([$PKGCONFIG --exists libpng16], [ AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_LIBPNG], 1, [Have PNG library?]) CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libpng16`" LIBS="$LIBS `$PKGCONFIG --libs libpng16` -lz" PKGCONFIG_LIBPNG="libpng >= 1.6," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libpng16)" ], [ AC_MSG_RESULT([no]); AS_IF([test x$enable_libpng = xyes], [ AC_MSG_ERROR([libpng-dev 1.6 or later required for --enable-libpng.]) ]) ]) ], [test x$enable_libpng = xyes], [ AC_MSG_ERROR([libpng-dev 1.6 or later required for --enable-libpng.]) ]) dnl libusb... AC_ARG_ENABLE([libusb], AS_HELP_STRING([--enable-libusb], [use libusb for USB printing, default=auto])) PKGCONFIG_LIBUSB="" AC_SUBST([PKGCONFIG_LIBUSB]) AS_IF([test "x$PKGCONFIG" != x -a x$enable_libusb != xno], [ AC_MSG_CHECKING([for libusb-1.0]) AS_IF([$PKGCONFIG --exists libusb-1.0], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_LIBUSB], 1, [Have USB library?]) CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libusb-1.0`" LIBS="$LIBS `$PKGCONFIG --libs libusb-1.0`" PKGCONFIG_LIBUSB="libusb-1.0 >= 1.0," PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE $($PKGCONFIG --libs libusb-1.0)" AS_IF([test "x$host_os_name" = xdarwin], [ LIBS="$LIBS -framework IOKit" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework IOKit" ]) ], [ AC_MSG_RESULT([no]) AS_IF([test x$enable_libusb = xyes], [ AC_MSG_ERROR([libusb-1.0-0-dev required for --enable-libusb.]) ]) ]) ], [test x$enable_libusb = xyes], [ AC_MSG_ERROR([pkgconfig and libusb-1.0-0-dev required for --enable-libusb.]) ]) dnl PAM support... AC_ARG_ENABLE([libpam], AS_HELP_STRING([--enable-libpam], [use libpam for authentication, default=auto])) AS_IF([test x$enable_libpam != xno], [ dnl PAM needs dlopen... AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pam], [pam_start], [ AC_DEFINE([HAVE_LIBPAM], 1, [Have PAM library?]) LIBS="$LIBS -lpam" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -lpam" ]) dnl PAM has two "standard" locations for its header... AC_CHECK_HEADER(security/pam_appl.h, AC_DEFINE([HAVE_SECURITY_PAM_APPL_H], 1, [Have header?])) AC_CHECK_HEADER(pam/pam_appl.h, AC_DEFINE([HAVE_PAM_PAM_APPL_H], 1, [Have header?])) AS_IF([test x$ac_pam_start = xno -a x$enable_libpam = xyes], [ AC_MSG_ERROR([libpam-dev required for --enable-libpam.]) ]) ]) dnl System status UI... AS_IF([test "$host_os_name" = darwin], [ LIBS="-framework AppKit $LIBS" PKGCONFIG_LIBS_PRIVATE="$PKGCONFIG_LIBS_PRIVATE -framework AppKit" SYSTEM_STATUS="system-status-macos.o" #], [ # AS_IF([$PKGCONFIG --exists gnome-desktop-3.0], [ # CPPFLAGS="$($PKGCONFIG --cflags gnome-desktop-3.0) $CPPFLAGS" # LIBS="$($PKGCONFIG --libs gnome-desktop-3.0) $LIBS" # PKGCONFIG_LIBS_PRIVATE="$($PKGCONFIG --libs gnome-desktop-3.0) $PKGCONFIG_LIBS_PRIVATE" # SYSTEM_STATUS="system-status-gnome.o" # ], [ # SYSTEM_STATUS="system-status-dummy.o" # ]) ]) AC_SUBST([SYSTEM_STATUS]) dnl Library target... AC_ARG_ENABLE([static], AS_HELP_STRING([--disable-static], [do not install static library])) AC_ARG_ENABLE([shared], AS_HELP_STRING([--disable-shared], [do not install shared library])) AS_IF([test x$enable_shared != xno], [ AS_IF([test "$host_os_name" = darwin], [ LIBPAPPL="libpappl.1.dylib" ], [ LIBPAPPL="libpappl.so.1" ]) AS_IF([test x$enable_static != xno], [ LIBPAPPL_STATIC="libpappl.a" ], [ LIBPAPPL_STATIC="" ]) ], [ LIBPAPPL="libpappl.a" LIBPAPPL_STATIC="" PKGCONFIG_LIBS="$PKGCONFIG_LIBS $PKGCONFIG_LIBS_PRIVATE" PKGCONFIG_LIBS_PRIVATE="" ]) AC_SUBST([LIBPAPPL]) AC_SUBST([LIBPAPPL_STATIC]) dnl Extra compiler options... AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [turn on debugging, default=no])) AC_ARG_ENABLE([debug_printfs], AS_HELP_STRING([--enable-debug-printfs], [turn on debug messages, default=no])) AC_ARG_ENABLE([maintainer], AS_HELP_STRING([--enable-maintainer], [turn on maintainer mode, default=no])) AC_ARG_ENABLE([sanitizer], AS_HELP_STRING([--enable-sanitizer], [build with AddressSanitizer, default=no])) AC_ARG_ENABLE([tsanitizer], AS_HELP_STRING([--enable-tsanitizer], [build with ThreadSanitizer, default=no])) AS_IF([test x$enable_debug = xyes], [ OPTIM="$OPTIM -g" CSFLAGS="" ], [ OPTIM="$OPTIM -g -Os" CSFLAGS="-o runtime" ]) AS_IF([test x$enable_debug_printfs = xyes], [ OPTIM="$OPTIM -DDEBUG" ]) AC_SUBST([CSFLAGS]) WARNINGS="" AC_SUBST([WARNINGS]) AS_IF([test -n "$GCC"], [ AS_IF([test x$enable_sanitizer = xyes], [ # Use -fsanitize=address with debugging... OPTIM="$OPTIM -fsanitize=address" AS_IF([test x$enable_tsanitizer = xyes], [ AC_MSG_WARN([Ignoring --enable-tsanitizer since --enable-sanitizer was specified.]) ]) ], [test x$enable_tsanitizer = xyes], [ # Use -fsanitize=thread with debugging... OPTIM="$OPTIM -fsanitize=address" ], [ # Otherwise use the Fortify enhancements to catch any unbounded # string operations... CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" ]) dnl Show all standard warnings + unused variables when compiling... WARNINGS="-Wall -Wunused" dnl Drop some not-useful/unreliable warnings... for warning in char-subscripts format-truncation format-y2k switch unused-result; do AC_MSG_CHECKING([whether compiler supports -Wno-$warning]) OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-$warning -Werror" AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [ AC_MSG_RESULT(yes) WARNINGS="$WARNINGS -Wno-$warning" ], [ AC_MSG_RESULT(no) ]) CFLAGS="$OLDCFLAGS" done dnl Maintainer mode enables -Werror... AS_IF([test x$enable_maintainer = xyes], [ WARNINGS="$WARNINGS -Werror -Wno-error=deprecated" ]) dnl See if PIE options are supported... AC_MSG_CHECKING(whether compiler supports -fPIE) OLDCFLAGS="$CFLAGS" AS_CASE(["$host_os_name"], [darwin*], [ CFLAGS="$CFLAGS -fPIC -fPIE -Wl,-pie" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[ OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -Wl,-pie $LDFLAGS" AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) ], [*], [ CFLAGS="$CFLAGS -fPIC -fPIE -pie" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[ OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -pie $LDFLAGS" AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) ]) CFLAGS="$OLDCFLAGS" dnl OS-specific compiler options... AC_MSG_CHECKING([for OS-specific compiler options]) AS_CASE(["$host_os_name"], [linux*], [ # Make sure we get the full set of 64-bit Linux APIs from the headers... CPPFLAGS="$CPPFLAGS -D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" # Mark read-only sections as relocatable to random addresses... LDFLAGS="$LDFLAGS -Wl,-z,relro,-z,now" AC_MSG_RESULT([-D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -Wl,-z,relro,-z,now]) ], [darwin*], [ # When not building for debug, target macOS 11 or later, "universal" # binaries when possible... AS_IF([echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-arch "], [ # Don't add architecture/min-version flags if they are already present AC_MSG_RESULT([none]) ], [echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-mmacosx-version-"], [ # Don't add architecture/min-version flags if they are already present AC_MSG_RESULT([none]) ], [test "$host_os_version" -ge 200 -a x$enable_debug != xyes], [ # macOS 11.0 and higher support the Apple Silicon (arm64) CPUs OPTIM="$OPTIM -mmacosx-version-min=11.0 -arch x86_64 -arch arm64" AC_MSG_RESULT([-mmacosx-version-min=11.0 -arch x86_64 -arch arm64]) ], [ # Don't add architecture/min-version flags if debug enabled AC_MSG_RESULT([none]) ]) ], [*], [ AC_MSG_RESULT([none]) ]) ]) dnl Extra linker options... AC_ARG_WITH([dsoflags], AS_HELP_STRING([--with-dsoflags=...], [Specify additional DSOFLAGS]), [ DSOFLAGS="$withval $DSOFLAGS" ]) AC_ARG_WITH([ldflags], AS_HELP_STRING([--with-ldflags=...], [Specify additional LDFLAGS]), [ LDFLAGS="$withval $LDFLAGS" ]) dnl State and run directories for root servers... AS_IF([test "$prefix" = NONE], [ # Default prefix isn't bound until AC_OUTPUT... realprefix="/usr/local" ], [ realprefix="$prefix" ]) AS_IF([test "$localstatedir" = "\${prefix}/var"], [ # Default localstatedir isn't bound until AC_OUTPUT, but the GNU default # doesn't match FHS or macOS/Darwin guidance... AS_IF([test "$host_os_name" = darwin], [ localstatedir="/private/var" ], [ localstatedir="/var" ]) ]) AC_ARG_WITH([papplstatedir], AS_HELP_STRING([--with-papplstatedir], [specify default location of printer application state and spool files (default=LOCALSTATEDIR)]), [ papplstatedir="$withval" ], [ papplstatedir="$localstatedir" ]) AC_DEFINE_UNQUOTED([PAPPL_STATEDIR], ["$papplstatedir"], [Location of PAPPL state and spool data (when run as root)]) AC_ARG_WITH([papplsockdir], AS_HELP_STRING([--with-papplsockdir], [specify default location of printer application domain sockets (default=/run or /private/var/run)]), [ papplsockdir="$withval" ], [ AS_IF([test "$host_os_name" = darwin], [ papplsockdir="/private/var/run" ], [ papplsockdir="/run" ]) ]) AC_DEFINE_UNQUOTED([PAPPL_SOCKDIR], ["$papplsockdir"], [Location of PAPPL domain socket (when run as root)]) dnl Generate the Makefile and pkg-config file... AC_CONFIG_FILES([Makedefs pappl/pappl.pc]) AC_OUTPUT pappl-1.4.9/doc/000077500000000000000000000000001476704353100134205ustar00rootroot00000000000000pappl-1.4.9/doc/IPP-EXTENSIONS.md000066400000000000000000000302471476704353100160750ustar00rootroot00000000000000--- title: PAPPL IPP Extensions author: Michael R Sweet copyright: Copyright © 2022-2023 by Michael R Sweet --- # 1. Introduction This document describes the IPP extensions unique to the [Printer Application Framework (PAPPL)][PAPPL]. Conformance words including MAY, MUST, MUST NOT, RECOMMENDED, REQUIRED, SHOULD, SHOULD NOT # 2. Terminology The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119][RFC2119]. Other printing terminology is imported from [RFC 8011: Internet Printing Protocol/1.1: Model and Semantics][RFC8011] and [PWG 5100.22-2019: IPP System Service v1.0 (SYSTEM)][PWG5100.22]. # 3. Model The [Printer Application Framework (PAPPL)][PAPPL] provides a generic framework for integrating legacy printer drivers with a common [IPP Everywhere][IPP-EVERYWHERE] front-end. The framework implements a subset of the [IPP System Service][PWG5100.22] to manage multiple IPP Printers. Each Printer has an associated Output Device whose URI ("smi55357-device-uri") and driver ("smi55357-driver") specify where and how to communicate with the Output Device. In order to support remote management of Printers, the existing Create-Printer operation is amended and two new operations are added to list the available Output Devices and drivers. Additionally, a third new operation automates adding multiple printers. # 4. IPP Operations All of the new operations can require authentication and authorization as an Operator or Administrator. ## 4.1 PAPPL-Create-Printers The REQUIRED PAPPL-Create-Printers System operation creates zero or more Printers for newly discovered Output Devices. ### 4.1.1 PAPPL-Create-Printers Request Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. - Target: The "system-uri" (uri) operation attribute, which is the target for this operation. - Requesting User Name: The "requesting-user-name" (name(MAX)) attribute SHOULD be supplied by the Client as described in [Section 9.3 of RFC 8011][RFC8011]. - "smi55357-device-type" (1setOf type2 keyword): The Client OPTIONALLY supplies and a System MUST support this attribute which lists one or more device types to query; the default is 'all'. ### 4.1.2 PAPPL-Create-Printers Response Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. Groups 2-N: Printer Attributes - “printer-id” (integer(1:65535)): The System MUST return this attribute. - “printer-is-accepting-jobs” (boolean): The System MUST return all three of these attributes. - “printer-state” (type1 enum): The System MUST return this attribute. - “printer-state-reasons” (1setOf type2 keyword): The System MUST return this attribute. - “printer-uuid” (uri(45)): The System MUST return this attribute. - “printer-xri-supported” (1setOf collection): The System MUST return this attribute. ## 4.2 PAPPL-Find-Devices The REQUIRED PAPPL-Find-Devices System operation queries the System for a list of known or discovered Output Devices that can be used with the Create-Printer operation. The System MAY cache the list of Output Devices but the list MUST have been updated or confirmed within the 300 seconds prior to receiving a Client request. Access Rights: The authenticated user (see [Section 9.3 of RFC 8011][RFC8011]) performing this operation MUST be an Operator or Administrator of the System (see [Sections 1 and 9.5][RFC8011] of RFC 8011). Otherwise, the IPP System MUST reject the operation and return 'client-error-forbidden', 'client-error-not-authenticated', or 'client-error-not-authorized' as appropriate. ### 4.2.1 PAPPL-Find-Devices Request Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. - Target: The "system-uri" (uri) operation attribute, which is the target for this operation. - Requesting User Name: The "requesting-user-name" (name(MAX)) attribute SHOULD be supplied by the Client as described in [Section 9.3 of RFC 8011][RFC8011]. - "smi55357-device-type" (1setOf type2 keyword): The Client OPTIONALLY supplies and a System MUST support this attribute which lists one or more device types to query; the default is 'all'. ### 4.2.2 PAPPL-Find-Devices Response Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. Group 2: System Attributes - "smi55357-device-col" (1setOf collection): A list of Output Devices supported by the System. ## 4.3 PAPPL-Find-Drivers The REQUIRED PAPPL-Find-Drivers System operation queries the System for a list of known or matching Output Device drivers that can be used with the Create-Printer operation. Access Rights: The authenticated user (see [Section 9.3 of RFC 8011][RFC8011]) performing this operation MUST be an Operator or Administrator of the System (see [Sections 1 and 9.5][RFC8011] of RFC 8011). Otherwise, the IPP System MUST reject the operation and return 'client-error-forbidden', 'client-error-not-authenticated', or 'client-error-not-authorized' as appropriate. ### 4.3.1 PAPPL-Find-Drivers Request Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. - Target: The "system-uri" (uri) operation attribute, which is the target for this operation. - Requesting User Name: The "requesting-user-name" (name(MAX)) attribute SHOULD be supplied by the Client as described in [Section 9.3 of RFC 8011][RFC8011]. - "smi55357-device-id" (text(MAX)): The Client OPTIONALLY supplies and a System MUST support this attribute which specifies an IEEE-1284 device ID for filtering the list of drivers. ### 4.3.2 PAPPL-Find-Drivers Response Group 1: Operation Attributes - Natural Language and Character Set: The "attributes-charset" and "attributes-natural-language" attributes as described in [Section 4.1.4.1 of RFC 8011][RFC8011]. Group 2: System Attributes - "smi55357-driver-col" (1setOf collection): A list of drivers supported by the System. # 5. IPP Attributes ## 5.1 Operation Attributes ### 5.1.1 smi55357-device-id (text(MAX)) This operation attribute specifies the IEEE-1284 device ID string for an Output Device. ### 5.1.2 smi55357-device-type (1setOf type2 keyword) This operation attribute specifies a list of Output Device connection types the Client wishes to query. The following keyword values are defined: - 'all': All devices - 'dns-sd': Devices discovered via DNS-SD - 'local': Local (directly connected) devices - 'network': Network devices - 'other-local': Devices connected via another local interface - 'other-network': Devices discovered via another network protocol - 'snmp': Devices discovered via SNMP - 'usb': Devices connected via USB ### 5.1.3 smi55357-device-uri (uri) This attribute specifies the URI for the Output Device. ### 5.1.4 smi55357-driver (keyword) This attribute specifies the driver for the Output Device. ## 5.2 Printer Status Attributes ### 5.2.1 smi55357-device-uri (uri) This REQUIRED attribute specifies the URI for the Output Device. ### 5.2.2 smi55357-driver (keyword) This REQUIRED attribute specifies the driver for the Output Device. ## 5.3 System Status Attributes ### 5.3.1 smi55357-device-col (1setOf collection) This attribute lists available Output Devices. The REQUIRED "smi55357-device-id", "smi55357-device-name", and "smi55357-device-uri" member attributes provide information about an individual Output Device. #### 5.3.1.1 smi55357-device-id (text(MAX)) This member attribute provides the IEEE-1284 Device ID for the Output Device. #### 5.3.1.2 smi55357-device-info (text(MAX)) This member attribute provides descriptive information about the Output Device. #### 5.3.1.3 smi55357-device-uri (uri) This member attribute provides the URI value to use with the Create-Printer operation. ### 5.3.2 smi55357-device-uri-schemes-supported (1setOf uriScheme) This REQUIRED attribute lists the supported "smi55357-device-uri" URI schemes. ### 5.3.3 smi55357-driver-col (1setOf collection) This attribute lists available or matching drivers for Output Devices. The REQUIRED "smi55357-device-id", "smi55357-driver", and "smi55357-driver-info" member attributes provide information about a driver. #### 5.3.3.1 smi55357-driver (keyword) This member attribute provides the driver name as a keyword. #### 5.3.3.2 smi55357-device-id (text(MAX)) This member attribute provides the IEEE-1284 Device ID for Output Devices supported by the driver. #### 5.3.3.3 smi55357-driver-info (text(MAX)) This member attribute provides descriptive information about the driver. # 6. Amended Semantics for Existing Operations ## 6.1 Create-Printer: smi55357-device-uri and smi55357-driver This registration amends the [Create-Printer operation][PWG5100.22] to accept the "smi55357-device-uri" and "smi55357-driver" operation attributes. The System MUST either accept the provided values and copy them to the corresponding Printer Status attributes of the new Printer or reject them with the 'client-error-attributes-or-values-not-supported' status code. When the "smi55357-driver" attribute has the value 'auto', the System copies the value of the automatically-determined driver to the corresponding Printer Status attribute. # 7. References [IPP-EVERYWHERE: IPP Everywhere™ technology landing page][IPP-EVERYWHERE] [IPP-EVERYWHERE]: https://www.pwg.org/ipp/everywhere.html [PAPPL: Printer Application Framework (PAPPL)][PAPPL] [PAPPL]: https://www.msweet.org/pappl [PWG5100.22: IPP System Service v1.0 (SYSTEM)][PWG5100.22], November 2019 [PWG5100.22]: https://ftp.pwg.org/pub/pwg/candidates/cs-ippsystem10-20191122-5100.22.pdf [RFC2199: Key words for use in RFCs to Indicate Requirement Levels][RFC2119], BCP14, March 1997 [RFC2119]: https://www.rfc-editor.org/rfc/rfc2119 [RFC8011: Internet Printing Protocol/1.1: Model and Semantics][RFC8011], STD92, January 2017 [RFC8011]: https://www.rfc-editor.org/rfc/rfc8011 # 8. IANA Considerations ## 8.1 Attribute Registrations ``` Operation attributes: Reference -------------------- --------- smi55357-device-id (text(MAX)) [PAPPL-IPP] smi55357-device-type (1setOf type2 keyword) [PAPPL-IPP] smi55357-device-uri (uri) [PAPPL-IPP] smi55357-driver (keyword) [PAPPL-IPP] Printer Status attributes: Reference ------------------------------ --------- smi55357-device-uri (uri) [PAPPL-IPP] smi55357-driver (keyword) [PAPPL-IPP] System Status attributes: Reference ------------------------------ --------- smi55357-device-col (1setOf collection) [PAPPL-IPP] smi55357-device-id (text(MAX)) [PAPPL-IPP] smi55357-device-info (text(MAX)) [PAPPL-IPP] smi55357-device-uri (uri) [PAPPL-IPP] smi55357-device-uri-schemes-supported (1setOf uriScheme) [PAPPL-IPP] smi55357-driver-col (1setOf collection) [PAPPL-IPP] smi55357-device-id (text(MAX)) [PAPPL-IPP] smi55357-driver (keyword) [PAPPL-IPP] smi55357-driver-info (text(MAX)) [PAPPL-IPP] ``` ## 8.2 Type2 keyword Registrations ``` Attributes (attribute syntax) Keyword Attribute Value Reference ----------------------- --------- smi55357-device-type (1setOf type2 keyword) [PAPPL-IPP] all [PAPPL-IPP] dns-sd [PAPPL-IPP] local [PAPPL-IPP] network [PAPPL-IPP] other-local [PAPPL-IPP] other-network [PAPPL-IPP] snmp [PAPPL-IPP] usb [PAPPL-IPP] ``` ## 8.2 Type2 enum Registrations ``` Attributes (attribute syntax) Enum Value Enum Symbolic Name Reference ---------- ------------------ --------- operations-supported (1setOf type2 enum) [RFC8011] 0x402B PAPPL-Find-Devices [PAPPL-IPP] 0x402C PAPPL-Find-Drivers [PAPPL-IPP] 0x402D PAPPL-Create-Printers [PAPPL-IPP] ``` ## 8.3 Operation Registrations ``` Operation Name Reference -------------- --------- Create-Printer (Extension) [PAPPL-IPP] PAPPL-Create-Printers [PAPPL-IPP] PAPPL-Find-Devices [PAPPL-IPP] PAPPL-Find-Drivers [PAPPL-IPP] ``` pappl-1.4.9/doc/Makefile000066400000000000000000000013151476704353100150600ustar00rootroot00000000000000# # Documentation page makefile for the Printer Application Framework # # Copyright © 2020 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # include ../Makedefs DOCFILES = \ pappl.html \ pappl-512.png \ pappl-block.png # Make everything all: # Clean everything clean: # Clean all non-distribution files distclean: clean # Update dependencies depend: # Install everything install: echo Installing documentation in $(BUILDROOT)/$(datadir)/doc/pappl... $(INSTALL) -d -m 755 $(BUILDROOT)/$(datadir)/doc/pappl for file in $(DOCFILES); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)/$(datadir)/doc/pappl; \ done # Test everything test: pappl-1.4.9/doc/pappl-128.png000066400000000000000000000072431476704353100155600ustar00rootroot00000000000000PNG  IHDRiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*ikF&MeiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image SvemPLTE@??@@@A??AAAB??BBBC>>CCCD>>DDDE>>EEEF==FFFG==GGGH==HHHIIIJ<(~a>sg<")c 0Swf_Z7.whM !y t¶_(1c\/mn(k$-?}M [\鮅V.~>OSAl{{}L 3:SϰkVVL8ˏmtJwɶjcHL'}n_#ctY5@ >@qh$Dkع¯7p3k>sM |,,ÐM-֞ p@[ Su=##Ɉ@=fќj)1/T  vM M4`pYXOJ 8l,gņ䈦r@爆i Phh80@ Sd:$&&vI 8ݘPDUaG.eu. Z8 CL0yįtBU4|C$}UҠ*' 室# U<p9_*xg@hT9*3@KB%n"tP j=<²). <mjt@ɮ1I֎],:SGi?Pa1duQXdejץ6:_x8;"?xZC?F  U~ܹIENDB`pappl-1.4.9/doc/pappl-512.png000066400000000000000000000313421476704353100155520ustar00rootroot00000000000000PNG  IHDRxiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*i(0eiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image Sve*IDATx }'J@  c6&c+8EK 悃r y\*IL"6v`DɕmH8rSs."D@F VZIUvG433ӟO2#vf6hP.@@@@@@@@@^W @@@@@@u}sLzWJկ~H+Wt2Sկ~@(~_G@gկ~#@~_Vկ~@(կ~hnnjIƍKcǎM]]]kzHﷀZĉԩSӴiҔ)Sɓ&M񼧧g#~o„ ~?>:CٺukzGg?Y (DW E~xooW>}z5kV9sf1cF3^GtC~gjo7q?`W^ ҩ<餓҉'_osחvؑ^{Ǯ]Fzٳ#ݻc߾}#+Vhp@ѢE㬳||#:m۶۷kCGg:iFSNIg}v836Gt/bڴiSؼys8{-Ey??moG׏ӆ 7n;g^;r . ?_8Ϧgy&=i# tr}{_ZdI~ha׮]ѯZ*=syW?-(.a{׻ޕs=.i۽{wz'Қ5k?||Pe˖x>UTk;f~n5www?ῑ8|c;c潡P٭AٖC;z _eg*n=NK/MW_}Gػw?^~厨*(TMLaZy[ޒ>O?O tT$nWhq^p8\1]_ PV;I{?c;O_y7|s~Mz(-_<7˿&O淴)~/~ӟ믿?@iָi}700>ώ/PZߘ8z|Z`A1-Z4y?27?cիW??hsCP!sO?tя~x&˨Yz{{Az7nܸӓf͚ϟ%QEv-[nժUTӖW~WK[rZaWn (E?dɒ?Ϥ+Vx|pߡ޽{~կ~5=smWњY3ҥKe]w& qwygG56D7Vlvm+W:Z䇟|Ʌ}I C|C9s'NLwqGZ`A}׿Lj[_fֿ{Oo~yviiڴi'gN<}!kb[k}ߕ_Jpӱ{c~i-‘O-pNx /ww_C=QߴiS~ϯ7" >]'mٮ . W!ƘGin+2{C Wq>xH~_kuY51@)YΨ]LŸo}[͝;7M^ꪫ*lw@/U]tшaɓ'ƍoZStxe2iΏbΝy؋Ie`1(4޷5feS֑d\fT[oXcY2՚5kiei/uԧ^G4b+u,шId+G iK*|ߨˡ8_ /o떩N|p =yOsX S_W 7pK.$}_>|3oV[jGh?wwuy8/]1mbƲeH˾Zq91LtmЂmsk?\=bƲ=ҲV FVN,3R )SE7ԯQl+}-xGjj3gZmH["0q7y\W^]:rc۷4D܎-!!Q}^z=Q*z F<_~Fau֍x~Ϸ_mLl|O=sʛDF["PE=Temݺuʁqod[j6UNd G FFΟ?_pubƍ}W@-\BĆ ,V{9*;V7H岭`ubڵ}W@-Z(͘1ne˖O8 A*m岯E N zj :q/rҥu{{l=i\7lƲ=ҲE Ï,[.m۶Nte׷RtI'9P2ie_Xb]Сt[iQ1/N+W{=;N G ;͞=;?ނ/Fǀ8?3~{キ-Bt&1`͛7I@Zs|X'n64FWtMipppDu7iӦY8.8zaXbصkH(P!;sk1[o;mq.:QۿJoO>A!`a:Kime@ @(8}.=rK>L.4 -M+hX*__%\ aW]uUg[ihhhhͣc:9l˿}\#~ 7䷆kMƝ1 nݚ޽{-&C===i֬Yy,\0op_Kb#ô(pG>tԑ3$?(x#o|#)K.IVv4tc  Pv /:/| _ri}qz&:V (@{3g @3~_PWկ~@@ F_W? QWՏ(`_G20 XW:.s˖-|hTj幩F]п7˹zQ6__v]c Xbŋ"6_+Wl>0N(`_G@`.p_G20 XW3~_PF_W?  tկ~(`_G@`կ~#@~_Vկ~@(կ~:QWՏe`կ~# @g0 XW Vկ~m0dŊl_x g,Bgcw~_~_PF_W?  tկ~(`_GԷ^lوC*i#_.sțT[Qˡ_z[m/u?)ue2/>{W ^tES]|ʕ+[.S2 XW Vկ~@@ F_W? QWՏ(`_G20 XW3~_PF_W?  tկ~(`_GF<7nr({zz,Pw@x>k, :T]#DEݸq/Ueor%aÆ.\h@ܾ+Qk׮s)Ueor%z-Zf̘a@:#mȶmҺu<;vlZt&ؾv?%vx~e. :Dlϱ]iGZal|۷)|;؞_{+W,V~\s5fqlϕ(ػ+߿y+4߹vc{bB{wkW\qE:3-hSv<\lEO@Җ-[<ßӜ9s,h3sͷ#cFصkW馛7ߜMfA//Fb:Ah6 vժU;Z[r$(pb;rخcߞ|Bˍ gllϱ]BZql*>~[n%]}uD(pb{28?\ EW]uU7k@(PlC{ 8\KZ}\W| 7W`ė=ܓ?" sq`ʔ)[XP|M___wckڸ-Jx@ԯ~< LBWկ~@(s_W?  tկ~h ࿡{,[쐉rt׽ވׇO(^<]e_nԯ~̀ @C~_PWկ~@@ F_W?4Aq s=闶l{fJJcƤmǥ-現q-W᜴sW>?x5K-hjR{6bo&ӟz[3cjZ?y?muOogɾ`>-S/-\~M-[G>5m߾tSO=kL׮{&?la _Z\YP{`._Nm\Ex1G9trM{sX_Lr~4`o}z(-FYS} Ц<{Kau|җlv{nH7~ٹFxg6@3jО {h MY5ڒɂopt,k]_]OCϿ۰}i7<}L DsS}P=3FsaqǦtAO&F]~l6g{<.:Z=nO;!\ʖTn9&-|mŽqZ[=Y;p/o^zaRψfd(V5.T{KvӘuUK!JV{6=VԃSo:*4bZݸ7di}6/+UfIL >h1[&LH_8}aꌽҩٍYmqUpfϬȂFٸTm 翞65}o}O;j3*@׿Nizg+U t;Xtrʽ?yt?fIS} ̅; kuq {?T#ɇjVY뫫 @6T.d*xs `;ffiGZ=ocOm_c뷊eG_~wUĉ]65?A#[=m`BLW9֗'TM{P{UQ v{ƎϊOS>ܨivnzg+ߌU,|O_w'=we_kٳb1pS} R8F}װf׻=eKߵ~Ҥ/&~vmzg߬Uhc/ҏ?LͿnQ { _7/О6[<~aGm:we#_8a]&npV:p,Lؿ_{:/)_C]];j^3l}*o`6>(Gveޝ~h i(oџ#v;ܣ?6iz#۳/r}uںK}Ξ?۽;/ۋ:{O69G>^=ޏvC̪:]0u|>>J(FK ^LmrKQ=}7Xwu~jf{(Gs? cНuD,x+g#vX_]pmdּݻY١ewdתW1olaXKT @Z]ٗ5>\W ^,L tF6-]@{2q'S;4rwd@(!Fzi„t5?^|*;8o3UYRg]_]O2Ȯó~!mD*kq5'r`AvI;wiOP6!?G=Q?ۓ{tìTm~}jѴgZ_]h0{kOHxaoSTk;f̏T8x);=c4'XTtS=}{=uśk߫Iz{/#xԶo姞 67H~urFL73_}-ɦ{m'g-??F{#p@[4a|Xiiv?z}l:`;vT7cm۳gTeNsa?0wN΃]w6?(K3@#ڳV 2@:ƹ^]YpP ݮwn٦11{n'Y!^t;Խ{I @s.a-:]®W;"l~E vw+[~/sҎq bOtտwf6-lz`wx?MӨ6n?=]u0ih^8O mmnvI7n❾šӚh8J˖-|hTj幩F>|6f|;kZV=nRjy[uֵ OMd7j?>5?:u4?{:i~n|4QѮXu[;vlڽ緼8q{o9ؖ\nE/N _ώjKrIԪ҂ =տmoߝGk-ۏbywZ{ZkkK.{#\) `tutLM{y%U@\AzPmxKc:W6iN̿!nۘP6kg@޲/KޤskAƍwc.1:{^h.k!YA7stNph?{/@+mW|qsdY34/I@8o{5;y͘v:WggLmڻ߿_w W @*9o!{fnq-4: Pn7{~_vhj`@`j={lk*&xH|I eٕ{{vz$1n.120pɦL 4ԯ~:{_W? QWՏ(`_G20 XW3~_@t0@@@@@@@Z^E@uYh"@@@@@@@<؄ntIENDB`pappl-1.4.9/doc/pappl-block.png000066400000000000000000003303111476704353100163330ustar00rootroot00000000000000PNG  IHDR;1gAMA a cHRMz&u0`:pQ<bKGD pHYs.#.#x?vorNTϢwIDATxw|uwBC BAEiR TTT TNςwbŊbWlwُl(*6lxiߝٝwfF;+֟,G3YXD\e+[2G+-1P;XKIff+9>Ra<T`4G۪{ߛ&eXtmj9zɊԀ` a@1AGװĕ5W] ojVd88,6jZbdc- jz\g2G,Cj::ԟힼβ{Xư׌r\j5W_?st9l "u=8낲꼯}f1GϛՍ2 | 5Q^G4Hbdk );N^iR2{,;fʌoδ"uAʋmh9: <žx9# Q .f>7G@~Z)mya'g9vO9%-e#;bGmjDʯ ,i@RpqdEjyqYNd'g=vVsuOe#;쫼BO)Rۘ{9n/d1JXG$ez'N=9۝echTfdzb)a_~y+R$||(NbaRnMܸ>xO5d'~j :>*u]P6þ߼aju}i@GLuЬ8/{;NQ]Юފto낲UGs40AjFz,!e#;w_F[@+ st9,΅.Q\Y@ѣ>^]3ɷQ1ǯ\u/1.Állw:??LY@7'}lc}Ui4\+E?H@$$f@>vK}[8Od~βw=Zs֗ҧPm=33l)VKW^FjY+ iO+P#jmc_%e!>|![X2) ڨ sut9hB=0헵j[B"ubomT`Rn55HVk_k63Rbd[k:Z-MI|t:Y"58 HI>idfkESf68%T~P,I5,;Eu~v}>\Q}he*2W%j99:}/ st4*Nqn4G0W__#d4GwHkz'ƎQ skWf|*ˬP}ltHmR9:-2W_F>KwIVFSp_GygsZcJ-ߧ?bbΰ6G@|Oj)A9s:xܺaVˈ7ZXs9zm 9V]}o>2W/X@ձN(wǎyf1G,V>:Үj}8iyuP nU<-b> P?{;NQ]( =L?j@ 6sWu0WjimR9:Y^J{eG/Y@Sc- Si?gyWUOt|}?L}ds4};d"ԱZs8?Knx.؎./D٫ŏ'P5stDVy~0WX@MH̉T-}81x&+}ފq]vvg)3Ǽc9j 訸;Hz U[^PlV&9:3Re>-U}.L*ڎǩvems5\Ǖ,S^f%n.\ Kcm{^{kWE,#U`P%(e"Q?|AϢ6k*xy/!^WQ&e[@ !ZZDSڽ$'F{w<βSTggoOJQ)g2ˌ$5W]sX9aXꘫ|X_H]WŴxҗ1I;p9ڜb/NZ~%){EuG_y. Ɵ3;w86[yrRB-$avs=_**);ĉOqe۝eOeg՛4~OʝJ07G$a>X+IT)ѥ1OPo˴ s"nv'TC{;NQ)qqms|evs4=6W) S}옔ee$U1w+&pc +P#niE;ퟲ+s2|?[?\ML6Y=UJziO'9svvg)3#ImO~S=}*3~7.PlhsdstO˾ʗylfx0$%aRMsu 6X+pz$mK՛Le<@|ޯK GX@CѶ$os%ȓh5Ne\mRT;hOz1*ps:ƤxI{GRb&趀zŮmL}މy@5B _?ԗVLw|;QW{YvLc^x 8NnQ49>;{Rp9ci9粯}>36%a;}k)n7}n4Gטk8-6stcs-;}{ Nb۝eNϏ/Pu8i%9`K>=vXJ._T; u99Ӧq ?_mb^Ƨ>dJecj~a:4Wך'5`*\X}8A%JY^hJ?_y1???q,;Eu}~Lʶ*N3W fN6y]$9;n}}ڝ h]F\Su옣ԇK~,8̫׼>:aa>u7Q?wǺk2WX@gw^xÇgڨv EOW:cXsx]ҏ/3RxwQ9ݎW<ߚ/Ug:"<9Dhq,;Eu??3Wυ]s/%[.b,'vtGsjѢ(݀ż]]8(3Go[j9\5GKqCƎ:bkyut3ғd~&Uq* +TQ~.t GD5*9ώ˨">}7GWeꅸݚ+kՋhwQ/?'Ē} ۀOVr_4\Yvd~'/ei>.%I5>7Q_rN/_y?c?Ӻj B if[3Ga+7cm~a]Մxq׀zVjJ'"^`^ 1;i:1Ѧ92$>}=b8U~yV$h~M~9!ē/zoӖrѷ[4b:vg)Sכd;Jca9󆭍jk}vsUri lm&}>˝ﮄG*}"iVVU\\8;;aU9 +Ts{(=lcOm1N#?on*( h4\k^FW\ bO628upOqANbZZy%v+h$V?\͉IO]tt ݿβST'yYc:u[>\52ߐ}<T)ˊ\]guJY}\ۇuڇx =؇mvp:êkno8}wSF{_ڞj2#ocDʟ31;ϧyr|Ǧ>,E>{x4Gy=c^FWzI;&ΊL%cqvg|kc\q^Ob:Zj %ƙJst9\mS se\:?\Wo`{,;Eu|~WNl6ju:==/w@|3B-e?9>Gnf%εXb_}9qۍH}XJ} V-!I;&V\k*/.6 8ypuO{DO_NV7ᶩ1߂p ~lw۝eVc s5b}[bjGwy\/qٟ8/F1;>3 5cw/QpW%v^q='dzCMsfҎ3;T_O_Ra|X@</\4+Ɠy1 É޷;NQ]m??QGEO=-=nlj~f?GފAuO쫒zE9K^/O\QL?m͘1Y#vLyx0Vlb J}Y@}KWɂ->6)7m˯4Y1"u~mwݧeN1wۺH`cjqm0?[Mʩr:jd<PSs䭨i^>?)<@Me領7<iLӕ<|=vg}ZvtC;`H[n7WC< reOJaڏc,ONQc(t~"u.YT;:gic3:i4&UrEc>cfKioR;xt)ZX@sZa3G~r F{UR~ŮwQ/_֧#9cOan$DD.~ZY@y"O䚣=8β'u)CȺn.{EG{Fpq#Ϩ6W[=5t[7a~W-(/I'~4Ā$ua/D_ֳKRt9E5 Ҥ{ÊpRWxTzβ'u)-ZFmʟx9y"ugTq>:$F]#?mݯ6jþ*EyަEjJcO54GWM)%ʢ\(p6G}9}(B'e_oW{\}:t)]8Y2яgGZ Mvk|;˞eNh:yhOcJ+4=P.?F܏y<<%?G.w3D{ZՎfzܞ>t9)mF[T$\],hs2x*V }<j~|)Z}o*m9M4β'm)Sj=Z0W_PlՏqߚ+8\ǂ="K\uSs Eu_g_G 91Wi]4ڢZixC hI9;Vn_kwEj@TiestTtqFՎvgٓ)>] uNOHgɖ}>).b_0NYiQyw}h6><&!՞yyO|<ST/iՋ* hp<ӉNQR lw=)NQъۇscvb~-ծ,"q?:^ W^Rj3W?XZJ>ߗdzT߇U6jC7~-AEuum6VTo8LQ H>'1w@2j.3W-`sh^1蚌*]]vgٓ)ћ1N7Es-P7/w@MSsZEw0] L}Ӕ0՗h9z\y1VF^odu`^\YQEO,;ze1M7~Ӵ ٽ#Xܾ+\}UbP2my| hkɱꇝV^>=¯sӢ㏢:x}PT/ɰlweg=1ONO%&z?$}>14tPJ~RXT{wz6i0;>oh̢y7sI |gIKCQ ?P3vtkFՎYv<_S c&hezzbGgV9 WWz\=>HwJ7)\݇SM8i>gU7eNrQ]jKUiR ՍDRn確? 냢|\\kekMvgYv֣$Y@'_t[Tq}{y@T9 Wz,enHQ|>Y/y9Ʋ3=Fm6-]|Ϛj7GYz~-Eu5E5 2 -?QїβGI2GpUbP=3_}<+4J<.[TVGU[@}чIծx\ޯZzo KMT-ߙߴ6)7k.>(ɗE^TvgYvc1@u6HPm#xMTE+$}ÀVWao(v4.0+S|]gTV94vsuOEuE5 2mgklwe T\5:m{mG"ΎXzֹ)9vVñv*)5 } $z a>|OZQPW^1Goh9d)wRs9l:̊ -k񿢺z?AQ H-%lwe\[Ӵ]4+nmR9㼌bqlRNJ}շWDg>|6Ļ<6%>~:=0BQmsT*pXhwsmӻ6>s)\TWJۇfjQ'?5);qt菱YvGs5ħ;4|6ѷ=qEsF9qLTjcfξ|sǻ|hRYTz;󺏵v4'm|Hz`X\Vrk2Ta^Oxvs,\e)=^gc; U|żw\ߛT#i:݇mΊY-ѷT;1fWE=>jX@C8Qh+qx3jM2B+V;:3>s\TWjۇffQ=IRkz =lwe>u4Gw{OO2Nlbc/r̵*/K.P/W}?v~T;&0WVj̾]n.4GӣO^m%=ý=|feVTaYOIj:RmPTL,]$ _G=yβ'd]MjԴڮVʷb,NV(st";P=ώ}3j[=R)mi{6GŴ\M4W*SuXkrGOӭ㶯qul+a`sUb]TGTNqa+V+%zE;^F)6wHw.KCQ ?P3B|a@c:^O8n_;˞eOtYg=9HI_ zstiJ+O4oqZjYfObsҫR._&OZ6Xu%~߇}1Q}+nXjGy\3W[@V:)KZT>5ӊjGS<JH{phBu,{=9eǸm>7YEuSs+PmcZf)ˇgc_2svtE_)^TOA 﫶GS8=Ur-},+߷ElWT_/CF}(j^p^ZηWβ'h)w=_wyZI5J;+־>8)RNܴ۽:/;EuŠ+'}]i?6Wݸ\U]MjI2W>,k+ѷ#G,EmMe{ъ%>5j?w,O{pݫOSTz u"uaܢ:ߞ;>xsu@J>iRT}a2c1ɸձ(4GMa\imT;>5CJgw~Ԫο?mW1eNkZ@.RयthTRN8ޫ{Q-?o?]sUu:~)ݜТz56Wߧ{!:-j:RiPTL) n ^!IY˲STW~+5NtOs:1(0WQT{XErկ>,gP}2sum $ނI^w^\&cha:zQTj@eLQ.#}83:m<擲azMWR[@m9zӘ9˧_>ߗ1_sud?&s#1T\KdQ(IVi2&Nc"/uE5;@̀ҮxaW1eN9;)ovU$13U:+vd:8[|st`w%.K.TQ4.p:)xܡ`PT;ۇ(Rb{8:ÇAwU^|Җ:]+A gIysUbMXO9с$=SxIױcESokW/X s Ew%N6GY@U|'Eam//:0["#Ia`i^Y꘣=7_MRb{ԴDY|Bm<擺թטљ,R|1b9ZS-_y)1>w&؊&stO>U,s'Ȕ}9z)..T*xP9z5M sl&K;E5@w6㖈7{uI]vQWb1GK# (k$ /'}7$l>P?st9Ɨ+gtt*]Am: {M"홴8\ߞoh;n~2W_ey1w.Y[:ìH6 HonՏjaQh4Wg@Imm_/4|\Ll Dls:]c7Gh9}n6GX@X@-XpkZzibEs9ZU^ޯ3W?Js9Zj斟cՒ$3`.c[4\cm&E濻/ʯ~=&ϊ}zn|K1)\˕: hrcZ@'WlYHQhrep9 y*Ps4CY=[RڣXs>nq޶u Y@X_+R )\]C򕗐j1l]HAV^ytk Eٺ՗1/$l~ )Ƥ,sTC is1#`WEq7Wqڇ )}cY\@]1ԎɖwVVKY@癫<̓3زUKM!+&Ոz!sӼ옟-ZlYHQP;gzl]dFY@'!L hm^6Wk}Eu_*8sq2V&sulϙ4anM+_a+@1G-ZlAHC&4)כjLipA\]ij bEmPI]jڨ[29h4Gےp&s4܊ՌՈQs4=iViGZ@㭹$+V3+֟ts9z}h2WUiUeh9}nV7o+~tt5)5 I9&e&/'IBH8h\#!ER rB?9*JGIEB!{6KjɡT/T4>;fB!$d=pEZ@ejHZa9KfBH,۶:VPT2۳-ݲ"BH >P%jrh9YA%C|{tZJB!a3Cԫ% *AFT2ԬU% !V+//,@2%}&~;% !yy6>C+L IKT2 :JB!al6ܧOoZ@USPɰoϞtB!a3CԯKɡTfJڵ0BfJՒZph iv*j֪eszBH{}\Rot VPƒPpnBH<֢0gsh!iJAcRB e۶Y>}B7rhUNA%þ={-[(b!UR.&VP! *ۣkRB *WKjTکdY}-JB!a3V^^pIYҁZ@eKBAWMvJB!a?XPWS͡T *K C!$lmf URȡT: iKl!6??TIZ@e(dho]K C!$lfΟ^-VP6j!'7% !V+//.t VPFPpͣ!6O[g- C]M=C+L IKT2 ;BH,۶:C+ʵ *ӖnBC!$lN0!TIZ@e(dho]K C!$lfΟ^-VP6j!'7% !V+//.t VPFPpͣ!6O[g- C]M=C+L IKT2 ;BH,۶:C+ʵ *ӖnBC!$lN0!TIZDޝT2JfvT՝4yGJZ좣JtRrB!+wT=&UPɰoϞtB!as„ J% @QQ:B!>z{\a QP8?]BH̜??TIZR Ng訑S4B! N4$mN%CNn}MJB!a3V^^pI]*VꨒTrBv;d82dFPpͣ!6O[g- C]Mdku<19g,nuvq\p­BHJ戣Zîú\n=[~_]`[UoX IKT23f % !Ym߷oz.V뤳:tx:=gOkT2ÖnBC!$lN0!TIZjt=k9Z;7lڏ(5!d|μ s)++} QP8?]BH̜??TIZR @5^#tTIi'ػ6NЦ|҂BH͔ Zreui{·iکd͵oI C!$l .K%u T3M#GuTIYizB*ulEOE]XwTIYŷ)/t5ܤy(a!͓YPWS TcWRGUR|M]#!&SWhuY͕RX IKT23f % !Ym߷oz.VLoݭ$BH֭n3 *aKl!6'N~CRM@5Igu訑FzkS:B!Q悵EQV)dJڵ0ydjz2Wl?i|=a9~zZjΪQ# ol BbE۷ GSVΪǷ)کd͵oI S&qG2dרa;ѣG۴gIɈ{}+ԍC+Pu#:Q5҆^B)C^l".[ $k$ ͣNoe[^ !i'׭s9XG >(!sEQVp2@ԐDA%1cPı=;r[pBHZfٶm߾ms9X;ѢJGrbkBWNfq/YNg ?0[A%C=l-1Qy܈~κ%]N81> I59XG?gRS"B!MϬ-@ QP8?]&zƃOv͒%v楗Ze;dB&3/[-?~h$'~]};!\}=m@Q; 967)a|*tv[Ng֯gBR>Xacqh^U'5d]Oy@!$(]oݚO6 IBAey(aXT)w^}uLI;mޏ]k,%|yLuɣ>}*_s/yѐAc]3sg6p3fLoܹ3ۀXq֥_?;⬳촙3m]wŴܙ8H9qP%r9\VՉ.~( B~.v NRP8?]&E Z}{\cֲ(măl=mۋeeQ?at$n ZNK{of/]jn.OgDZ.jy| 3b wm9c|5YYW,Zd{w߸q}ϛӹsO}vr2BՒZphN*_I!=EI@!$9C.z*KڨJ\曔0I( tk7y1QAyg]vYL9}1Os>觟үի%3su]rӽ{|vÆǃ$x#+V^^.ԍC+4~'@A@!$9mZo9|H *u&͛G >w\{_áz*:~}{)*ϥaVyES?hzC+IR' ?+N(!"9a~6r% *=&EubnȔ)Us Y5)(Ǐ)wi׾MN;~x۽Yw?`֭Xj6ibǍg?vv#بٳmְE]s\GrjY~lȔ)6mvʅGau4}nݪ|^qէϚe99yvI'I'[SO>8|x䑕~QG٩ӧ믷'N=vkSs3ml6ۿoP&Q%/Vz;kMz!":UyQQ%/-X1GSaB*ˉxR$Ջ7o6[}uW{/B>!Cz5+a/|ͨٳ+<[8}γ}{g7l-!KV{ew\uZe{wϚVEup컯GMo56D'N 5ސ˷1:n'lDwC BR,}Toim`~5WFHUyeq~=v-%L;b׼=qc3thםrUNC޾ .<]_Zh6o =ztڣ|EuSNx=[mv_}6ʤḞ 5NWKj1uwA!@!Xμ*oA#mmԆDeyYKoI ᄈ&OYVJ_{k[ysDoTfZB^|;6}=^x'~}{#~oV{U}]tQjx 9ݑ$~ ކm .:JOrgi?n BR,~`GUu?ꀦRHXV# 9}Qg7._n,9*Vt? 駣}TxP~>y o[oC=S~wU{VEuNnQMkgmLo$Zg*M :|avS^mc%-[ٞ{V"mpʬWіeȳl۶D"&STlI )!I zvGQaXRU&5XÖRı6uѭ_,+:uvy}z'͛Wa>_qE?[vo5γW|[n߫Wwܸqo}MQm|ʕ!kgx#IBސ˷0m9RB!)TDZV,Dt*_Q}I7DCƼMF͞]N93-ꚵjE}eOPZR ST] BR4?^AQ=7z@QMʊֲϾ曔0)VT_paTӼW};T܃Ǝ[W^iOC3;=zZ ;6-w]&Nmgx#V^^.ԍo_ꤒѕ3fmF@!hfmfsFWQV["**?euh^C*HtE^j|qyKG1y]q+۷ʫ,iSԬ]tvGUtC Ƿ1i㍄ϲml}Cۛ8RG\]ىú^A@!xzEEuG\ͷH z%1)PTdfn1sw^2+h=Ds /Ds^y2jԬYiXܡCpO ĕWƼMf/]* :5{oc< 'M >ߐˡ@:i͕{صBHUqE!q~-\&e۶Y~Ux]h{o7n\R5k촙3mf–+-ґ$3~\?4iE/\aǏ۶ʹFf=z\-%V騑WvbRB!)#[#[$jT^FT27ߤI%3Bkʉ͛m5Tx^3Tx-[8K.~gq-饤ZUawo4WZyyTR7"Q%Wvb{ RB!)'Zխ)!h$ ]%3u^ۨeK{_*}C_]uM RjCVx+~:*ߑW_4w_ҊʬfڻOv|ۖ6Ȯyr:kQX@T( !jT(WC GE E/P0Tf{YuW>lJ>j֪딤zkuT,;u ?*O>v=zXVvv㭺uEaa8C+O( !jTV IKT25j%LշeegWxAcVY TZJ&ְE xa֪m[n!_Uš-:X;a;mL;j(;#C>YwPzbѢAeeg[m!XcG Fh/)-V{=rԱ82:~߷KͶ\TdfCMtԫg7j'ՙ8ު[mfj}̡gՄBE5j zֻ$l`IIrޫʺhMqmnm*pOr7 1–m񺟽l~I/mѤ:[uJ穿!)C+( !jTI *5k(a2~-ٻ[l979;^ee\4?պU۶QO9sbZs5l<ըYN1Ömjg^ziҋ3c.*3qU|PkZBFAQ]Q; 967)a+-P^,;gNw߭/ ZC?8t3eNMDTZa+uvŢE֥_*ojlium[F*/4~nXk/^0:|ǿN4*W^0LoWZyyTR7|CQM!PTVI\An!!xfWmCٸ&z3f<] vS?{?ٕ>kι;m5n}-ۺy߶Y ȫW^i.)qY}]KvM7Y]fcn2Zj>˞x&~lfSۮz9͛o'׭EE ZBFAQ]mԐDA%QFQB ml}C7sh;jB!EuqJv=zB&OUR!)C+QTB!ը>(T24jYC C!$lf>PzZE5!BQꃢ:㵗Q; 9v0B+V^^pI]*;VqCQM!PTh$}&v% !yr:kYTjZE5!BQꃢ:cՐXA%QFQB e۶Y~B7shwՄBE5uJv=zؒRB!asɡJ7$rhwՄBE5tJF-[5k(a!̇ URԒC+&B(Q}PTg6j!'7n\BHܾb .K%u a( !jTt5n!6O[g-B]M=C+&B(Q}PTg+d8jHJB!al6ү_9FKQ\B!$L'SB!ՠF.ݖRB &OUR/ˡ.[ҢB&_Ha&BE5(Ili ׬!63z(Թ5ZrhE&rBOia&BE5(QA{Iv k7._N C!$ln_j׭|TRwI*X!C@QM!jPT5y艷F C!$l\Z:;C+2A;IjHJB!al6ү_phE&h ?nb@!$l_o{8N/H9ՄBE5*:7>ݻےR3B &Ouv\Hwْ8?!yav6`@/Hwqh(Izdچ v櫯ZٳmSN޽[bۭE kܶ>wvy窫l=iK9|:$jPT#:'nԲ-\ BfւԒC+2m׮xfvB / I8$usQYts ]f}yiX\l'N3_{fm%jPT#6]*'7n\s B+vݺK%uЊLp͚ëV 6>)++ ҷ 8$u3쥗^{y*ånfElMoBE5_#Ip뭜c 6O[g-B/ЊL_v5jִ9BHGV^/G[$ PT̅b>;.uz%wBE5vȖ8Q#GrBH]ү_ܷphE&h ?nb@!$l_o{8N/H9$5sVн{JjIV6~f3JKY'PT:]]imIi)!͐)SB^.)C+28?!Jۀ š&{%u~׮ -m˺cm`5jc}׬[ !ՠNM'WjԲ-\ Bfւ~oԒC+2m׮xfvB / I8$5u̘ ,+:6z6ছiӬ[[c׵:u*}.uǜ˖nE5Eui/i\qr1B Wu+ԝC+2v7kfZBH\c/HJ* PT˗[VvvrVС6#~7)6DŽz8E5!ՠN9$}|̞p뭜c 6O[g-B~/ЊL_v996WB W:9*Vn#n޾3OӘmvqVU+kգ>vkтjGPTlIG9B!>vK~~¡Oy7BH,Z \7ZjO]fؒ:iS;﫯|R3wBnOjB(AQMQR >Vӽ-)-<!2eJ{%rhE˒t| !͋eemP_ PTαήY|US̙ՄPTST:|nԲ-\ Bfւ~뭑ԒC+2m׮xfvBfi #Vx9cFآ!4-:u&թk?Iv>Fڍ˗sBHYuJΡXIe;ݛ5Wb@!$l.}1SVVo%ph(IYg-{L:JÜjUmJQME5()σns BueQQy%Z ΃;;' ;B!asʕV^/G[% PT &?ȇܲ+;W\c;qB;{r;﫯|{fb{nz};mwXs>h/[fc>fmߞRmƍ6vJ;ub;;UW[n!O>i#}&y6ajv…9sWQى b+#BQ ̑-iqy`I ! ۷[~BƻC+2AIn!Y~n/H9$}pܸgMvmY=^~eeg]$+6]Yl?ռK>ajРn02g=_}7ZaޖS:kڟv ^b3p[ElFZUs|1i׿8n5iR4j԰of̰I|~PT:]ߧ{w[RZyB!a3dʔPKЊt%3B ʬ[+ PTJO[{} f6 ;O'n1iRt^'zŖ״itٽMvv櫯r^?޲je;n1ǩ?d{yjX\l'y9}2kޡCȩ]8眸E5z-m5g 6,`Z .mvś6 6CM I9$–b'NL<8n\yj}!qۭ^~~um̙Se)Ӗ. ;͚yyv?|EeeuظƒWT\O}RE_hܶWէ-Yb7m.]|߬]>|$kкM'cՠN} %}p뭜c 6O,* [C+2ޒ~ypg؜W^a@!$l^ԫh^Zj숿5)AMK-:48眸9uؔ~H颺ggz1_A7{vK4)?`o^>8cՠNmْpBHؼ}u/o[9"4I?w.;B!ahz+pP_ph(I梲2ۭEEXv͚v+$|ްTfm۴mhvz-]VY5jsvȬYvܹv…vOQY3[Cvĵk}/B&T{_R5+^!]d? &2jt^=zi+kV.h]v t=v%ؾ'l-:v۝:z͜Yi8ehw6m୷Z ,pVo="*O[}E5E5(SU}w%g 6CB!rIZ$=ھݗyii(4Gn}οlm7_c f|Q +/6Ǐʊnq䑕~654&q BQ j֒/X!CHjavb7m!6CM ]I9դzE,IXo͞m6lCf^+ϙv9RT˼v3ù~í{~թa$ !$;TdAv7kfZE C!$l.{qSVVo%ph(Iʅj_~yW4WM_RUeʕa߿~陿=c__o9k}d6#^=zr/\T=ۗysUaQY3IâfEQMQ q$%B̕:p(E&[/ ٜW^!6w\iu >UR/E5K.Z xEbֽz}ײaq]TVV{?JN6{| zf=Nm9fmn5rsNW_\T}9_uCͬa9*jjPT 4IsRB E[:9C+y(I,O窫q۶1N:){YxQ_Q¾ߡ\{S27nzkLW~bQaO, =Oe>Oy8pxGۣ&Ո E5!KҢ !6/YCC+(?u:,YneuΝm7D\:~Ϭ,׌3ʊ/wwǍ1~Euþ#׌nau̝wz*sr"rkQ}STj$E5?X.]lM1BC|WRm@f&~>onݢ*콷(-jZ'L~fΌ}䐰wU[(ת_ߦmr oPQZeՍ۶MHQ}wPTj$E5⥁O;BH,Z \71ZGQMY۷[+{w\T{}v'X돹W>ܗeנAS[x6RST7w_jBQj%iQÆQB ʬNt͡(I2,;'q_F~36o&MBOZlʺuwq>ܺOv~+KVv:ۑdz}{uXQ#ysbRZȒ(Gia(a!͋eemP'6N&jd5WV8aBQ E5Ite"[y5in]=䢋N~kܶme/Hai() Eu|~3Hxs\m @Q]oDCb#WՋG׮eA9uP'5ߕT;'js9 j .(I3bzte1iR<{򈞑]aCiSJs?4jvN~꩔(WAQMQM(P-*@Q]zG$ctflK C u3IV;.Fz:k+\Txy<﫯*{PTSTjo \MUfjRT%Ct+PjBHܽrթW/3URE5<|x"m;,{o2kViZOS~!l~xJ{v:PTG[{STST iH$o!ՄY~nct)[{ST$3}&kX\>{~衰;wb3k>!iv)fmn5k{ŋ?Czt_Ћ/;6() Eud"7E5E5"KҢ !Մy̺ Dq?)jwȐ%^ lo3JK-iӐ}E؏?;W_rj/<gaߣI'2j兝Nc׵ PT))靡IDATvb7m!Մ9uP'1ߕT;.'=ڛ&Izw;ج6C/_Ry=&O]Z+ [M\6I sOD1sV˪Q#{ԩc?_رnۢ}킟&;~3x7E5E5n|ެ-)aE5!$l.{P϶VR+O4skoj$-yIMgڐ'i7?>aB-/7}Sػ }9z]lfQoG~u;evy,kޡ4s3vkO=enz͘a:ˊj|jjEu\oMQMQ Ȓ(Gga(aH߬avGۥw`{ާbg_~{}ߦwϿm߆]|=4ۧ{w td=9Ǝ?<;lC٬ *ͣk2~HŲ26p`w{8vU&)QT#MǦ[(-͚E4=m#(tUqweԨخ2;鄚gbob{w\E5E5I:!@B\oDC2t]D|BjDZ.yz^m8ò}9A6/aɩ3fJ Dڛ&ժ޽_*.sʔHxQk:uV̷bELxEWc:T:@ TIflK C2~߬1ܧ-駨9V^'κ2I\nVH歽)jR->q.;~iE:2D՝Y۷{''=jկOQMQM2Nꭽ))W{K%/L C2~]ON-\&i^aOX֬UZﳏirԉx7oCW:ѭD+)j'鬳,ĿfMcm'dt~_/әwsTkuּCK-Z%̦[g]pլ[ҰzNX& T7E5E5⦁OhFJqEu0'VjY~lȔ)6mvʅGau4ue[V:GvV{e-o7}!'{>؞۸qCR"֯ 5^Vz"nMQ PTgo>hG:Yv͚ Ŝڵ{w6,w_3Ԏ?ߜ#Zyi:a^|Uԡr᯿ځGu+6coW\am=jƴ^mkOf#{/HDQ=w.)O?MQMҮN[{STST .$- 0JqEJW Wu gͪt'_pA[(mKJKþŲ2})^7jl IXVf ;ITwUqdIBVO)Iz&6xӜ9sx晶'^kΑGZQ߾裭ikf̰Fܺ5i~m- 4(ӟvڒ%kyYm!C8٩Z1c쐋..s?4.tb}fv⣏Z:qk{u3;殻l̇:i6g]gOfG jgځ̱۟SySINE s?p\aVis_Ri6RT e'O.]lM1$%ְy 9h=/ѣ+^k~Mw|R Wr{_u}>DEEe(np!-"($ĺꪣRpU+h֊mj~:PPYyo3HNNxisr\sqNE9өӦ:FޒMGjƶ'sISM{iuQ!Or8O,aTw_u4n,>lYƗu}.Is)իc ^ag֫_?>z猪KTwBjG{K*״K&[mU$j'Y=T-@ݱsᛐ7EKEu㤩S+|9S;rz_;N~͔)_׈+LUkNlf5 G؏dQ-UR'LH=aHEN COú1|2[aQ P75!=iQ_X¨N,_qEk6_.o)cvOZCƢYog>81o0wO5k<_՞\4nөSlA}4NQ*_0Aj.Zh犲#R='充5-ZJѤ'пs܀v_I ;^q)|iQmQ @riɒN{\i:'3ҙo^0Ve|$d!FujQ}o$]~#;K..+^}F m~;.PtcŐ,>+'0r-Zu;,x-▻w0 n~qT%E 7t_JEr--!o?Y_PEKչE}tt)IwSO=C΋???ϙ/ob焪{y'6l~Y?+ nQ ժ-!x7%YTWz y'K0b3:{ _#O߰ᆗ_${I__4k^9דKm:uJuj?Q nQ ղ@.$.|P nQmQ @!“'K94KEN^TrN٩g ]w׾}=ʹ旖G=9w# nQ ղΠ:~'ɢfG[T[TBᧉ'L:GrEzֿ-CƗW_&͛']Ƥ3=n]9W!Bh':`Q-2jآEp5qڪU;I9uC6>ܢڢ08PI[9|b :~!xg$]OV=W{q۝wN[A 4i"G㳫Vy]c1%>?!1'=-Zu{,:5vq}->ׯ׏:wL+NK$^T*?ܢڢBf%C~AA-aT#njfR-ت]ʯW/IUxΜhR˽}o=o nq]vwAv-y!sύn5yJwS=ׄ'@*-Z1N/-KKTCfÚK\/,aTc՛#+|2ؾs}b=zĂ´1pĈn߯?[+OlG[TE$I_3lG[T[TQ?M\2tիܿ+E 1ƻt$-&-Zı7ܐmO-޺Ro[o3mRCR=BhXOT-Z$E*ߧBK[9|b O>YF~;xɸǐWe%rE%K2]#*njܻwܢѢVBf%C~AA-a/|XiRG[TE$I_3uH{q7d #H;v 7F_ޞo [} Բe>~Cz'P?ܢE$I55CG[TYT y!'B’a,a>KZ|ᅛt_rIeʸϠA:9G P,%Iv 鮜ɢViHsWr>iXCtǞ{ne>l[7(Ւ!@u$ɢâB( -n|%C]_'-/MmަZ?'{,!@u$ɢâfB&d/(׿%c裤E 'o卼ꪤʨ{}76lК~@u$ɢâjBx/$,t%jn^ OV/-} JסՒ$YTSwXTL? KNzŹ+WZH9Kv%97k2nߵkqv-2B}rZT9BCV XTKdQMaQ P ! [s>F=ۗxH:*oܷ*K{,!@$ɢâfB&d/(׿%Tz)]hQzǽ;,KOeԽmYsiMa?V XTKdQMaQ Ps4 !VnFo810 l6o}ņMͷ*%=x)qƧ-s)Z,9?z jI,;,j!apa0R-l~iA\3hP%@.$ɢâ:M!$UBeuI⒡S^qʕ1 +.NcׄETZ'E`R$jj,ׄS$7!uB(]h޺u'0]c1%>!*q>Q/ $jj,!N\$UR'e%l+/(׿%$)mnlܬYkMa? jɢZ,jx IR%}mUKq7d #IJS˖;:x,%ɢjȺ-BJ:8%IJ\U} !չBx"6#IJgРT{&,%jYdkQE5d]s;ֹ,IR]w?չq$;\$mXqqC .,%jYdkQE5dگ_|nj$Ii2aBs/Wkpt+n޺u'IR.}\{MXTfEWxq5W]x+:ǾN$!͚];.{]7ߜrF'?TܿozIe^vo~QE˗/'???Ж3!gڵl^?ިEvQ6mO{n=Y:眜&_j,ʵ !|;{w8%IJc_~tj?\y!'a<0/-} JukB:!ذE /!h͛W១IxR]7纶oc=7|/(zO^aF}1^|9s{se94s}]Z^TWvyUXTC%Bx.Qc:%IJۼko+ԫWrGaũ\ !4EƖ_PZ |.emc2/̯u{~kkcǁ˼ 5kr1x?YN|}%OS^iEf~q[oe~_]zi >oծ]|db$Ii+5+OCm%,__ IR}8,kB{MXTznKCo1G/\Xuꪔ,x/n=R^_[s]\T|`mEXаa[nI =;Ny;noY5f;+^ZgpCiw><}|g/(wI?SJ-v9+}睤jUc۪עjȊ!./(,3^{͹,IRfVlиqU!,^ sn#IJS˖;:8kB:-߾%WI{ID H睗} 7,OsV\KKc-H~SOeGsOʿ^;B/پ_ToVqEݖ򿥲q%}o]cu-[S~iI_i)i۶I_{XTC6 !||̙eIؗ_6:z-6\y!'a<0/-} JukBf,ǾNƗ|gty -tMj͛F[s][T) |O[*o$E~ӧQoYuN\($뒒ձȼb͓.С_Ƹ#ׯtΝICo1k\sMʯMS,ƢZsǏ;ֹ,IR]w?Λq*INzŹ+Wzp$Ii;-?z]XT׌Euy\z*eTd1Z |9y{s~Mub-nݗe3}41I}c{qFw' >[̔'.^\vIs 7lҢ_"EuwƢگ_|nj$Ii2aBs/WBWܼu8=0]>¶^յsQ]n]|.;ҟ3G΃'ݞFq= L5rd6l|e"GeۛE^%]v={gQmQmQE5ى[kYع,IRڊfJu.B>pu !,[ /$wߍ5K

_4k;xV)iРii;{lw8s{lNŢڢڢjj!wO9ӹ,IR_$I_!U} !<׿nߥ}4Z?1~='k"sSKyoآڢڢjjz!o5vsY[6޿M7gUxŝzsWHv\ !4ꓞx"2ZwZM䓔\_TWV\?tqs)//rqq_Qn=H2ZuIW:noYUТڢڢjjgگ_|nj$Ii;Sfz9P\GJ׿[쁑$Ou¶^ugQ}w&]6}=S,w%ݞ{KJwO|x֫ X#mQ][s]_T}5jT|2^^!gW̞_O/-c~5fkoQmQmQE5dĤ ׮]|db$Ii+5+OCm%l+/(׿F{}76N5!&,֢z'= w;xUu>cF-+z{~Nn?rKcb7/s_~_'Eʿͻfչ뵨o;x{„X?Ey !͚Ţի+tpCAn$NXczIɓk"swN}쾲ƢeՓfδ$%KbR>/B}t$uׄEu\T52δ_c%n+3\TWVZTWI}w?cuւ 66l"r/? 7|'sAAlKIR]wOpF`X$UB !4{_|1e6~%7'޽+Wעzcnou]o][T[;~xR?B T׹UWU7ujl^qW']?ޒS^q=T)!?yծW/~-,UE5հɮKk~ի-b$Ii;Skx9P?[,W$IBzMXTמE/2Rz)tIӦg -g-VwTHqe]0`@_:Ӕq*̹t{Kb;|pep饕؞{)mzOxOċ΢:G_j,aUvŋ-a$Ii+5+kOCmyB8+ps۸%IH{MXT׮Evp7/$}3,R}w~q.ҵkcQR]:*'oou]o]\Tw6,AQAq뭕${ךۻI᠃*6th<˸h1Bܪ[8Αעj(C+\PXg%$)m3z+6h8q_B 5Hm\T-}׮M'=DנAGs{띸hQڅԯN}}qpi7'oou]o]\Ts#S},wa >v֬Zs{)/{ﭔwʗ_ƭ[g/Z?Vݻo} [>Eu<䐖!/O9FǗ,mR|:WaC+0uQB<07ǏսhŊ8bS~u7nx-^|xGV<.]E.9y{~;K/-T:}c~;'өn!n318gcN}M۶KfǢ5kjk)/3~رS:x8c}M:gˎwǼ䜿=;mZ%AW^iQ#E55E59^Ƀ>FykO5ph6/a|m{ QouS1etVfxݺy?zݗ1o7iϏM۶[[lv^aaگͯ_?:w&x%$)mEf? !qh6.O{ᅴ'|_zucAÆZP 9{ߡZ]:纺c}uy)=~&$]c{㏧sCl.͛cOZ_jrE5լ{a_ W_$m[o'BZi/書ǘ1Ei?Aȑqʗ_nqGŮ'PºQ˖qkթS>|x꼟O{ᅬ/Gqϱck$x֫Ɲ;Z^^z?\GW.6m6y*ﺺo=>w=m|shŊ _ϴᅬ^vYr]}nӻw4sfoʽub-7zQ}ԽѢ:;ע\dQM5jB0w3-a$Ii{|ɒئCTpVjz`ٲxK/g̈]ye<{Oq?OzxW_}x/Ǣիk͵ۯʖjӞ_Z<⁗_rK8;o%vM_=N3UGZT+,&B&N|ٖ0[60 P ԅEumno]kʂ-])ٜ,,ɔE5]ϭ^m#IJq矟5+!P XT[T-ҵIImr]-#jj0j[kYFYR4ơj jj;kVrQG3^zcy'4jyߑE55E5Y=bY0xUKIRfVlиqU!PXT[T?[u7n;dQM gQM !|8OL9FǗ,m:tHubC+2gPqƖ;|̏~dQM gQM !<8K >lKIR]{  V,-u_} b74Iww0 N/-uIpdɵD׾}sW[Ԑ~_IjO+!P YT[TvK;Ʃ_},,ɂgVG/xܹTկ?Һu귿uKfJzBV,-uW]Uz]w}%YTSKXTSźV?Kj S M*:?a%Ui3z+6h8wܪBoVj+b-no]Zxbu^~~;yY !|8SL9-o# [c Jz|ɒئCTK;@-W%1I}y Gno]Rbwڴm\Oo/tHBTz!gC’1c,ajآ-:Zo痖V)S 'ӦOjA֮ HC+5}Q-I,ɜE5Uڐdڷo|nj~!Ƹ}׮\ǩ_'gjR-S-_ !wh:Z$jj!aЪ]Ŗ05tQЧ3/,{s>'n#,ZTѬYԟ8@aQ-IE5uE5[aEXoPPXg%L ^TbKKcv,Z 'N[B uE$IT!Ct̙0ՕޭۢZ=dIlӡCwSwh:ƢZ$jj*I³!ap10Ui%%R-hڵ׀Կth:ȢZ$jj*ɵ!aеoU1`Q=c9?6*/Z'~{ZT9cvO<qG_{mv޼8o͚2//ï"6kjݰI ~nz饌?R?!:mZc}v-گ_GǓN׿b?gy㥏=?tizqqw=Գgc)]sOcJlKy$uGQ=T?qb%+!BVzQub#gXHvrգ7E5ℐdhծ]|dbKZyy\GSOori0"*eM7<:4Gܕ+8hԨXبQƗ~} *飏ƶ;mKK7~Ϗ]!7huwqqoc6X_q۝wN{}ZrٳS=n8@3@oוFb!j6YŠޒ0xUK:>K7j~ S7ZT?wu:*h_>\lFVDznC~_1Ǽ2g>} cƍU!P#.{\n IRwWzM2aHXMvK:yUTܦS }9&IU~0;>_{^(<ټMoEoʹ_<3^s5p{|R:~TωWB2 t *8$h];w 2ѢZJhvSv#[XT:+bEL)I^X=n]ʏ> 6jy{ 'd<旖.{ïB<3~NdT4{vħ!6&2۔wr{ԯl IR6`Q=|Sժh qކK8W-a, 1ƾG l,X0opv)oFNTۂ8O2o.Ϊ5{qDl=TݱpalиqsbUi @0ryY'Lz"@mȤ\R#vVE[c O=YYT4uj4rnQ}I'%Wu0?.N[Xkv%uvËYXT~i)> } W=L|~ݺjYT?I?vO sIsg|?nVur/soРIUS٩OCmM`@Z&=eu$XE&6XVVnb3;W-a,uc.h#~ؗ_fuQ}_϶qߏzEuϿl^_mr=|N-kmI&z^ !:3U;N$I܉ӟ#gn  ڵ/Zd cQ])KLJ-Cb-L\GW٢KcƏǫ:5fʩhT!@u#(Mǩʒ@jj꿿ԱG(GŠޒ0xUKJ_:8kbæMS.odQ}SOUck򢺦l=ݱpalиq*ۡh=86ICn L5@9Z> ˝n cQ]K}׮z,gqum6rQ]okOڴ_$!? laO~ce$IYn{M5@ KAG[XTge>4zzx`ƋFmVrm=t[Tۚ6yk^ZR Taԛդx⥖$e /zԛׄ%C׾}㳫VYXTgmةW ۾} IO.]uzI߾K8o͚Zɷ5['m|OjIJС=3yր[gy IR7}ݺ8gnj( !aЪ]E0Y]:n~m}~S$_zuo;co-kmIW٩[:Gu&'Ç$IUܐpI=~S Pn!a%CAaa꫖0t,3'N8+t:wqhQQ4ztc S;v^;{w{;6,4uj|ٱ۾9sʽOfy6;džM\^Tۚ2oڵ׀[Z*#z exg$Iթ̭z ׄ%C׾}+tXѶn8룏ʽWrzu $md׭oRqBHX2l6>h%E&/;vC9' \Tcǎ?{^^)uw,\4nx !qhG>G*罷<KI2lTwR0i !|:oFUփgO?'yg<Y_G_sM,5+qykTu=^n5ye_2^#—5㍿},=;/pC矏w/񉯾QM|>%KbvHF8զ[qb04=è8pmq꿿$)MSU8Xk0[qH^ِd4z%$)m֮ Hšvè]Vt|2 !| 7-a$Ii{|ɒvRzC+:37F=Iv/xq<`+9#<6IrÎp]<`+b/y\F=9(Cܐd4j%$)m֮{|p%@#3\Z'%Iۍ\#n2puHX2t7>jE$)m'LjIJСQX$iE}pzB’e۶E,a$Ii+=;ՒzQC+PcFi IRo7MBX[2ƛ,$펅 cƍԫB}ZZG9gAr?{A0r!B»&~%$)m/YCwSphja=Y=è,"$Iz B F$mڵqNաv 4#3\mA!I^v 43ꐰdإOU10yr%BC+Pgt Ct#F^#zGBT;]=8[lB’e۶E,a$Ii+=;ՒzQC+Pu ÷F33,F^3Gu0AIפLn?kRkOҦ4F^3,FF- 9a%CAaayKIRX06l$qI*ǡ2cX;a{ r^!pv%$)m/YCwSthE5xBsC’aШQ0[6qԷ:U΢jC’a>}ⳫVYHvɩ B@dhٶm|x"KIRڊI^Bh dE5XBzKx0ݱpalؤIzUC+5P# !| wmYH%;z7HV ,! KAFYHuqNա:jq K]ϮZe#IJۉSZR/!:YgQ 5!aвmE0ϙjI(֡Pct !,- XHv…a&KU!>@eაnoFǗ,mw!ջG:ʢr^~anHX21r%$)mϯ[8TKZjgQ 9敖dإOU18eJ%BC+P,  -۶/Zd #IJ[9ԋBmZ`Q 9kޒ0޼`%$)mwvlؤIzUC+3, ' !| wmYH%;z7HV XT@! K#F$ujI}C+s, \ ]"FLI^B(thrE5C’e۶E,a$Ii+3'ՒzQC+, gBX[2ƛ,$ηߎ 4I\R !qhrE5CwÝm0=W;z7HV YT@! K#F$ujI}C+,] ]"FLI^B(thrE5TC’e۶E,a$Ii+3'ՒzQC+P#XT@-`l fkl fk`6[>`5fk0[`6[p5|0[fkpw5|0[p`l fkp5|0[l >l 8l fk`l `l fk58fk0[`5fk5|0[p5`||0[p5l 8>`l fk`6[>l 8>`l fkl fk`6[>`5fk0[`6[p5|0[fkpw5|0[l >l 8l fk`l `l fk58fk0[`5fk5|0[p5^5|0[p>l 80[>l 8fkp`l fkfk0[`5fkl `5fk0[0[p5|0[l 8>58;>l 8fk0[`5fkl 8>lm|l fk`lm5fk0[`fk0[`5|0[p>l 80[>l 8fkp`l fkfk0[`5fk0[`l fkfk0[`5fkl `5fk0[0[p5|0[l 8>58;>lm|l fk`lm5fk0[`fk0[`5|0[p{ >l 8fkp`l fkfk0[`5fkl `5fk0[0[p5|0[l 8>58;>lm|l fk`lm5fk0[`fk0[`5l 8>58;>lm|l fk`lm5fk0[`fk0[`5|0[p縗l Y瘭Q2%lS\*O E%EᖒpIqxPudžwO&uWWO E˜pPɔ;`֒րZZ2[IBppzIQX^R$I|zqx}zQ82iRh%>`$l %I2[g_ ͊JAT%Ea~pVɸ)l-I0[Kd"EaVIQ΃-IҏY%N fkIրZ$uTI=/(.&֒$$IfT2-_RJT%I2[fkI9OmJ0I6K&6N#@>f$l %I2[gp/ KR$IԖN)@σ/I-ܾ 7栿(fkIրZ$uf%E[1-IZmŔ*~/ %EaSP+N%I2[fkI֙%.[:+IR-ec5fkIրZ$u9=2ؔkj$IkjRSwf2[Kd֒$3PTO/fsw7=x$UoﹻCENM@a$l %I2[g`ʔYIQx?+~}b4I6u3SSyʔS֒$$If 2—_$z8Ml-I0[Kd`_gzEI*?Ȋ NU@H3[Kd֒$38OmJL4IW^i) ifkIրZ$urÃ!IRVq'֒$$If \=ww{ $IJM!SC'֒$$Iff뒢fyvUML Hfb&|ʛN_@L3[Kd֒$˟L;_,dӊ@0%I2[fkI%EaAy2g.tI9w_-prfkIրZ$uyuqq8 ¸lw$IԲfp*fkIրZ$u&0o~a~lIWzQtT$Ifkl-I:ٺd\hVR+_}b;ZjSiEỒqS}fkIրZ$uupVygs'K#=;o2-dZ$5`$ll]RMK>,IR=Nk@5l-I0[Kd.4)4)) ޝ+IRu]ۗw_=iRhdZ$5`$ll]\)oc%Iʱ?F8dZ$5`$ll=(\UOϋ}7+IRwSc2ӋUNo@%I2[fkIӋe}᭷uJzK۲u7 '֒$$Iff뒢/L_w$I9g>;c$l %I2[g0[L ۔s;TwN(}L 8Y8f$l %IRFu(.E_|>*IRc=怪g$l %IRfu(Ɣǵkܡ$hkKJ>6-qp2l-I0[KfP<-7^;S7/dZifkIրZ$e0[puY_pܑ$xڮQizfkIրZ$e6[EᖲwGJse[怪g$ww0[Z$ea%_uvGJ=~9 +0[Kd֒$):⎔$){p.L{i4$Ifkl-I2%Ir2 p2M$l-I,%Iid$I2[l-IE$Ir2 p2M$֒$ɢZ$9NI$5%IE$Ir2 L3[Kd֒$-%Ir24p2M$l-I,%Iid$I2[fkI,%Ir2 p2M$֒$ɢZ$9NI$5֒$YTK$''$I2[fkIdQ-Iid$I2[Z$YTK$'4$Ifkl-IڢZ$''$I֒$ɢZ$9NI$5`$ɢ_$''$I2[l-I,%Iid$I2[l-IE$Ir2 p2M$5`$IՒ$9;NI$5%IE$Ir2 L3[Kd֒$-%Ir2 p2M$l-I,%Iid$I2[l-IE$INNId6[Z$YTK$'4Id$I$INifkIրZ$YTK = LtHr2 p2M$l-I,ʯcǖ1Ԯndd$I2[Z$YTK~Cv_OӟF%9N%y dƔdVbE׆Ǚ31>ۖq6m]w2C6{2_CC~wzrbQ}-c~~S^^#<ΒL'ue.Mw?kA^/Hfkl?`|\xb ufL%IRrJqРNaÂԭV?Z_}556n\?e5iR?~$$'4uk]ZoCmiw*pqܸbdݤIصkx1;Nj.'Ι3$._~S,UWsȑbaaJ;iXϞmW?`|/pZ?3Ϝd8fc5oޠfz9{t{dʍ9i8lX8oްk3$jr=bAA~[:.+sO-Q+L'Ne~ǧ>cy roffjnj)ɢZʠw;wntmV,ESO\y.h+W^Z5}"''TaOz=9 0[+wwo fLz%YT#6+s^}?9̟/-_~QlР?}#''T?t{ի<՜ 0[+6m 2c:+ɢZu$UV/'??$W<.pá!Cv{ulӦiӤI${)/kΞ9گ}B5o0LLS`+(ȏ]lQf;2j(֫W)xDI5dEuYs6McӦ1?f ٳ1dQܚ5EvxeK ]χ/صk˜ܳ]3sFOX8+ɢZ5+/]lQA>//ěn:,g~f[QѾ98ZVM]Vzj7$l:;G/[vAׯ}3{x,dQy.^P-n={144ժEu%OϏ}lS[z$l fk9z≱Yi-hpWEjJ>vmGmQ]7'}^ddj:ƒjմl[lVM|$l:=G_{eK^pWEjB{u#蔓?wmXT/[vA|gNsT:/Z59N Ɵ䩩jm룏΋6<>I8<tPXP_G;n8-Ι3Rѧ&N?.Į][3b !oe`\MYsI;7L8jȐ>\xb~cv9 {֍{?y=r2 Ll z7WY׆ю[G,U-]yAebᆪsgEu6ޝSq{y±vqCUM?'p3b˖bq~>KgcyPGffs|XRlݺq\۷&ޅ$'491c(s#kcaasC>4S=zaŊeX LsvN]2[ZT+1+smlRTox`d8&W}1 ^%_Lwċ/^mضmJ5oZl.5eNմi=H4u7phF(]sݻo;[ghޖE޻}p()?.)ٿJ~w*~y~=иn]qiiM8T.^U^(-NW%A/Ԋ.fsl-stK{\7nM:GSC?F3f^緝hޖE+s )SU/v6׹z]{q„UsMs٫̍TL'T}jVIDATկrfܹYu͚2A|T}^[􀬿^X(ֽ;ך.fsl-st>{M~V9wK{o|Qޟmzk9~>eQjK-s}Q]!ļwaxQ]86{>}M{}kWmnѢaړO-^qA?;N٥4Ŏ 6EQTDAҤ JS`hl j4(&Ƃ%FԈI1&ޘbMb)j{Ex~Ovgfg93y̜9>na1u~qDnٝ.eo>?f8Z;l<>)/*N_zfd-ZĈq=Ńo|ㄨg9 ?|6mEb1 ,Iڵk -^5u?w^WiiI򼼿_es6q=cܸc֬1nqcH۷;yEo.zk[>:]FJ-|:_?!zh\͎;vAǑG}nicZ=I7Q-(e_| yѺu/{M[֮-q1$&M7֯6T{-Smg ~Iwћ֢NwvNڤ:^}6R]ƲeC׿Ϧei|o[mk |oA4J^~y^̠w26 >X6딌W%iem;O~2%_Έ&k^EѲeƫ}VuM3LEǼy4&زʥ-W4{}K۷{zE}_׿;t'xY-?ɔO _]梷d{\IDY f}65z>ŠZ-_3(ߋ k/}z?`L\5k`vݵKsk=)2sk^~)iUxi`1Mom-?g{W׎O{}ٮ^SO:tibT}_XG[Vwћ֢N%bb0xÊn}65|>ŠZ-wzV1܇BToXgg?HrAM$z:?NO\r睧/9XLizk ly-ǂ}[MثѮ]˴կM_O~@^/rvR{Ao-T3]4\slQo7ަf_GTKFd<͜AuC׎[_z^+mڤQoŞTY%K yWG/!b[oG-ط=ԢUN{E6}Ҵe$3S~ᦛFe\wq.ji,]zXceP]m;~]rxsOtЫOLU_-OM{9XLizk lr{ڷoGyUx" v)6nln=!4i߼>Ὃ\֠}L/4I[5s~jPuQ-h9}TuPK6J۷?7vءc ض^{矟^PKsϭ/"b[޳(EݫnڴŠZ-'ϴiյUWv.^<ƍѺu߼xꩳ|Ыz\qŰew:j:NĠ:dwR87;vl7c"VuץO8O/\xioςTL]梷4>!өSDsY#5k`ѯo7ަfPGTKdN]:=?^{^]|]z/8^oM7J{]=4?ٴhٲ&o߭k_;>ĠAөS$zաC{v =_tVn;9ϧbz75Š:Sz>;טz|5b1 ,AuΊW}%i9ޢEIN)ιj ;16JJuMwћbPiڴig<]cnݺEXnkMe>GTK^/nmiP]muغ zW\1Ny:T.::ڶmо}8qOxi`1M _bzƾ/h2)ʕ{FyСC-6.zs[ZU8䐝Fo,sC6vs_fo-\ @s-'}Q)--jˠ:1Ao߭ ee{GII!Cv~4&?Z6^'~mʴ߾Q{|q _NEo.zk[K%%It&eڪ]k0`2d8>1s7N|Z|᲼1Mb}965|<bP-y_dݺ 9l\dzM}Po3/JKKjyyAXLTq^imrj߾[o~S͜90寻nDU^OEo.zk[>֘Mmךp1g.;ڠ:mߋ WRռ4pΉ;8ukcԢEI,]zXlXH,4Uq$1wAMW첣n[m.ߋGǠgϮy}>{Ao-hjk͡-A~[ n[}9~9lkʴ,rv>Zys𣏖]wG3S7{o"[s2wzUEӦi/cN۳{lX_zy}N{Ao-hjk͡-A~[ 2~|/[lѺ]MLi͡ kꪋ y*;kXLib-c,8$'EMW1w~L{Q{tϩ6mZ}Ao.zk[>ڠZos{ yPjd:$I_HիW״T7Ay bOg?H,4Tu[l:m/є{ջ>5z]v>ꂼb{>Eo zkGT[m}o zkj2p■Au:G)7n&OKK[ew5o4&?_<4ch&۫~Ѳ5ݵk۔[jtda;vioߣ-\֠}A۠Z6:eӦѯ_/O=uAuۘ:u[3.AyѷVs&4&6k-nڧڴiyMWXs6Y33߿ҜFҕW-\֠}AަZ6Z2{?\fPECɠ#[n.~^bXL leÆ8?m["{촷yܸ7cAhQo=t3:o75EmPm>o%ѩS`nMD}lq?W3 yYpOSxcK/=XLib̝{PƾeҜ?^lgԧرu|Ҭ樂i|Nu>梷 6德) RK$JKK?dPEv޹s8iҾм|'4"dC\%%oH,4$jԫ~k96m3>wJ7:w޹ z *2fʕo75EmPm)MeP6vKsuöܲ]M6!+Vvn"{l:6/kזҥ{z7VFV)ox-i`1M/ڧ!vW^9VQLyi߫g`׿vd„;w޺}b|>Eo zkGT[m}oST %\~5.o*yIh׶^}aoIU|9sn,cK:$b4_{MxVLGԫ~>cv66lk=.}zɉ;S3>Ƴf 75EmPmך~[ ~|Y-]qŰei2kpذ[Tײyٰ"Z(IvZyEa[ouH,4i l=wvOI|ҫ~>>8.]nBy)_^]cӦ;xn}[Ao-hjkbP-M0rnt6E=OOA~m'/+/Kې}&soGcjKĊu. "??=vءc̜90yfJ?#tV$b4m~y)Y}H9~K|Iel)oԩ.xhA.II^{\kXfl?梷 6A~>ŠZ .FlY{lhcÆwĺuKݺl>8wzVN1_r}~p6f/Gki^ v{%qjmpد_է}wIpȌߒ7no=b1 ,IZ`e,nvM.=zti8 O>V j,Z48VZZmgWQRz;iP]*Gk|e׿砺i/~1=niT̚50Yo$8G,^<8xK6;}k-_jFY36v2?8nut75ŠڠZo]zŠZ4=wvlЖmʠ+w~kNqQR}8g?Vƨti2}^obXL"T#}sz*=1Sc-5>eP]Ao-zk^-RžngP]}iXxAu4/??VT6&[.i4{u|G>r*_ Y]W.m /̊]vB}>Eo zk16[^km1"ƍqm'GϞ] UFGNm yX R)S+ƈ4&՟eȐ]5ʛBUS孷Ώ[5'wAB|>Eo zk16[߃jkm1"W׏oӁUb;_Z>ٳk,Z48~ͮyXk֌vTok-ŋ[4&ѵk8>qeGsϝzt)/_u>̔[ܴiyqǘի> |=75ŠڠZoC ~[ ('L.-[Ūw-cڴ6^^ ^ol K#[@ɒ괨σޚ5c뵁w޹ =(5I͏>Zw1&F]krv1u~ni`1Mɠ$vmzuwcgW̜90nadW3 gҫOs."?[n91N:_ݱ^pd4\֠4mkbP-M:ou~6zh\M=~,~qァxTLO 3ƌ=f^xDrˉ_yۯ }t|\y尘7oPL_q^q}bذ1jT(/3g{9-~9b1 ,UVٰ"~ókeˆg'{SO#90.7GC_lzs[ZDe T4&"""zk[EDD EDDb`1MDDDo EDDĠZDDbXL5EDDĠZDDD,4[ EDD,DDDDo zk1i`1MDDD֠[T;XL,֠jDDDDo zk1i`1Mo-"""""bP-""o1 ,"""bP-"""bA4bAo-""""""b1 ,zkjXL[zk1i`1MDDD֠j"""zk@o-""6XL5EDDĠZDDD,4[zkj|i4"""bP-"""bAo1i45j|i`1MDDD֠j"""zk@o-""6XL5EDDĠZDDD,4[zkj|i4"""bP-"""bAo5KDDĠZDDD,DDDրZDDD EDD-4[ZDDD EDDbXL%"""""zkji4[ZDDD EDDbXL5"""v4bZo zk1i`1MDDD֠j"""zk@o-""6bG-__s||~qD}uƍ,\[Ao-cODĠZw$I9,o1 ,?y^}ѧVK"zk5ElTFA/ϋK.92-,4&nAu-<[Z>UD EQhDiif{G{D,4AuE_/zk@o-cѧ E E>gm-=n"bڠ5SERT51g9@Є{n]zKJx%z7qgQaCk1 &>A^}T}x| EGQhy}< ;U۷O?=XL}ˠZ_/;[ZDOշנZDO!Cv\oO4G?ZL,OmPf_Ao-?֧kP-Q#bEʹ?Рbڠ_Eojj(fPmP XLT֠M<"Y_i`1MDgP-[zkĠ\?O+_~tzXnB|^wz\qŰXrx|{g/9#y&wzSqce<ԸG%I}v֐w{Nk=..ȸψ^G'wsr\vqţ_6-נbZ|IeǓN+\slZ{oImyy1ѭ[ݡCCszǎ+Mzh\A{inbXL_׹ŃcHoKJիksAKuPݐ'!O'Sm{[QO֠nZ?nJqu&TvYޛ}[Gǡ\cO//gy/7,w%sm~ zZOnlڴ:>}u뭣S>i)'zk[ΠZ?nJϩG#~IѩSnSOUܘq>Wr_Xk-K'g}rb/{MCnjotiBɸ;vl]*IQrC3^O%5JJxZ5(YO?XV_Lo6 i|-4Z]s~9ѡCz߹ opBc:]mg܃ oO||zk[֠Z?nJ|T6mZdpY˵m2xcqS37|?k5 sP?7Ausbt)=t;v;v1w-Z(vZC5F\ׁ?J_nP kƛo\slO=|͟ S~8R^3L)ۘ-mP}lV5.·uRhQ}Qiz?7nڴ<;l生.S^Ŕ)|>siujPnS^z?t^?Ѥ&ZLikSȭ[~t͠1͍+Sv 7z} GB}^5x|zk[ޠZ?nJ|%1fMWUF۠2g΁նw;˿9sl%bElujx3-,bZ뮫8sFmՍo~xRoFoP2|4ti[7ǹ7~|zk[ߠZ?~biiINnbZ.ОWrꜶ3a€jXlHnӇ._Mo}9sz΍(~neU=3P0 9dj;=go#Gnemm㡇YXr-4Z]%;V,렺ϧ=cdSqV}}c*Wuq cj(ٵɬ{7uB y/7i;CmNx91wAѩS?^S(z i?7Fᬳv?,9̠wݶњү_oPw;j ibZ"Fk3n~ᆑ9v{;zTZo zTT7uB 86)˾¬8ݢ(z a?7F!էoaAu=_o]Ҿ}+ 4Z.ǽ7?߾ :vle[,W_]PoѢEfNO* oO֠.AXAuS].ؠڠ_Xx`lm5^/97\oc(wjP][M}dZ4vӚӠZ. ֳ ߬3VtLcE -?㫿[޺c{MuPcj~a7GUwxkQi CXqDtӨΈ?˴i7ZmվQ][ZZbPmPmP T͠}nw{z߬_rF6YlYy7By|zk[נZ?n :pEº|ն1n/s){q?iny#Q6~nNBX[oTnej7NW_]PB 4Z.k=Սof;O~{jw/?㫿[޺xcqsgPtׁ ?66.I /VJ]f܃bӦY]gc6 ƺ(\vDŽ  zS}bHjli`19 By\~,\xHL|jeƌ>sT?S!=k5譋gP?7{M{Pcj~asP7G?߷i">`i٘B5 wzѯ_7zۭ=v7jjiAZnY~v >n~3U>hYlunK.mWTe֋ߍjO֠.AXܜT7uB ''ƺu^ .Qmmno~33>zɉ9mb/yxhQf7ٳkm}M4_̔藿Ѡ7v{n}L|{rX_{>T7uB鏛f7?eTѺuv}.8pzk66FᣏvmQ~uu׍0wS> G6mZ<06iQ6(ӫڶ.xh=`7k1 ,O٦Mjz=4.Auc?΍Ғn˰a=w-\jO֠C?٠iJܜЗ7AiPhٲo}Lo˥:JVKsjO>?=_Aƺ(;=aVeYuq? qOgw]^pN5(S7 :j&{nbXL_כgݗvZf۷:?z󠺱L1w/?㫿[Z?٠BܜЗ7AO>L{%xyA;o,N{_Gkc͠1Lyq57yX _Ao? lPׁ ?n΃b˛:I8]キ${l|,^<8Z*My1cvw٥sw>я&ş47~qݧƩFO~ 6~~YqC3f/ k/oSS-JbHʹ 㷿'-Z\">{2Q_جA{ٱlِ/~jP~))oSV1kfWDĊxSOYƲeC4_믫g֬i{SoŇ.vV,_~xt>͠1Lٸ2$Ibキ>nUc*WX?.sc m7Au1vPiڶm;9%%IVןm:vl7Vmnѡ>oTMȑOWZZ;1v߽[o*} z?7)۷o={v-hN9eQ Jߕ|JJwءcQkuʹ~f;wYS.۾ a|<S!>k5cq!(6ׁۜ?n΃b˛:t>~zrN׿`!uZHiws?7DžOlِ:5KV?\hoSqw\ AGmjuEwnbXL_שKsR"tԦN|5WwҡC{B{^S!>k5cq? :pc}P]}yT_?!zл90{ĊXh۶eN /8;첣 6~n i桇}.֭PPߟtj9_GmN.&4iO)=6(MZLik:vYߟ&^ziNյփ|dؽ]ԩ`c*WX?.AuYn /ov?\o}A̘q@kܹMLt;yq{flܲ]L_s>\>[U)S+ۘy y?Sc֬ |Oӧl!}iժ46QOSH17ݧ#cqۃuo|x rzcQM:>Z>W7(;9s`vkٲ4>{\w݈x%BwbkuS?hY,YrXlE=cܡ΃|䩧Ϊv]9]c!xZo zTWbc2~өq=u׍/|O矟AN2Ś5c㦛F 7k=.V>5yfJ&}{oIwyJ|Ge]7"Oƻ.)G u-aP_7O*G?IqeGW UF[7~3_iO ֠.AX\lqsR8}[Sz/7 kSIc涟FĿ#}k}@Aoo;ZD`/4"wd1 ,}Gzk[T E沟cLݯsI?<ˋ4wd1 ,Tg}GzkZl?qݠZD_nPQi`1M_j=[T;""jZDD֠ ED jDDbXL_EDDo zkj"bPU&"b1 0_""zk5TgAFA ""bO-""zk[b?Au>{KK慵os""Ӏ:_EDDo zkxWDĠ:foM7os""Ӏ8_EDDo zkxWDĠZDDD,4[Zo-""bP-"""i"""zk5EDDĠZDDD,4[ZDDD EDDbXL[ڠZDDbe&"""zk[AXLi""""""vP}[?;}H[bm9 /izk5,zdyErC?Xus;RDD+,s@[d['+*+2n)|j9 /[譁<_[}oT.K*25+ڑ"""kVvx\TX怆[zkɮN*%32+JO*L'Tą+JkZLa򲘦[zkuuRYUf١"""_Uө 292a1Mo-"""""UoXt~vH/^Ţehxzk5z+w3GCEDD 4k9$"yqAMo-"""""zz3CEDD 47ް}?zk5[g[/H.8^^￿N)X$"q1Mo-"""""zzdxM'ڱ"""~~bQY [zkuIǙ{ر"""[nQ||`AZDDDo EDD9+*u5M|c+""R yy5~*mEEZDDDo EDDY֕˒5]ѵ"""GRS%-k@EDD@>{^DDD^1'鴢"y?Ӆ.BxEvH#%_h]ӧ_1'dY[zk5[g[/Hi½~vH#gkTKx"""zk@o-""βLtK:z\;[DD֛$V,KGo-"""""zz5m;EDD)wݹGiK"""zk@o-""βLFָ$^zNs^z,9NWV&#-c@A|Co-"""""zl{s5m;;oϷEDDwޞW^!O=g  zk5[gu_{-Ʀ=""" MǪ[vSi~? l1Mo-"""""z{mli<;W&Y\P[:dɛlG?iò;W$oXlg p1Mo-"""""zɔ,򠈈s~Q~"-VT$S,Y@/EDDրZDDDoөTn~#PGò?W&["XP[:;%WT$/e{|شqJDDٴqy.+-J:Z§[zku**+wU=߃&""cy{~G.w**(xEDDրZDDDodlow^*d^*+/d (>zk5[`EErƊdS#z\Hqם{"ٴ"9Ò/[s;OZu-_oQ_wx\ֵ9OMbAMo-"""""z\>T>txyhiyy)Mzk5[g~\o觹O_)s??1nGع2yAӤ[zku**+*j{WT&byIxC/6+>“CDD6|R6+~CK.ɋKtEDDրZDDDoE+*tЯ W5+o!V#nNX}"""ۿ7V#~qʮqҨE[Zo EDD9ZQLYQYwPDD"ysEE24?zk5[r_l2̓$""Rܶba%h jzk5[x_"y΃%""ў[,92[zku-UV&#WT$O{EDDj;ȿ"2j[޺t\L^Q[Q|fxxEErY2yŜe@o-"""""zD7A5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^TWA5yeP @^T@:eeݓq3򊤬l IymI"Rv?:bHa'$Rߖ!)+")/HƕHʎJʺ;@!9f|dܸIYIgw!""ҴRnR6dܸ1;h :%ONƯKlx!""0'exXIs eܸIyIY""";#4 P_G&e6ih=餼|j|s"""99߰\zvIym """uMmɩnL˧$eo,oXOd@UFuLoυ3GΊ*DKF/{\;]DD KgGKSygE>=5$IN/Tcg.Y] RHb%q gK'G:_LN/y[>,)+ =05N|XnRJ&_߭~u=n_)*jRʠʠZ)22VJ)  RJ)j+jRʠʠZ)22VJ)  RJ)j+jRʠʠZ)22VJ)  RJ)j+jRʠʠZ)22VJ)  RJ)j+jRʠʠZ)22VJ)  RJ)j+jRʠʠZ)2(r%ILL+I\/""cV$I̠Z)2(r$I"""uȫIl ydPRJTs ydPRJT#$ِHF$Z! ju}/i(eP PvNC$=8q""")s RoJV3jEm{˔fm N$I1‰^)JSk?X}jҡARJ)j"skEO88mZg R*ms1HġAj&u_΍spN,bjA5@Wuc;Ńo=hR*mZ9+"$ ĠZ5$)7 2h Od7ulV#Rik+ei$ ȠZ5:SRijj NIFIRJu_[w8)IZT+jjA5@k$ɳU6&^8F)TZs@TP AARʠ1An:cRik$IR ZTT+  ؼ t5o1QJ)fjQ$I:;B0VJ)jux$>ѮcX*#Rik+ei$ݡ A26VJT$yuŌ$.b#Ri뮿]Ru1|S$':B1VJ)j6Ig.dLpRJ>+ZT+jjA5@YUucbݦu0J) S-Iġ A26VJTyU0k\cR*mZ9+"ItvheP R$I6|~]vUF0J)'WFiҪ o'IC+0jePݬ3D)jS$nxQ_lR*m6].~oJDV(pʠ';#N 1aqܵ)wM>\(߾.碘111qΈkԟNy/ϋ V|\5otܱc|Zuh}O'|ㄘyTwԽ.ߴ<&?=9;(:ܹ޶K{q]o_Р _?!vStܡcԼKhuaqxq_2(0tXi1RJ5|Tk$)qh"`P o8mY ӥUi4XE >Н7 'V}mo۵mz} 0XqDߺ}ңK :wPYQҿeP ЈU}޽OX#RikY_LC+ jeP]oѩ{z&{ͱ :]?~ni?V/}HŐhٶeW IlvŪV(J[+\-K.$PD Au? 6DM$onP~q[vlWﷻM61Ǔj}oZg l}$IuQ(jFS$&U~^lR*m6].nJdC+jeP]V~Ro!7 5I;o,}i:c1G[:V6~mٮe,"JA5@M٪o'`R*m`m9OP Au;x송m[Fȯ1o<>^448uhөMVwRzTה::8c[No;9hplvY|?t{gzf!/iQZyx~Dvi1qq7N!CbbwO߿eP VU}>An:cRikz$IR EȠZTjMҒԎ;vuR,yoImU|\MCv|K[As;yj*q9gbX2z8hAiG|of ln7t5o1QJ)f]=+ՂItvh"eP sޢ-N;e0X["]9,UV1wlPe-cKsrMg-mYu)LǠyPy6$I ߮cX*#Ri\j$Ivwh"fP s?̧tn'rbauϣ{6Ƞz[ͯhݱuo6YmgO1WA5PvJ$qw/6QJ)]e.U7%I2ڡA2i[K[mmߑ|yɑ3~9~%ILyfJoI:)L:=^o 6IgџbRJ>;B`P s_;>i;srn抏+b=N{]N޷^P/{~g<%zMՑi/JTEhU763QJ)OjxM$%T+ꜶmnkHŐzk^W˶-c?۠zϧ>3^OmbCE˟zi/=yF+eP Uw=ּF)TښuT/&I١jePvsQa98^oMˣ.ehiPyz},oUOZF{n}gR@$ɆϿoױ]zaRJuҖUNdwVhB AufltԽAnaKK{T/X{3J{}9*ehٶe|αJTn$I^}Ib#Ri뮿]RuaxS$Z1V24>b r'?=9ux2>v~D8s`_?m.F::*7Vz+eP I<[ `RJ>I(ܡ jePvv=j״9/ywIVuTO~zr &5|Ϧ:Klw8kz+jj&~bݦu0J) S-Iġ jePv-S9 vUǹuT/z u5m _9AiۥmtA13=AA5V}޽OX#RikճR-$IgVh Aub-RnEI,ߴn~>N[4nѦEl߭}8Vx|ʠڠȳ!IlvŪV(J[WT|;IZ 3VuҶAok: mٮnwڥ=ey.}hٶeV[>)?_2ȃ$yu7%I\݋`RJrWt٦KMIvh&ΠZTg/MN;uj?p}S4nyiow)=scﲽ#)IrX'I %=4οeP @&Il7O0QJ)~6+Z0VYmck 3>rCC=8N-{op7ok/|ma9ӣ~QRZRG3~5ÿ eP PVU}>An:cRikr$IR ̀A2Fu]8=1uTwޥs|w.Ӷs<.iQ-=,*7Vס ܪok\cR*mͺzV$ ̈́A2z;m<1`€eu%-J:},NytϜO wTXBA5@ Idf ŪV(J[W(mYZu$Iv/\$IIJn[2<'[6;jP NݻFiNOɔ: [m`EO޵aN>s␅DۮmV:w!ʠ'IfoK(J[_Y]RuvS$ hH+z'EDO^'waIVGdd$I&yG Au1Gʹ vg;uT'pT5TsA _9<:1ӀO4JA5@&Il7O0QJ)~6'bF vK:n0$Y wdߣwre٤A2z;{+v=4An{ņhѺE]uTO}vj383myyܗ4hվUavn7-/ET`U7؃63QJ)OjvM$%2 L}oGjjjIAlj7VYoQ }ƯfήfL꓾}Rr\}~qvlw_29UXw=ּI Sq+'WͿ9=õQJ)Uf_3;ItW[N.5Š|?G3ɇ;O nP 5cn={ͱi2hpN#nDޟs~?'m.mXRA5@$Ioul^X* ˔mw6OoYw.#*Tpu,Zv$mMʠ:,hY&oͯ۾;#oY/nwۼezioO4`cx {$n${quP]uhC㛿qRWVGmT}mܔ$e{joj L-yjpjePӶv[\uLw3Ǚ2N$fvV3wFiѺE,`i<sQ$%oס_2Ƞm$V}C=a&;XAuNTC~8}Mu)FzM\ѠC\OmPM㠺xN nP sҟ6bv~isVM;~PoyڞS.#,K?[t)>qx5I`.6)ʠ:Z&X/eϜr):nѺEyiNozז7`/\r)ʠ sR ZS ݾ,?㺧iOO88Znv1m㺧3R*9uAukR2$I:0NmPMT AuvŰ?94u~;+:l!utܱcTlAu$~}S.N,-Ԅ ~6'k݊Z ujoj ʠz-Zݎ-QIe,~cq~qvvi1`€hUթ{XE >4[uǹqD'1cϦő߶픶* }S=bq]gǒwoo-c׌g[M(j*nzAn::ݺwzx{nsrN 0<S]xm]^^|3bȱG^=}Go6}_qԸb{A#1ļ΋k^O}OoeqiGD!c׽wth]<6V>2ߐs}51r8hA{ޱ۾Ő1ClIY,^8ٿS.wh[9̏='}~' }7v{cCNWMVS->$IINC|۠95A2v+6T~Sy\>>;ַ5ݠ;n>;͠: mQҢ$v QUS t>c͛kհ!c}|reEYzt\L}ʻ;Ɗ{V>\{9-~qUe_Vo}~nW?C3}R7$?P{nڶ/}ٿgV8|`\tE}mv&ܶ$W>qxj*>Η'}BnWE˃O88voz>axl2mmu6~X\tE5kfڏ/&I9\c۠95A2Z IMמ]cKstS [o:*6T''Fv-fH}݈okfIM Q3$I ݮcXªf7piAX{ ޫڶuH֗Gb)Cj(Ś7r>O\K vP$I|˫mn:*>={tUV sϏHg=|MzTC:k祽i/ՠzœ꼘X7{]e_|;I3 T7Ω Au\GˢM6>LqDX:߾T^l|tܡcm[ _?V5of+eP 4ݓ$yu7%I\݋Х!wQmw!D}ĞYő]5=9N[u>~#5cTQ-ƽ7p 8b@ݾqY=ѳFȵV:Շ6%I2:NmPAuܠZT8pr*:>0n[AQߜq9GsZօ-GzƄPUMUHYyf4zkS~}2ꐔmڷ9 XtF,mITQ.w`t!o4⠌>|iyZ9+NZzҡE->gr4@1|~[Ϗ珍vM\u۱[ %QjwZ;ݩ U3uR갶>ꂷ/r\t-!j-^gc}S 'xRʿ8ˮٟM6ev},1&z[lElM/&[ʠ [4rPaC}նf̹7rc~;e<=WVl?p }1x\2.7T=}hg~%3:5Aj5C v7-9/͉q׎Ö{;z=q@^yxnDL9D=ώ_C*~S>ݎ-,<$11QqEߖ.񏎏aWA~S+'z}Gćq{N9c8 8mAu)V?ऋ'G?z47y\˧:-u-3n:woֶ qP=a~;3gz,?>~,u~˻j]vtˍ`\{b)O>WCO~h׻nӺw`jrT<)ǿf_3;$I:nI\T495!>" U3}'훶gs{H)eP 4[C$ŒvevAuToz7&_ }N:DoK4 4UxG{ rqւTkfgM%vk?:㯤|L3Teq_WW :z\.j~xiNjtgOr}۴.Zk61Acv^X_YVoe'"Y|-icPC-ǂhվUAͷR@6I&bz']vվ{zfm]=`C]IiIۚ:ә\pt*TVz;2=[9mhxN|iy}洯n9?F;fztPŇXvw޺s\5^jYk?X}Mܿ0%cdrI~h'"QԊ8pi]vb) f閪 %FuiPTGvDS=WCO>j[%n v\HZoUV>@6xoVGZ9^tAuI}X{qV7NO-Z1WV{˱Oj$IJ>^n;oT4ߨ~Z5ǚYѢugR@3"I>c͛k`8uj=ktʿWۣˎ_1_z>voM׹Cr;m6OڿwW_K-))ڽvOmZ=Fth^c}/+O@ܢUrʐ㉍Ox嫡\;'~|1I#.LIDAT8$%39*$ߎ{w""nɬlYcWjPh퓢M6i{$IeO) feH$>@ҮcX*#<WNLn^T[뮼2!U5A^4dA5O]q.9W}S4'6>go˶1q? QڲڷNdl@E}j#'Y-N^k6VM$/<}8la1Q1aQv=w}ooo* f{$&UN{}4 zAն _QoϹZ_uO_Wm{G;*o}ϺzVTquT/eq E3*m{l[~hնU{ֱqonJe.Uզ$IN)vKzթwKFO;yI۠Z5y׹*Iϴ7R@&IV]$9L#FT?ХC_?)vk}7j;a n%_uT]~t uoTzLcP]}؃>ј{e]j-J9'>ܬ_ ~6j]X/øb95A5յ;A2C?ԞTJT-UH7YiP-oj?*'N_5 ՏHE&8N-#N;"~gi'UOe=ѢUɽ{qo}->qx`$>+STcP]S{T+Ͳǩ{Dņ {R)eP 4s.t=ּ8Ǟulm}i5fV߼>S'WV1s,|jsNnMqPi{b|TjεsR$CB;5A5qP]6VS囖ۋJ)j$ǟ_ iױ^mAWV '̍XuHo 'Vޤ/LJy[a'VW6A^) s;+W{L?bz Wzz;I;-STӼwjojePSb) f{$nPRE]d Hua'Vmڴzw}.Sj};.;.}ҔUV]={~W-g_qvY%bP}wVݺw3ZgFzWV$INj]cܠ?nS{T&VW.=D-ڴ;tݎ-]9,fr26I3qP=)eqkl߁}].o {qosR;WޕO|7UrΨŠz}mvަ}˚͠]v ;hf'ox[ڔ7I\XPC^ny=5A5MqPS{TfPK_>?.x{C)ePmP $IrK!à≍OA7Ҡzӣ$巩]5^+ήS>=lniSw`y)MxP7wS<&9rʐjw͛k5}6C7׾R?$IiAujpj֠:6VJ) feN!Îw`Ǡ:i88o-^8;R^ސmyDmc7ןz!e[Suݶfnٺe|O[pZ}T_)שׂg5AΨv_W5`띶:>l&79[/%Iҹ({ yjpjP86VJ) f$I>N&bAͿ9FL򛾟f̼19ݦTߤU걫j쭿5i;o9~6e9jkߩ}\%9}s:k^նgmڷiV>;zjEi/-G?z4~G./rϽjuCʻ*cõ9 ーu0I]5ѢU$)mܠbT© RJ)jY$ɫI辋iP}gͿy|\wTČ/͈! v*p'ykRnEiL|Z-7kf7ዥV:lӥ}ޔ$IE?쫯STnՅsjT+R@k$OVW7rAu}UVO]S]Ҕu$IN}wA#E}zE-ޖSGf}eK2ޯvE:ŀ#.{Տ~homݮu;_ =ch{侱sJ撚uSTmAݢv]cN}wv{?M!ةoG1gcg^zx6^zš'wj'L?!qP3 |~M~6~_u95A5~>.S{ĠZ)2-U F'6>a\(<&7|.}Ҵߦ6#ݏox4f_3;s\ꉍOĥk.9Nv%e}׾-8-vmMNcq/O;֩~#sO[v{V44:?Sr]UGvDXi]gE >08M^w_j}_AXW괧O>w:*?ԭSV[n' oM5I[o'If<5A5~>VT穽kbPRJTE{$&Uy}37ú|5*戴8;^65~sa\%qǟŷᶸcM ✯|Xjq\XZoWWƼ΋IO_wTĵ?6QzkΊ8+y_;/f]=+ݾ,ė_wX~e{1 bWŅ^7挗[㲇/\/ӯՏ;_3x~eut٦K!$INrh!aST`&qjT+R@i$O*_1ޘN)T27շ/rhM1,;$ -$N]jRʠ(:$U F'6>a R*m 8<Ր$IJZ3VJ) 2;2dر5F0J)9_9'Ր$I:; Z)2aI||nЮc7(J[UB>qx#UTo[Q 2oD#""9sfPyC+Pr".z{^}=oEZQ tZR3%>~q5ܕs]|,P EZՊjE5Х[5~T|GU0""3 7d@RaC+P"jQT+@.poN_89ԁXѷE#!@RT_v)n hafYΊ xbE}//?5;_n˾,nȞݹ^Eugw_/.gjv\u7ԢXs\q/sg~bfp~LUՊjE5!WNxCU❏ܩ9X=!E@ISTwmrq˽qrXU] !Uǝvwp6׹qCcy !xQl>\[L7էuzeӆa_x {W׌_&ZT79N?}ĭ?Z%/)gju4PT@TBv7IIc9x ]hۡ(y.ӳiƆ5ȻW_?r%.~xqW]p4¡|跷so, /zQt)N2u8ݦS.WWkuѿg^zZQ tZAR3%>~q5ܕs]d{,P '[cѦbgj℅r>fZwcE;yxu#.Q۝77]o=WC瞟g~|f훷w_틷>ykq׌YsrQݧO\?9۵q/?o[Uy7W]ow3pwJ;GE5*CV|#w`DD$g|(V!E@.ze#o.q.iuȕ(H}o#?82zW?(;so.ˆn谢:9^5yу>v+NqK?e`sbKpRre}x7o[^Q Oeᙌ7 FDDrۇㄫQuC+(2fH;}/,Z^Z{i7{\zu^{ˏ~e<~]3r{s?+;nus֏vѰ_}t[>/Y5\TWUWŭ5VV1FQ-jhiJ͔0""3sWvBC+(>e7缬wFW0,1z]^ʢϊ/s}z!5!E.*ޜzg5SWT+P[i5~T|GU0""3 7dxRaC+#)n|1e~62 )O&Ze~VTZQ=aA' `hl9ޒ2mK&\T|ugXVQPQ-j! !}ӫ`DD$g֜c}n^>ds Ež'_To7? 0b@8& f=CQ-jF^9 SYw>r FDDrˇbCZMQ]rE?NZ1)c7^RϩƸ'Vą_Zg~bfjUuW0RT~VTwLQ'[_XYwk.k϶wjQ=̏|jQT@ !UEu[LYQݱEڿ^.}so<*}~^2E5ZQR3%>~q5ܕs]t|,P x,o8szlPN]\TŰ՝ST'e ?S?XĊN-SXFjE(շ~4j돪`DD$govVWPTdQ31>nOe-BՅnowgEu|Y2F\6⤟Ӱ 2WXm FE(D]B87HUWŃ/THx@["ۑDVPTdQGhtڮ8|#͋˾,\n+ ϊN/30bI?gX^uZTgۆ!c(EQ %hT x#w`DD$gӡX=!E@.ɢzZ˴e\Z{i%-Koiw5鶢ܢzͳkW=ٿNeĘcբSBx#c19g%c]hǡu%YT_~˸nu9WweJl9ޒ:.t{k/xK׶{|Bq?mԢ:@\~jQT@ijcz<B(whzEuI/yWVTV}., Zcͱ*c9_o|rFGe|+EQ %Ab1UWRT\Q}듷f]Ɗ'V.,G_]w-wWQ}2]UTw~Q?|ArF\6eo.]1QToXV^E^q_Ы41ƘS7BR^KQ]Eߕ廦+Uĝ,9^gѦ8r+;{{k)oY_p2jVu ࢺ35y=fKn^GL3/=36ࢺrPe=.V ?r~ɽSdlؙcWT@EQTJ߶J_]+*+2WV^7}S;sԔQq빋5؜-*n^ޖq~-k#;WQB}z6|oZRʧVkyܘ/.^Q yPTMQBc?<6}.o{cYsZsg}iNs~N훷-??>.%q⒉Y*~ 0(;sq3ڜ8;cCiqAQ(3(_g}l>[YkFWs[EuxS XsE\울{ْxb>朩k[soMG~5q z*;}4}[ܺ@- y?7_l>\t۝yɡ%? PQjy*oS5*n|a)ՅNYEYLUt,~”?[Gt4PT)gNvZ\?'~Y趷;qlQC;Ö;2ϫ.6nO*ڢznWm9aJl|1,Ew|w7{\8r`w{}eYqqqWcͱ',o1~LG̹%m?VzqɱSGht&^GE5h;㎸oVƚę|aA{.վ}>ǚcÏG9?'o6~Lki{gu\f~lN9K'qYΊ>9+.‚Nvuk|9q}s̏ό>?/&{z{㺿_o[Ǒ>9+_o[o{TN+EYT^'?r =E5OQVT+2ȜT7)cWooE(uՊjEugË:~N+fe-QT+)Պj97g!kf~b='RT+r ־ C̏-[=E5K{cՐ^Svܝ[+BT7)|u&STwyno:azݥݵm?wշ-q'geeK]sm\qͳk#{-E5GQ-"".QT@RT(K)EDDХ"""jRI`[/o"""E [ c>"ϘQTPBRɧں=i"""EM$ijv.yTTPBj m].KǦw[T"""Ew[by]ZQ @ Ifya;IUi7w,w@qIFwq{;"""ETTPͶ.nO}h@DDH3MɛNv(>3m]>{*5H}.SgP|R{ۺ]No6DDD,lev>;ŧr"""EOnokkop@Ѷ.rg:@DD25GÜ';T>Hdڿ:~Iū6;I+R[m].:Ҥ:kn䭐J r@qKۻ3k# nδGڿ:Ivr@񫭝E~U"""ݔm57oNn( ]x`@DD2KTi'5$;1NUH'Θq:$ɍNj(-I.xkx1xk>EsNf(=I2=~|ml9֢:kc?6߻;4%Ƀ\ Ѓ"""=)ߒA'1%K |.H'e׶WR7’%g9%JyخJ8$j'/ |/VHI5:<c޼!=)kQ/dZ¼yг,M&Tr$ c?6xQ ""R`v|lM!wR KINV虖'C*y' 6ST9;」RR'гզTr"^swHl{1N RCx)K+Ȧq ['~z1Ss}☏#V+cy]߻0o@'Z0o1I%o$Y$ڲdY!IT.c1:Ƀaɒ\@dzH)1Ƙ繐$ӝLJC*cicO$t!I-e1~+$áv,ԠP^R'B>0 hH05t9JRgB0&y3τTP[{C#@eXIfMM*V^(if,,;ؙ%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ColorSpace1ItEXtexif:ExifOffset102sB) tEXtexif:PhotometricInterpretation2+tEXtexif:PixelXDimension1962p tEXtexif:PixelYDimension1595AIENDB`pappl-1.4.9/doc/pappl-body.md000066400000000000000000001401371476704353100160170ustar00rootroot00000000000000Introduction ============ PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. It is sufficiently general purpose to support any kind of printer or driver that can be used on desktops, servers, and in embedded environments. PAPPL embeds a multi-threaded HTTP / [IPP Everywhere™](https://www.pwg.org/ipp/everywhere.html) server and provides callbacks for a variety of events that allows a GUI or command-line application to interact with both the local user that is running the Printer Application and any network clients that are submitting print jobs, querying printer status and capabilities, and so forth. PAPPL provides a simple driver interface for raster graphics printing, and developers of CUPS Raster drivers will readily adapt to it. PAPPL can also be used with printers that support vector graphics printing although you'll have to develop more code to support them. Drivers provide configuration and capability information to PAPPL, and PAPPL then calls the driver to print things as needed. PAPPL automatically supports printing of JPEG, PNG, PWG Raster, Apple Raster, and "raw" files to printers connected via USB and network (AppSocket/JetDirect) connections. Other formats can be supported through "filter" callbacks you register. PAPPL is Copyright © 2019-2024 by Michael R Sweet and is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used *freely* in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. Requirements ------------ PAPPL requires Microsoft® Windows® 10 or higher or a POSIX-compliant host operating system such as Linux®, macOS®, QNX®, or VxWorks®. On Windows, the provided project files require Visual Studio 2019 or higher. For POSIX hosts, a "make" utility that supports the `include` directive (like GNU make), a C99-compatible C compiler such as GCC or Clang, and the "pkg-config" utility are required along with the following support libraries: - Avahi (0.8 or later) or mDNSResponder for mDNS/DNS-SD support - CUPS (2.2 or later) or libcups (3.0 or later) for the CUPS libraries - GNU TLS (3.0 or later), LibreSSL (3.0 or later), or OpenSSL (1.1 or later) for TLS support - JPEGLIB (8 or later) or libjpeg-turbo (2.0 or later) for JPEG image support (optional for B&W printers) - LIBPNG (1.6 or later) for PNG image support (optional) - LIBPAM for authentication support (optional) - LIBUSB (1.0 or later) for USB printing support (optional) - PAM for authentication support (optional) - ZLIB (1.1 or later) for compression support Getting Prerequisites --------------------- CentOS 8/Fedora 23+/RHEL 8+: sudo dnf groupinstall 'Development Tools' sudo dnf install avahi-devel cups-devel libjpeg-turbo-devel \ libpng-devel libssl-devel libusbx-devel pam-devel zlib-devel Debian/Raspbian/Ubuntu: sudo apt-get install build-essential libavahi-client-dev libcups2-dev \ libcupsimage2-dev libjpeg-dev libpam-dev libpng-dev libssl-dev \ libusb-1.0-0-dev zlib1g-dev macOS (after installing Xcode from the AppStore): (install brew if necessary from ) brew install libjpeg brew install libpng brew install libusb brew install openssl@3 or download, build, and install libjpeg, libpng, libusb, and OpenSSL from source. Windows (after installing Visual Studio 2019 or later) will automatically install the prerequisites via NuGet packages. Building PAPPL -------------- PAPPL uses the usual `configure` script to generate a `make` file: ./configure [options] make Use `./configure --help` to see a full list of options. There is also an Xcode project under the `xcode` directory that can be used on macOS: open xcode/pappl.xcodeproj and a Visual Studio solution under the `vcnet` directory that must be used on Windows. You can test the build by running the PAPPL test program: testsuite/testpappl Installing PAPPL ---------------- Once you have successfully built PAPPL, install it using: sudo make install By default everything will be installed under `/usr/local`. Use the `--prefix` configure option to override the base installation directory. Set the `DESTDIR`, `DSTROOT`, or `RPM_BUILD_ROOT` environment variables to redirect the installation to a staging area, as is typically done for most software packaging systems (using one of those environment variables...) Detecting PAPPL --------------- PAPPL can be detected using the `pkg-config` command, for example: if pkg-config --exists pappl; then ... fi In a makefile you can add the necessary compiler and linker options with: ```make CFLAGS += `pkg-config --cflags pappl` LIBS += `pkg-config --libs pappl` ``` Header Files ------------ PAPPL provides a top-level header file that should be used: ```c #include ``` This header includes all of the base object headers in PAPPL as well as the CUPS header files that provide the HTTP and IPP support functions. API Overview ============ PAPPL provides five main objects: - [The System](@) (`pappl_system_t`): The main object that manages the whole printer application; - [Clients](@) (`pappl_client_t`): The objects that manage client connections; - [Devices](@) (`pappl_device_t`): The objects that manage printer connections; - [Printers](@) (`pappl_printer_t`): The objects that manage printers; and - [Jobs](@) (`pappl_job_t`): The objects that manage print jobs. ![PAPPL Block Diagram::100%](../doc/pappl-block.png) The System ---------- The system is an object of type [`pappl_system_t`](@@) that manages client and device connections, listeners, the log, printers, and resources. It implements a subset of the IPP System Service ([PWG 5100.22](https://ftp.pwg.org/pub/pwg/candidates/cs-ippsystem10-20191122-5100.22.pdf)) with each printer implementing IPP Everywhere™ ([PWG 5100.14](https://ftp.pwg.org/pub/pwg/candidates/cs-ippeve11-20200515-5100.14.pdf)) and some extensions to provide compatibility with the full range of mobile and desktop client devices. In addition, it provides an optional embedded web interface, raw socket printing, and USB printer gadget (Linux only). A system object is created using the [`papplSystemCreate`](@@) function and deleted using the [`papplSystemDelete`](@@) function. Each system manages zero or more [printers](@) which can be accessed using either of the following functions: - [`papplSystemFindPrinter`](@@): Finds the named or numbered print queue, and - [`papplSystemIteratePrinters`](@@): Iterates all print queues managed by the system. The [`papplSystemLoadState`](@@) function is often used to load system values and printers from a prior run which used the [`papplSystemSaveState`](@@) function. IP and domain socket listeners are added using the [`papplSystemAddListeners`](@@) function. The `papplSystemGet` functions get various system values: - [`papplSystemGetAdminGroup`](@@): Gets the administrative group name, - [`papplSystemGetAuthService`](@@): Gets the PAM authorization service name, - [`papplSystemGetContact`](@@): Gets the contact information for the system, - [`papplSystemGetDefaultPrinterID`](@@): Gets the default printer's ID number, - [`papplSystemGetDefaultPrintGroup`](@@): Gets the default print group name, - [`papplSystemGetDNSSDName`](@@): Gets the system's DNS-SD service instance name, - [`papplSystemGetFooterHTML`](@@): Gets the HTML to use at the bottom of the web interface, - [`papplSystemGetGeoLocation`](@@): Gets the geographic location as a "geo:" URI, - [`papplSystemGetHostName`](@@): Gets the hostname for the system, - [`papplSystemGetHostPort`](@@): Gets the port number assigned to the system, - [`papplSystemGetLocation`](@@): Gets the human-readable location, - [`papplSystemGetLogLevel`](@@): Gets the current log level, - [`papplSystemGetMaxClients`](@@): Gets the maximum number of simultaneous network clients that are allowed, - [`papplSystemGetMaxLogSize`](@@): Gets the maximum log file size (when logging to a file), - [`papplSystemGetMaxSubscriptions`](@@): Gets the maximum number of event subscriptions that are allowed, - [`papplSystemGetName`](@@): Gets the name of the system that was passed to [`papplSystemCreate`](@@), - [`papplSystemGetNextPrinterID`](@@): Gets the ID number that will be used for the next printer that is created, - [`papplSystemGetOptions`](@@): Gets the system options that were passed to [`papplSystemCreate`](@@), - [`papplSystemGetOrganization`](@@): Gets the organization name, - [`papplSystemGetOrganizationalUnit`](@@): Gets the organizational unit name, - [`papplSystemGetPassword`](@@): Gets the web interface access password, - [`papplSystemGetServerHeader`](@@): Gets the HTTP "Server:" header value, - [`papplSystemGetSessionKey`](@@): Gets the current cryptographic session key, - [`papplSystemGetTLSOnly`](@@): Gets the "tlsonly" value that was passed to [`papplSystemCreate`](@@), - [`papplSystemGetUUID`](@@): Gets the UUID assigned to the system, and - [`papplSystemGetVersions`](@@): Gets the firmware version numbers that are reported to clients. Similarly, the `papplSystemSet` functions set various system values: - [`papplSystemSetAdminGroup`](@@): Sets the administrative group name, - [`papplSystemSetContact`](@@): Sets the contact information for the system, - [`papplSystemSetDefaultPrinterID`](@@): Sets the ID number of the default printer, - [`papplSystemSetDefaultPrintGroup`](@@): Sets the default print group name, - [`papplSystemSetPrinterDrivers`](@@): Sets the list of printer drivers, - [`papplSystemSetDNSSDName`](@@): Sets the DNS-SD service instance name, - [`papplSystemSetFooterHTML`](@@): Sets the HTML to use at the bottom of the web interface, - [`papplSystemSetGeoLocation`](@@): Sets the geographic location of the system as a "geo:" URI, - [`papplSystemSetHostName`](@@): Sets the system hostname, - [`papplSystemSetLocation`](@@): Sets the human-readable location, - [`papplSystemSetLogLevel`](@@): Sets the current log level, - [`papplSystemSetMaxClients`](@@): Sets the maximum number of simultaneous network clients that are allowed, - [`papplSystemSetMaxLogSize`](@@): Sets the maximum log file size (when logging to a file), - [`papplSystemSetMaxSubscriptions`](@@): Sets the maximum number of event subscriptions that are allowed, - [`papplSystemSetMIMECallback`](@@): Sets a MIME media type detection callback, - [`papplSystemSetNextPrinterID`](@@): Sets the ID to use for the next printer that is created, - [`papplSystemSetOperationCallback`](@@): Sets an IPP operation callback, - [`papplSystemSetOrganization`](@@): Sets the organization name, - [`papplSystemSetOrganizationalUnit`](@@): Sets the organizational unit name, - [`papplSystemSetPassword`](@@): Sets the web interface access password, - [`papplSystemSetSaveCallback`](@@): Sets a save callback, usually [`papplSystemSaveState`](@@), that is used to save configuration and state changes as the system runs, - [`papplSystemSetUUID`](@@): Sets the UUID for the system, and - [`papplSystemSetVersions`](@@): Sets the firmware versions that are reported to clients, ### Logging ### The PAPPL logging functions record messages to the configured log file. The [`papplLog`](@@) records messages applying to the system as a whole while [`papplLogClient`](@@), [`papplLogJob`](@@), and [`papplLogPrinter`](@@) record messages specific to a client connection, print job, or printer respectively. The "level" argument specifies a log level from debugging (`PAPPL_LOGLEVEL_DEBUG`) to fatal (`PAPPL_LOGLEVEL_FATAL`) and is used to determine whether the message is recorded to the log. The "message" argument specifies the message using a `printf` format string. ### Navigation Links ### Navigation links can be added to the web interface using the [`papplSystemAddLink`](@@) function and removed using the [`papplSystemRemoveLink`](@@) function. ### Run Loops ### PAPPL provides two functions to manage its run loops: - [`papplSystemRun`](@@): Runs a system object that you have created and configured, and - [`papplMainloop`](@@): Handles processing standard command-line arguments and sub-commands for a printer application. You can learn more about the second function in the chapter on the [HP Printer Application Example](@). The system will run until it receives a Shutdown-System request, a termination signal, or you call the [`papplSystemShutdown`](@@) function. You can test whether is system is running with the [`papplSystemIsRunning`](@@) function and whether it has been shut down with the [`papplSystemIsShutdown`](@@) function. ### Resources ### PAPPL provides several functions for adding static and dynamic resources to the embedded HTTP server: - [`papplSystemAddResourceCallback`](@@): Adds a callback to serve dynamic content (HTTP GET or POST requests), - [`papplSystemAddResourceData`](@@): Adds a static resource using an `unsigned char` array, - [`papplSystemAddResourceDirectory`](@@): Adds static resource files from a directory, - [`papplSystemAddResourceFile`](@@): Adds a static resource file, - [`papplSystemAddResourceString`](@@): Adds a static resource using a constant string, - [`papplSystemAddStringsData`](@@): Adds a localization file from a constant string, and - [`papplSystemAddStringsFile`](@@): Adds a localization file from a file. Resources may be removed using the [`papplSystemRemoveResource`](@@) function. Localization ------------ Resources added using the [`papplSystemAddStringsData`](@@) and [`papplSystemAddStringsFile`](@@) functions are automatically used to localize the web interface and are provided to clients to localize printer-specific attributes and values. PAPPL provides several additional localization functions that can be used to localize your own dynamic content and/or main loop sub-command: - [`papplClientGetLoc`](@@) returns the collection of localization strings for the client's preferred language, - [`papplClientGetLocString`](@@) returns a localized string for the client's preferred language, - [`papplLocFormatString`](@@) formats a localized string from a given collection, - [`papplLocGetString`](@@) returns a localized string from a given collection, and - [`papplSystemFindLoc`](@@) finds the collection of localization strings for the specified language. Key to these functions is the [`pappl_loc_t`](@@) collection of localization strings, which combines the strings from the built-in PAPPL localizations and any strings file resources that have been added. ### Web Interface Localization ### When localizing the web interface, PAPPL looks up strings for titles and labels passed to [`papplClientHTMLHeader`](@@), [`papplClientHTMLPrinterHeader`](@@), [`papplPrinterAddLink`](@@), and [`papplSystemAddLink`](@@), the footer HTML passed to [`papplSystemSetFooterHTML`](@@), string versions passed to [`papplSystemSetVersions`](@@), and attribute names and values for the "Printing Defaults" web pages. The key string for most localization strings is the English text, for example the title "Example Page" might be localized to French with the following line in the corresponding ".strings" file: "Example Page" = "Exemple de Page"; Attribute names are localized using the IPP attribute name string, for example "smi32473-algorithm" might be localized as: /* English strings file */ "smi32473-algorithm" = "Dithering Algorithm"; /* French strings file */ "smi32473-algorithm" = "Algorithme de Tramage"; Attribute values are localized by concatenating the attribute name with the enum (numeric) or keyword (string) values. For example, the values "ordered" and "contone" might be localized as: /* English strings file */ "smi32473-algorithm.ordered" = "Patterned"; "smi32473-algorithm.contone" = "Continuous Tone"; /* French strings file */ "smi32473-algorithm.ordered" = "À Motifs"; "smi32473-algorithm.contone" = "Tonalité Continue"; Web pages can display a localized HTML banner for the resource path, for example: /* English strings file */ "/" = "Example text for the root web page."; "/network" = "

Example text for the network web page.

"; /* French strings file */ "/" = "Exemple de texte pour la page Web racine."; "/network" = "

Exemple de texte pour la page Web du réseau.

"; Clients ------- The PAPPL client functions provide access to client connections. Client connections and the life cycle of the [`pappl_client_t`](@@) objects are managed automatically by the system object for the printer application. The `papplClientGet` functions get the current values for various client- supplied request data: - [`papplClientGetCSRFToken`](@@): Get the current CSRF token. - [`papplClientGetCookie`](@@): Get the value of a named cookie. - [`papplClientGetForm`](@@): Get form data from the client request. - [`papplClientGetHTTP`](@@): Get the HTTP connection associate with a client. - [`papplClientGetHostName`](@@): Get the host name used for the client request. - [`papplClientGetHostPort`](@@): Get the host port used for the client request. - [`papplClientGetJob`](@@): Get the job object associated with the client request. - [`papplClientGetLoc`](@@): Get the client's preferred localization. - [`papplClientGetLocString`](@@): Get a localized string using the client's preferred localization. - [`papplClientGetMethod`](@@): Get the HTTP request method. - [`papplClientGetOperation`](@@): Get the IPP operation code. - [`papplClientGetOptions`](@@): Get any options from the HTTP request URI. - [`papplClientGetPrinter`](@@): Get the printer object associated with the client request. - [`papplClientGetRequest`](@@): Get the IPP request. - [`papplClientGetResponse`](@@): Get the IPP response. - [`papplClientGetSystem`](@@): Get the system object associated with the client. - [`papplClientGetURI`](@@): Get the HTTP request URI. - [`papplClientGetUsername`](@@): Get the authenticated username, if any. ### Responding to Client Requests ### The [`papplClientRespond`](@@) function starts a HTTP response to a client request. The [`papplClientHTMLHeader`](@@) and [`papplClientHTMLFooter`](@@) functions send standard HTML headers and footers for the printer application's configured web interface while the [`papplClientHTMLEscape`](@@), [`papplClientHTMLPrintf`](@@), [`papplClientHTMLPuts`](@@), and [`papplClientHTMLStartForm`](@@) functions send HTML messages or strings. Use the [`papplClientGetHTTP`](@@) and (CUPS) `httpWrite2` functions to send arbitrary data in a client response. Cookies can be included in web browser requests using the [`papplClientSetCookie`](@@) function. The [`papplClientRespondIPP`](@@) function starts an IPP response. Use the various CUPS `ippAdd` functions to add attributes to the response message. The [`papplClientRespondRedirect`](@@) function sends a redirection response to the client. ### HTML Forms ### PAPPL provides the [`papplClientGetCSRFToken`](@@), [`papplClientGetForm`](@@), [`papplClientHTMLStartForm`](@@), and [`papplClientValidateForm`](@@) functions to securely manage HTML forms. The [`papplClientHTMLStartForm`](@@) function starts a HTML form and inserts a hidden variable containing a CSRF token that was generated by PAPPL from a secure session key that is periodically updated. Upon receipt of a follow-up form submission request, the [`papplClientGetForm`](@@) and [`papplClientValidateForm`](@@) functions can be used to securely read the form data (including any file attachments) and validate the hidden CSRF token. ### Authentication and Authorization ### PAPPL supports both user-based authentication using PAM modules and a simple cookie-based password authentication mechanism that is used to limit administrative access through the web interface. The [`papplHTMLAuthorize`](@@) function authorizes access to the web interface and handles displaying an authentication form on the client's web browser. The return value indicates whether the client is authorized to access the web page. The [`papplIsAuthorized`](@@) function can be used to determine whether the current client is authorized to perform administrative operations and is normally only used for IPP clients. Local users are always authorized while remote users must provide credentials (typically a username and password) for access. This function will return an HTTP status code that can be provided to the [`httpClientSendResponse`](@@) function. The value `HTTP_STATUS_CONTINUE` indicates that authorization is granted and the request should continue. The [`papplGetUsername`](@@) function can be used to obtain the authenticated user identity. Devices ------- The PAPPL device functions provide access to output device connections and to list available output devices. Output devices are accessed using Uniform Resource Identifier (URI) strings such as "file:///path/to/file-or-directory", "socket://11.22.33.44", and "usb://make/model?serial=number". The follow URI schemes are supported by PAPPL: - "dnssd": Network (AppSocket) printers discovered via DNS-SD/mDNS (Bonjour), - "file": Local files and directories, - "snmp": Network (AppSocket) printers discovered via SNMPv1, - "socket": Network (AppSocket) printers using a numeric IP address or hostname and optional port number, and - "usb": Local USB printer. Custom device URI schemes can be registered using the [`papplDeviceAddScheme`](@@) function. The [`papplDeviceList`](@@) function lists available output devices, providing each available output device to the supplied callback function. The list only contains devices whose URI scheme supports discovery, at present USB printers and network printers that advertise themselves using DNS-SD/mDNS and/or SNMPv1. The [`papplDeviceOpen`](@@) function opens a connection to an output device using its URI. The [`papplDeviceClose`](@@) function closes the connection. The [`papplDevicePrintf`](@@), [`papplDevicePuts`](@@), and [`papplDeviceWrite`](@@) functions send data to the device, while the [`papplDeviceRead`](@@) function reads data from the device. The `papplDeviceGet` functions get various device values: - [`papplDeviceGetID`](@@): Gets the current IEEE-1284 device ID string, - [`papplDeviceGetMetrics`](@@): Gets statistical information about all communications with the device while it has been open, and - [`papplDeviceGetStatus`](@@): Gets the hardware status of a device mapped to the [`pappl_preason_t`](@@) bitfield. Printers -------- Printers are managed by the system and are represented by the [`pappl_printer_t`](@@) type. Each printer is connected to a device and uses a driver to process document data and produce output. PAPPL supports raster printers out-of-the-box and provides filter callbacks to support other kinds of printers. Printers are created using the [`papplPrinterCreate`](@@) function and deleted using the [`papplPrinterDelete`](@@) function. Each printer has zero or more jobs that are pending, processing (printing), or completed which can be access using any of the following functions: - [`papplPrinterFindJob`](@@): Finds the numbered print job, - [`papplPrinterIterateActiveJobs`](@@): Iterates active print jobs managed by the printer, - [`papplPrinterIterateAllJobs`](@@): Iterates all print jobs managed by the printer, and - [`papplPrinterIterateCompletedJobs`](@@): Iterates completed print jobs managed by the printer. The `papplPrinterGet` functions get various printer values: - [`papplPrinterGetContact`](@@): Gets the contact information, - [`papplPrinterGetDeviceID`](@@): Gets the IEEE-1284 device ID, - [`papplPrinterGetDeviceURI`](@@): Gets the device URI, - [`papplPrinterGetDNSSDName`](@@): Gets the DNS-SD service instance name, - [`papplPrinterGetDriverAttributes`](@@): Gets the driver IPP attributes, - [`papplPrinterGetDriverData`](@@): Gets the driver data, - [`papplPrinterGetDriverName`](@@): Gets the driver name, - [`papplPrinterGetGeoLocation`](@@): Gets the geographic location as a "geo:" URI, - [`papplPrinterGetID`](@@): Gets the ID number, - [`papplPrinterGetImpressionsCompleted`](@@): Gets the number of impressions (sides) that have been printed, - [`papplPrinterGetLocation`](@@): Gets the human-readable location, - [`papplPrinterGetMaxActiveJobs`](@@): Gets the maximum number of simultaneous active (queued) jobs, - [`papplPrinterGetMaxCompletedJobs`](@@): Gets the maximum number of completed jobs for the job history, - [`papplPrinterGetMaxPreservedJobs`](@@): Gets the maximum number of preserved jobs (with document data) for the job history, - [`papplPrinterGetName`](@@): Gets the name, - [`papplPrinterGetNextJobID`](@@): Gets the ID number of the next job that is created, - [`papplPrinterGetNumberOfActiveJobs`](@@): Gets the current number of active jobs, - [`papplPrinterGetNumberOfCompletedJobs`](@@): Gets the current number of completed jobs in the job history, - [`papplPrinterGetNumberOfJobs`](@@): Gets the total number of jobs in memory, - [`papplPrinterGetOrganization`](@@): Gets the organization name, - [`papplPrinterGetOrganizationalUnit`](@@): Gets the organizational unit name, - [`papplPrinterGetPath`](@@): Gets the path of a printer web page, - [`papplPrinterGetPrintGroup`](@@): Gets the print authorization group name, - [`papplPrinterGetReasons`](@@): Gets the "printer-state-reasons" bitfield, - [`papplPrinterGetState`](@@): Gets the "printer-state" value, - [`papplPrinterGetSupplies`](@@): Gets the current supply levels, and - [`papplPrinterGetSystem`](@@): Gets the system managing the printer. Similarly, the `papplPrinterSet` functions set those values: - [`papplPrinterSetContact`](@@): Sets the contact information, - [`papplPrinterSetDNSSDName`](@@): Sets the DNS-SD service instance name, - [`papplPrinterSetDriverData`](@@): Sets the driver data and attributes, - [`papplPrinterSetDriverDefaults`](@@): Sets the driver defaults, - [`papplPrinterSetGeoLocation`](@@): Sets the geographic location as a "geo:" URI, - [`papplPrinterSetImpressionsCompleted`](@@): Sets the number of impressions that have been printed, - [`papplPrinterSetLocation`](@@): Sets the human-readable location, - [`papplPrinterSetMaxActiveJobs`](@@): Sets the maximum number of jobs that can be queued, - [`papplPrinterSetMaxCompletedJobs`](@@): Sets the maximum number of completed jobs that are kept in the job history, - [`papplPrinterSetMaxPreservedJobs`](@@): Sets the maximum number of preserved jobs (with document data) that are kept in the job history, - [`papplPrinterSetNextJobID`](@@): Sets the ID number of the next job that is created, - [`papplPrinterSetOrganization`](@@): Sets the organization name, - [`papplPrinterSetOrganizationalUnit`](@@): Sets the organizational unit name, - [`papplPrinterSetPrintGroup`](@@): Sets the print authorization group name, - [`papplPrinterSetReadyMedia`](@@): Sets the ready (loaded) media, - [`papplPrinterSetReasons`](@@): Sets or clears "printer-state-reasons" values, - [`papplPrinterSetSupplies`](@@): Sets supply level information, and - [`papplPrinterSetUSB`](@@): Sets the USB vendor ID, product ID, and configuration options. ### Accessing the Printer Device ### When necessary, the device associated with a printer can be opened with the [`papplPrinterOpenDevice`](@@) function and subsequently closed using the [`papplPrinterCloseDevice`](@@) function. ### Controlling Printers ### Printers are stopped using the [`papplPrinterPause`](@@) function and started using the [`papplPrinterResume`](@@) function. New jobs can be held using the [`papplPrinterHoldNewJobs`](@@) function and later released for printing using the [`papplPrinterReleaseHeldNewJobs`](@@) function. ### Navigation Links ### Navigation links can be added to the web interface using the [`papplPrinterAddLink`](@@) function and removed using the [`papplPrinterRemoveLink`](@@) function. Jobs ---- Jobs are managed by the system and are represented by the [`pappl_job_t`](@@) type. Jobs are created and deleted automatically by the system object for the printer application. The `papplJobGet` functions get the current values associated with a job: - [`papplJobGetAttribute`](@@): Gets a named Job Template attribute, - [`papplJobGetData`](@@): Gets driver-specific processing data, - [`papplJobGetFilename`](@@): Gets the filename of the document data, - [`papplJobGetFormat`](@@): Gets the MIME media type for the document data, - [`papplJobGetID`](@@): Gets the job's numeric ID, - [`papplJobGetImpressions`](@@): Gets the number of impressions (sides) in the document, - [`papplJobGetImpressionsCompleted`](@@): Gets the number of impressions (sides) that have been printed, - [`papplJobGetMessage`](@@): Gets the current processing message (if any), - [`papplJobGetName`](@@): Gets the job name/title, - [`papplJobGetPrinter`](@@): Gets the printer for the job, - [`papplJobGetReasons`](@@): Gets the "job-state-reasons" bitfield, - [`papplJobGetState`](@@): Gets the "job-state" value, - [`papplJobGetTimeCompleted`](@@): Gets the UNIX time when the job completed, aborted, or was canceled, - [`papplJobGetTimeCreated`](@@): Gets the UNIX time when the job was created, - [`papplJobGetTimeProcessed`](@@): Gets the UNIX time when processing started, and - [`papplJobGetUsername`](@@): Gets the name of the user that created the job. Similarly, the `papplJobSet` functions set the current values associated with a job: - [`papplJobSetData`](@@): Sets driver-specific processing data, - [`papplJobSetImpressions`](@@): Sets the number of impressions (sides) in the job, - [`papplJobSetImpressionsCompleted`](@@): Updates the number of impressions (sides) that have been completed, - [`papplJobSetMessage`](@@): Set the current processing message, and - [`papplJobSetReasons`](@@): Sets or clears bits in the "job-state-reasons" bitfield. ### Controlling Jobs ### The [`papplJobCancel`](@@) function cancels processing of a job while the [`papplJobIsCanceled`](@@) function returns whether a job is in the canceled state (`IPP_JSTATE_CANCELED`) or is in the process of being canceled (`IPP_JSTATE_PROCESSING` and `PAPPL_JREASON_PROCESSING_TO_STOP_POINT`). The [`papplJobHold`](@@) function holds a job while the [`papplJobRelease`](@@) function releases a job for printing. ### Processing Jobs ### PAPPL stores print options in [`pappl_pr_options_t`](@@) objects. The [`papplJobCreatePrintOptions`](@@) function creates a new print option object and initializes it using the job's attributes and printer defaults. The creator of a print options object must free it using the [`papplJobDeletePrintOptions`](@@) function. The [`papplJobOpenFile`](@@) function opens a file associated with the job. The file descriptor must be closed by the caller using the `close` function. The primary document file for a job can be retrieved using the [`papplJobGetFilename`](@@) function, and its format using the [`papplJobGetFormat`](@@) function. Filters allow a printer application to support different file formats. PAPPL includes raster filters for PWG and Apple raster documents (streamed) as well as JPEG and PNG image files. Filters for other formats or non-raster printers can be added using the [`papplSystemAddMIMEFilter`](@@) function. The [`papplJobFilterImage`](@@) function converts raw image data to raster data suitable for the printer, and prints using the printer driver's raster callbacks. Raster filters that output a single page can use this function to handle the details of scaling, cropping, color space conversion, and dithering for raster printers. A raster filter that needs to print more than one image must use the raster callback functions in the [`pappl_pr_driver_data_t`](@@) structure directly. Filters that produce non-raster data can call the `papplDevice` functions to directly communicate with the printer in its native language. The HP Printer Application Example ================================== This chapter will guide you through creating a simple PCL printer application based on the old CUPS "rastertohp" filter. The complete code can be found in the [hp-printer-app](https://github.com/michaelrsweet/hp-printer-app) project and serves as an overgrown "Hello, World!" program for PAPPL. The Main Loop ------------- All printer applications require some sort of a main loop for processing IPP requests, printing files, and so forth. PAPPL provides the [`papplMainloop`](@@) convenience function that provides a standard command-line interface, and in the "hp-printer-app" project the `main` function just calls `papplMainloop` to do all of the work: ```c int main(int argc, char *argv[]) { return (papplMainloop(argc, argv, /*version*/"1.0", /*footer_html*/NULL, (int)(sizeof(pcl_drivers) / sizeof(pcl_drivers[0])), pcl_drivers, pcl_callback, pcl_autoadd, /*subcmd_name*/NULL, /*subcmd_cb*/NULL, /*system_cb*/NULL, /*usage_cb*/NULL, /*data*/NULL)); } ``` As you can see, we pass in the command-line arguments, a version number ("1.0") for our printer application, a list of drivers supported by the printer application, a callback for the driver that will configure a printer for a named driver, and a callback for automatically adding printers. The "footer_html" argument can be provided to override the default footer text that appears at the bottom of the web interface. In this case we are passing `NULL` to use the default. The drivers list is a collection of names, descriptions, IEEE-1284 device IDs, and extension pointers. Ours looks like this for HP DeskJet, HP LaserJet, and a generic PCL driver: ```c static pappl_pr_driver_t pcl_drivers[] =// Driver information { /* name */ /* description */ /* device ID */ /* extension */ { "hp_deskjet", "HP Deskjet", NULL, NULL }, { "hp_generic", "Generic PCL", "CMD:PCL;", NULL }, { "hp_laserjet", "HP LaserJet", NULL, NULL } }; ``` [The driver callback](@) is responsible for providing the data associated with each driver, while [the auto-add callback](@) tells PAPPL which driver to use for the printers it finds. The "subcmd\_name" and "subcmd\_cb" arguments specify a custom sub-command for the printer application along with a function to call. Since this printer application does not have a custom sub-command, we pass `NULL` for both. The "system_cb" argument specifies a callback for creating the [system object](#the-system). We pass `NULL` because we want the default system object for this printer application, which supports multiple printers and a web interface. The "usage_cb" argument specifies a callback from displaying the program usage message. Passing `NULL` yields the default usage message. The "data" argument specifies a pointer that will be passed to any of the callback functions. We pass `NULL` since we do not have any extra contextual information to provide to the callbacks. The `papplMainloop` function runs until all processing for the current sub-command is complete, returning the exit status for the program. ### Configuration and State Files ### Printer applications using the main loop API use a configuration file for server options and a state file for printers and jobs. The files are named based on the base name of the printer application, in this case "hp-printer-app.conf" for the server options and "hp-printer-app.state" for the state file. Server options are loaded from the "/etc" and "/usr/local/etc" directories on regular Unix/Linux systems, "$HOME/snap/BASENAME/common" for snap-based applications, and "/Library/Application Support" on macOS. The Driver Callback ------------------- The PAPPL driver callback is called when the system is creating a new printer object. It receives pointers to the system, driver name, device URI, a driver data structure, an IPP attributes pointer, and the callback data, and it returns a boolean indicating whether the driver callback was successful: ```c typedef bool (*pappl_pr_driver_cb_t)(pappl_system_t *system, const char *driver_name, const char *device_uri, pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data); ``` A driver callback can communicate with the printer via its device URI as needed to configure the driver, however our printer application doesn't need to do that. The first thing our `pcl_callback` function does is to set the printer callbacks in the driver data structure: ```c driver_data->printfile_cb = pcl_print; driver_data->rendjob_cb = pcl_rendjob; driver_data->rendpage_cb = pcl_rendpage; driver_data->rstartjob_cb = pcl_rstartjob; driver_data->rstartpage_cb = pcl_rstartpage; driver_data->rwriteline_cb = pcl_rwriteline; driver_data->status_cb = pcl_status; ``` The `pcl_print` function prints a raw PCL file while the `pcl_r` functions print raster graphics. The `pcl_status` updates the printer status. Next is the printer's native print format as a MIME media type, in this case HP PCL: ```c driver_data->format = "application/vnd.hp-pcl"; ``` The default orientation and print quality follow: ```c driver_data->orient_default = IPP_ORIENT_NONE; driver_data->quality_default = IPP_QUALITY_NORMAL; ``` Then the values for the various drivers. Here are the HP DeskJet driver settings: ```c if (!strcmp(driver_name, "hp_deskjet")) { /* Make and model name */ strncpy(driver_data->make_and_model, "HP DeskJet", sizeof(driver_data->make_and_model) - 1); /* Pages-per-minute for monochrome and color */ driver_data->ppm = 8; driver_data->ppm_color = 2; /* Three resolutions - 150dpi, 300dpi (default), and 600dpi */ driver_data->num_resolution = 3; driver_data->x_resolution[0] = 150; driver_data->y_resolution[0] = 150; driver_data->x_resolution[1] = 300; driver_data->y_resolution[1] = 300; driver_data->x_resolution[2] = 600; driver_data->y_resolution[2] = 600; driver_data->x_default = driver_data->y_default = 300; /* Four color spaces - black (1-bit and 8-bit), grayscale, and sRGB */ driver_data->raster_types = PAPPL_PWG_RASTER_TYPE_BLACK_1 | PAPPL_PWG_RASTER_TYPE_BLACK_8 | PAPPL_PWG_RASTER_TYPE_SGRAY_8 | PAPPL_PWG_RASTER_TYPE_SRGB_8; /* Color modes: auto (default), monochrome, and color */ driver_data->color_supported = PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_AUTO_MONOCHROME | PAPPL_COLOR_MODE_COLOR | PAPPL_COLOR_MODE_MONOCHROME; driver_data->color_default = PAPPL_COLOR_MODE_AUTO; /* Media sizes with 1/4" left/right and 1/2" top/bottom margins*/ driver_data->num_media = (int)(sizeof(pcl_hp_deskjet_media) / sizeof(pcl_hp_deskjet_media[0])); memcpy(driver_data->media, pcl_hp_deskjet_media, sizeof(pcl_hp_deskjet_media)); driver_data->left_right = 635; // 1/4" left and right driver_data->bottom_top = 1270; // 1/2" top and bottom /* 1-sided printing only */ driver_data->sides_supported = PAPPL_SIDES_ONE_SIDED; driver_data->sides_default = PAPPL_SIDES_ONE_SIDED; /* Three paper trays (MSN names) */ driver_data->num_source = 3; driver_data->source[0] = "tray-1"; driver_data->source[1] = "manual"; driver_data->source[2] = "envelope"; /* Five media types (MSN names) */ driver_data->num_type = 5; driver_data->type[0] = "stationery"; driver_data->type[1] = "bond"; driver_data->type[2] = "special"; driver_data->type[3] = "transparency"; driver_data->type[4] = "photographic-glossy"; } ``` Finally, we fill out the ready and default media for each media source (tray), putting US Letter paper in the regular trays and #10 envelopes in any envelope tray: ```c // Fill out ready and default media (default == ready media from the first source) for (i = 0; i < driver_data->num_source; i ++) { pwg_media_t *pwg; /* Media size information */ /* Use US Letter for regular trays, #10 envelope for the envelope tray */ if (!strcmp(driver_data->source[i], "envelope")) strncpy(driver_data->media_ready[i].size_name, "env_10_4.125x9.5in", sizeof(driver_data->media_ready[i].size_name) - 1); else strncpy(driver_data->media_ready[i].size_name, "na_letter_8.5x11in", sizeof(driver_data->media_ready[i].size_name) - 1); /* Set margin and size information */ if ((pwg = pwgMediaForPWG(driver_data->media_ready[i].size_name)) != NULL) { driver_data->media_ready[i].bottom_margin = driver_data->bottom_top; driver_data->media_ready[i].left_margin = driver_data->left_right; driver_data->media_ready[i].right_margin = driver_data->left_right; driver_data->media_ready[i].size_width = pwg->width; driver_data->media_ready[i].size_length = pwg->length; driver_data->media_ready[i].top_margin = driver_data->bottom_top; strncpy(driver_data->media_ready[i].source, driver_data->source[i], sizeof(driver_data->media_ready[i].source) - 1); strncpy(driver_data->media_ready[i].type, driver_data->type[0], sizeof(driver_data->media_ready[i].type) - 1); } } driver_data->media_default = driver_data->media_ready[0]; return (true); ``` The Auto-Add Callback --------------------- The PAPPL auto-add callback is called when processing the "autoadd" sub-command. It is called for each new device and is responsible for returning the name of the driver to be used for the device or `NULL` if no driver is available: ```c typedef const char *(*pappl_ml_autoadd_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data); ``` Our `pcl_autoadd` function uses the IEEE-1284 device ID string to determine whether one of the drivers will work. The [`papplDeviceParseID`](@@) function splits the string into key/value pairs that can be looked up using the `cupsGetOption` function: ```c const char *ret = NULL; // Return value int num_did; // Number of device ID key/value pairs cups_option_t *did; // Device ID key/value pairs const char *cmd, // Command set value *pcl; // PCL command set pointer // Parse the IEEE-1284 device ID to see if this is a printer we support... num_did = papplDeviceParseID(device_id, &did); ``` The two keys we care about are the "COMMAND SET" (also abbreviated as "CMD") for the list of document formats the printer supports and "MODEL"/"MDL" for the model name. We are looking for the "PCL" format and one of the common model names for HP printers: ```c // Look at the COMMAND SET (CMD) key for the list of printer languages,,, if ((cmd = cupsGetOption("COMMAND SET", num_did, did)) == NULL) cmd = cupsGetOption("CMD", num_did, did); if (cmd && (pcl = strstr(cmd, "PCL")) != NULL && (pcl[3] == ',' || !pcl[3])) { // Printer supports HP PCL, now look at the MODEL (MDL) string to see if // it is one of the HP models or a generic PCL printer... const char *mdl; // Model name string if ((mdl = cupsGetOption("MODEL", num_did, did)) == NULL) mdl = cupsGetOption("MDL", num_did, did); if (mdl && (strstr(mdl, "DeskJet") || strstr(mdl, "Photosmart"))) ret = "hp_deskjet"; // HP DeskJet/Photosmart printer else if (mdl && strstr(mdl, "LaserJet")) ret = "hp_laserjet"; // HP LaserJet printer else ret = "hp_generic"; // Some other PCL laser printer } cupsFreeOptions(num_did, did); return (ret); ``` The File Printing Callback -------------------------- The file printing callback is used when printing a "raw" (printer-ready) file from a client: ```c typedef bool (*pappl_pr_printfile_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); ``` This callback will sometimes send some printer initialization commands followed by the job file and then any cleanup commands. It may also be able to count the number of pages (impressions) in the file, although that is not a requirement. For the HP Printer Application our `pcl_print` function just copies the file from the job to the device and assumes that the file contains only one page: ```c int fd; // Job file ssize_t bytes; // Bytes read/written char buffer[65536]; // Read/write buffer papplJobSetImpressions(job, 1); fd = open(papplJobGetFilename(job), O_RDONLY); while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) { if (papplDeviceWrite(device, buffer, (size_t)bytes) < 0) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to send %d bytes to printer.", (int)bytes); close(fd); return (false); } } close(fd); papplJobSetImpressionsCompleted(job, 1); return (true); ``` The Raster Printing Callbacks ----------------------------- The PAPPL raster printing callbacks are used for printing PWG and Apple raster documents, JPEG and PNG images, and other formats that end up as raster data: ```c typedef bool (*pappl_pr_rstartjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); typedef bool (*pappl_pr_rstartpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); typedef bool (*pappl_pr_rwriteline_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned y, const unsigned char *line); typedef bool (*pappl_pr_rendpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); typedef bool (*pappl_pr_rendjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); ``` Each of the raster printing callbacks is expected to send data to the printer using the provided "device" pointer. The "job" argument provides the current job object and the "options" pointer provides the current [print job options](#pappl_pr_options_s). The "page" argument specifies the current page number staring at `0`. The `pappl_pr_rstartjob_cb_t` function is called at the beginning of a job to allow the driver to initialize the printer for the current job. The `pappl_pr_rstartpage_cb_t` function is called at the beginning of each page to allow the driver to do any per-page initialization and/or memory allocations and send any printer commands that are necessary to start a new page. The `pappl_pr_rwriteline_cb_t` function is called for each raster line on the page and is typically responsible for dithering and compressing the raster data for the printer. The `pappl_pr_rendpage_cb_t` function is called at the end of each page where the driver will typically eject the current page. The `pappl_pr_rendjob_cb_t` function is called at the end of a job to allow the driver to send any cleanup commands to the printer. The Identification Callback --------------------------- The PAPPL identification callback is used to audibly or visibly identify the printer being used: ```c typedef void (*pappl_pr_identify_cb_t)(pappl_printer_t *printer, pappl_identify_actions_t actions, const char *message); ``` The most common identification method is `PAPPL_IDENTIFY_ACTIONS_SOUND` which should have the printer make a sound. The `PAPPL_IDENTIFY_ACTIONS_DISPLAY` and `PAPPL_IDENTIFY_ACTIONS_SPEAK` methods use the "message" argument to display or speak a message. Finally, the `PAPPL_IDENTIFY_ACTIONS_FLASH` method flashes a light on the printer. The HP Printer Application does not have an identification callback since most PCL printers lack a buzzer or light that can be remotely activated. > *Note:* IPP Everywhere™ requires all printers to support identification. > A warning message is logged by PAPPL whenever a driver does not set the > `identify_cb` member of the printer driver data structure. The Status Callback ------------------- The PAPPL status callback is used to update the printer state, supply levels, and/or ready media for the printer: ```c typedef bool (*pappl_pr_status_cb_t)(pappl_printer_t *printer); ``` The callback can open a connection to the printer using the [`papplPrinterOpenDevice`](@@) function. The Self-Test Page Callback --------------------------- The PAPPL self-test page callback is used to generate a self-test page for the printer: ```c typedef const char *(*pappl_printer_testpage_cb_t)(pappl_printer_t *printer, char *buffer, size_t bufsize); ``` When the callback returns a filename (copied to the specified buffer), that file will be queued as a job for the printer. The callback can also try opening the device using the [`papplPrinterOpenDevice`](@@) function to send a printer self-test command instead - in this case the callback must return `NULL` to indicate there is no file to be printed. pappl-1.4.9/doc/pappl.html000066400000000000000000016011141476704353100154260ustar00rootroot00000000000000 PAPPL v1.4 Programmers Manual

PAPPL v1.4 Programmers Manual

Michael R Sweet

Copyright © 2020-2025 by Michael R Sweet

Contents

Introduction

PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. It is sufficiently general purpose to support any kind of printer or driver that can be used on desktops, servers, and in embedded environments.

PAPPL embeds a multi-threaded HTTP / IPP Everywhere™ server and provides callbacks for a variety of events that allows a GUI or command-line application to interact with both the local user that is running the Printer Application and any network clients that are submitting print jobs, querying printer status and capabilities, and so forth.

PAPPL provides a simple driver interface for raster graphics printing, and developers of CUPS Raster drivers will readily adapt to it. PAPPL can also be used with printers that support vector graphics printing although you'll have to develop more code to support them. Drivers provide configuration and capability information to PAPPL, and PAPPL then calls the driver to print things as needed. PAPPL automatically supports printing of JPEG, PNG, PWG Raster, Apple Raster, and "raw" files to printers connected via USB and network (AppSocket/JetDirect) connections. Other formats can be supported through "filter" callbacks you register.

PAPPL is Copyright © 2019-2024 by Michael R Sweet and is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information.

Requirements

PAPPL requires Microsoft® Windows® 10 or higher or a POSIX-compliant host operating system such as Linux®, macOS®, QNX®, or VxWorks®. On Windows, the provided project files require Visual Studio 2019 or higher. For POSIX hosts, a "make" utility that supports the include directive (like GNU make), a C99-compatible C compiler such as GCC or Clang, and the "pkg-config" utility are required along with the following support libraries:

  • Avahi (0.8 or later) or mDNSResponder for mDNS/DNS-SD support

  • CUPS (2.2 or later) or libcups (3.0 or later) for the CUPS libraries

  • GNU TLS (3.0 or later), LibreSSL (3.0 or later), or OpenSSL (1.1 or later) for TLS support

  • JPEGLIB (8 or later) or libjpeg-turbo (2.0 or later) for JPEG image support (optional for B&W printers)

  • LIBPNG (1.6 or later) for PNG image support (optional)

  • LIBPAM for authentication support (optional)

  • LIBUSB (1.0 or later) for USB printing support (optional)

  • PAM for authentication support (optional)

  • ZLIB (1.1 or later) for compression support

Getting Prerequisites

CentOS 8/Fedora 23+/RHEL 8+:

sudo dnf groupinstall 'Development Tools'
sudo dnf install avahi-devel cups-devel libjpeg-turbo-devel \
    libpng-devel libssl-devel libusbx-devel pam-devel zlib-devel

Debian/Raspbian/Ubuntu:

sudo apt-get install build-essential libavahi-client-dev libcups2-dev \
    libcupsimage2-dev libjpeg-dev libpam-dev libpng-dev libssl-dev \
    libusb-1.0-0-dev zlib1g-dev

macOS (after installing Xcode from the AppStore):

(install brew if necessary from <https://brew.sh>)
brew install libjpeg
brew install libpng
brew install libusb
brew install openssl@3

or download, build, and install libjpeg, libpng, libusb, and OpenSSL from source.

Windows (after installing Visual Studio 2019 or later) will automatically install the prerequisites via NuGet packages.

Building PAPPL

PAPPL uses the usual configure script to generate a make file:

./configure [options]
make

Use ./configure --help to see a full list of options.

There is also an Xcode project under the xcode directory that can be used on macOS:

open xcode/pappl.xcodeproj

and a Visual Studio solution under the vcnet directory that must be used on Windows.

You can test the build by running the PAPPL test program:

testsuite/testpappl

Installing PAPPL

Once you have successfully built PAPPL, install it using:

sudo make install

By default everything will be installed under /usr/local. Use the --prefix configure option to override the base installation directory. Set the DESTDIR, DSTROOT, or RPM_BUILD_ROOT environment variables to redirect the installation to a staging area, as is typically done for most software packaging systems (using one of those environment variables...)

Detecting PAPPL

PAPPL can be detected using the pkg-config command, for example:

if pkg-config --exists pappl; then
    ...
fi

In a makefile you can add the necessary compiler and linker options with:

CFLAGS  +=      `pkg-config --cflags pappl`
LIBS    +=      `pkg-config --libs pappl`

Header Files

PAPPL provides a top-level header file that should be used:

#include <pappl/pappl.h>

This header includes all of the base object headers in PAPPL as well as the CUPS header files that provide the HTTP and IPP support functions.

API Overview

PAPPL provides five main objects:

  • The System (pappl_system_t): The main object that manages the whole printer application;

  • Clients (pappl_client_t): The objects that manage client connections;

  • Devices (pappl_device_t): The objects that manage printer connections;

  • Printers (pappl_printer_t): The objects that manage printers; and

  • Jobs (pappl_job_t): The objects that manage print jobs.

PAPPL Block Diagram::100%

The System

The system is an object of type pappl_system_t that manages client and device connections, listeners, the log, printers, and resources. It implements a subset of the IPP System Service (PWG 5100.22) with each printer implementing IPP Everywhere™ (PWG 5100.14) and some extensions to provide compatibility with the full range of mobile and desktop client devices. In addition, it provides an optional embedded web interface, raw socket printing, and USB printer gadget (Linux only).

A system object is created using the papplSystemCreate function and deleted using the papplSystemDelete function. Each system manages zero or more printers which can be accessed using either of the following functions:

The papplSystemLoadState function is often used to load system values and printers from a prior run which used the papplSystemSaveState function.

IP and domain socket listeners are added using the papplSystemAddListeners function.

The papplSystemGet functions get various system values:

Similarly, the papplSystemSet functions set various system values:

Logging

The PAPPL logging functions record messages to the configured log file. The papplLog records messages applying to the system as a whole while papplLogClient, papplLogJob, and papplLogPrinter record messages specific to a client connection, print job, or printer respectively.

The "level" argument specifies a log level from debugging (PAPPL_LOGLEVEL_DEBUG) to fatal (PAPPL_LOGLEVEL_FATAL) and is used to determine whether the message is recorded to the log.

The "message" argument specifies the message using a printf format string.

Navigation links can be added to the web interface using the papplSystemAddLink function and removed using the papplSystemRemoveLink function.

Run Loops

PAPPL provides two functions to manage its run loops:

  • papplSystemRun: Runs a system object that you have created and configured, and

  • papplMainloop: Handles processing standard command-line arguments and sub-commands for a printer application.

You can learn more about the second function in the chapter on the HP Printer Application Example.

The system will run until it receives a Shutdown-System request, a termination signal, or you call the papplSystemShutdown function. You can test whether is system is running with the papplSystemIsRunning function and whether it has been shut down with the papplSystemIsShutdown function.

Resources

PAPPL provides several functions for adding static and dynamic resources to the embedded HTTP server:

Resources may be removed using the papplSystemRemoveResource function.

Localization

Resources added using the papplSystemAddStringsData and papplSystemAddStringsFile functions are automatically used to localize the web interface and are provided to clients to localize printer-specific attributes and values.

PAPPL provides several additional localization functions that can be used to localize your own dynamic content and/or main loop sub-command:

Key to these functions is the pappl_loc_t collection of localization strings, which combines the strings from the built-in PAPPL localizations and any strings file resources that have been added.

Web Interface Localization

When localizing the web interface, PAPPL looks up strings for titles and labels passed to papplClientHTMLHeader, papplClientHTMLPrinterHeader, papplPrinterAddLink, and papplSystemAddLink, the footer HTML passed to papplSystemSetFooterHTML, string versions passed to papplSystemSetVersions, and attribute names and values for the "Printing Defaults" web pages. The key string for most localization strings is the English text, for example the title "Example Page" might be localized to French with the following line in the corresponding ".strings" file:

"Example Page" = "Exemple de Page";

Attribute names are localized using the IPP attribute name string, for example "smi32473-algorithm" might be localized as:

/* English strings file */
"smi32473-algorithm" = "Dithering Algorithm";

/* French strings file */
"smi32473-algorithm" = "Algorithme de Tramage";

Attribute values are localized by concatenating the attribute name with the enum (numeric) or keyword (string) values. For example, the values "ordered" and "contone" might be localized as:

/* English strings file */
"smi32473-algorithm.ordered" = "Patterned";
"smi32473-algorithm.contone" = "Continuous Tone";

/* French strings file */
"smi32473-algorithm.ordered" = "À Motifs";
"smi32473-algorithm.contone" = "Tonalité Continue";

Web pages can display a localized HTML banner for the resource path, for example:

/* English strings file */
"/" = "Example text for the root web page.";
"/network" = "<p>Example text for the <em>network</em> web page.</p>";

/* French strings file */
"/" = "Exemple de texte pour la page Web racine.";
"/network" = "<p>Exemple de texte pour la page Web du <em>réseau</em>.</p>";

Clients

The PAPPL client functions provide access to client connections. Client connections and the life cycle of the pappl_client_t objects are managed automatically by the system object for the printer application.

The papplClientGet functions get the current values for various client- supplied request data:

Responding to Client Requests

The papplClientRespond function starts a HTTP response to a client request. The papplClientHTMLHeader and papplClientHTMLFooter functions send standard HTML headers and footers for the printer application's configured web interface while the papplClientHTMLEscape, papplClientHTMLPrintf, papplClientHTMLPuts, and papplClientHTMLStartForm functions send HTML messages or strings. Use the papplClientGetHTTP and (CUPS) httpWrite2 functions to send arbitrary data in a client response. Cookies can be included in web browser requests using the papplClientSetCookie function.

The papplClientRespondIPP function starts an IPP response. Use the various CUPS ippAdd functions to add attributes to the response message.

The papplClientRespondRedirect function sends a redirection response to the client.

HTML Forms

PAPPL provides the papplClientGetCSRFToken, papplClientGetForm, papplClientHTMLStartForm, and papplClientValidateForm functions to securely manage HTML forms.

The papplClientHTMLStartForm function starts a HTML form and inserts a hidden variable containing a CSRF token that was generated by PAPPL from a secure session key that is periodically updated. Upon receipt of a follow-up form submission request, the papplClientGetForm and papplClientValidateForm functions can be used to securely read the form data (including any file attachments) and validate the hidden CSRF token.

Authentication and Authorization

PAPPL supports both user-based authentication using PAM modules and a simple cookie-based password authentication mechanism that is used to limit administrative access through the web interface.

The papplHTMLAuthorize function authorizes access to the web interface and handles displaying an authentication form on the client's web browser. The return value indicates whether the client is authorized to access the web page.

The papplIsAuthorized function can be used to determine whether the current client is authorized to perform administrative operations and is normally only used for IPP clients. Local users are always authorized while remote users must provide credentials (typically a username and password) for access. This function will return an HTTP status code that can be provided to the httpClientSendResponse function. The value HTTP_STATUS_CONTINUE indicates that authorization is granted and the request should continue. The papplGetUsername function can be used to obtain the authenticated user identity.

Devices

The PAPPL device functions provide access to output device connections and to list available output devices. Output devices are accessed using Uniform Resource Identifier (URI) strings such as "file:///path/to/file-or-directory", "socket://11.22.33.44", and "usb://make/model?serial=number". The follow URI schemes are supported by PAPPL:

  • "dnssd": Network (AppSocket) printers discovered via DNS-SD/mDNS (Bonjour),

  • "file": Local files and directories,

  • "snmp": Network (AppSocket) printers discovered via SNMPv1,

  • "socket": Network (AppSocket) printers using a numeric IP address or hostname and optional port number, and

  • "usb": Local USB printer.

Custom device URI schemes can be registered using the papplDeviceAddScheme function.

The papplDeviceList function lists available output devices, providing each available output device to the supplied callback function. The list only contains devices whose URI scheme supports discovery, at present USB printers and network printers that advertise themselves using DNS-SD/mDNS and/or SNMPv1.

The papplDeviceOpen function opens a connection to an output device using its URI. The papplDeviceClose function closes the connection.

The papplDevicePrintf, papplDevicePuts, and papplDeviceWrite functions send data to the device, while the papplDeviceRead function reads data from the device.

The papplDeviceGet functions get various device values:

Printers

Printers are managed by the system and are represented by the pappl_printer_t type. Each printer is connected to a device and uses a driver to process document data and produce output. PAPPL supports raster printers out-of-the-box and provides filter callbacks to support other kinds of printers.

Printers are created using the papplPrinterCreate function and deleted using the papplPrinterDelete function. Each printer has zero or more jobs that are pending, processing (printing), or completed which can be access using any of the following functions:

The papplPrinterGet functions get various printer values:

Similarly, the papplPrinterSet functions set those values:

Accessing the Printer Device

When necessary, the device associated with a printer can be opened with the papplPrinterOpenDevice function and subsequently closed using the papplPrinterCloseDevice function.

Controlling Printers

Printers are stopped using the papplPrinterPause function and started using the papplPrinterResume function. New jobs can be held using the papplPrinterHoldNewJobs function and later released for printing using the papplPrinterReleaseHeldNewJobs function.

Navigation links can be added to the web interface using the papplPrinterAddLink function and removed using the papplPrinterRemoveLink function.

Jobs

Jobs are managed by the system and are represented by the pappl_job_t type. Jobs are created and deleted automatically by the system object for the printer application.

The papplJobGet functions get the current values associated with a job:

Similarly, the papplJobSet functions set the current values associated with a job:

Controlling Jobs

The papplJobCancel function cancels processing of a job while the papplJobIsCanceled function returns whether a job is in the canceled state (IPP_JSTATE_CANCELED) or is in the process of being canceled (IPP_JSTATE_PROCESSING and PAPPL_JREASON_PROCESSING_TO_STOP_POINT).

The papplJobHold function holds a job while the papplJobRelease function releases a job for printing.

Processing Jobs

PAPPL stores print options in pappl_pr_options_t objects. The papplJobCreatePrintOptions function creates a new print option object and initializes it using the job's attributes and printer defaults. The creator of a print options object must free it using the papplJobDeletePrintOptions function.

The papplJobOpenFile function opens a file associated with the job. The file descriptor must be closed by the caller using the close function. The primary document file for a job can be retrieved using the papplJobGetFilename function, and its format using the papplJobGetFormat function.

Filters allow a printer application to support different file formats. PAPPL includes raster filters for PWG and Apple raster documents (streamed) as well as JPEG and PNG image files. Filters for other formats or non-raster printers can be added using the papplSystemAddMIMEFilter function.

The papplJobFilterImage function converts raw image data to raster data suitable for the printer, and prints using the printer driver's raster callbacks. Raster filters that output a single page can use this function to handle the details of scaling, cropping, color space conversion, and dithering for raster printers. A raster filter that needs to print more than one image must use the raster callback functions in the pappl_pr_driver_data_t structure directly.

Filters that produce non-raster data can call the papplDevice functions to directly communicate with the printer in its native language.

The HP Printer Application Example

This chapter will guide you through creating a simple PCL printer application based on the old CUPS "rastertohp" filter. The complete code can be found in the hp-printer-app project and serves as an overgrown "Hello, World!" program for PAPPL.

The Main Loop

All printer applications require some sort of a main loop for processing IPP requests, printing files, and so forth. PAPPL provides the papplMainloop convenience function that provides a standard command-line interface, and in the "hp-printer-app" project the main function just calls papplMainloop to do all of the work:

int
main(int  argc, char *argv[])
{
  return (papplMainloop(argc, argv,
                        /*version*/"1.0",
                        /*footer_html*/NULL,
                        (int)(sizeof(pcl_drivers) / sizeof(pcl_drivers[0])),
                        pcl_drivers, pcl_callback, pcl_autoadd,
                        /*subcmd_name*/NULL, /*subcmd_cb*/NULL,
                        /*system_cb*/NULL,
                        /*usage_cb*/NULL,
                        /*data*/NULL));
}

As you can see, we pass in the command-line arguments, a version number ("1.0") for our printer application, a list of drivers supported by the printer application, a callback for the driver that will configure a printer for a named driver, and a callback for automatically adding printers.

The "footer_html" argument can be provided to override the default footer text that appears at the bottom of the web interface. In this case we are passing NULL to use the default.

The drivers list is a collection of names, descriptions, IEEE-1284 device IDs, and extension pointers. Ours looks like this for HP DeskJet, HP LaserJet, and a generic PCL driver:

static pappl_pr_driver_t pcl_drivers[] =// Driver information
{   /* name */          /* description */       /* device ID */ /* extension */
  { "hp_deskjet",       "HP Deskjet",           NULL,           NULL },
  { "hp_generic",       "Generic PCL",          "CMD:PCL;",     NULL },
  { "hp_laserjet",      "HP LaserJet",          NULL,           NULL }
};

The driver callback is responsible for providing the data associated with each driver, while the auto-add callback tells PAPPL which driver to use for the printers it finds.

The "subcmd_name" and "subcmd_cb" arguments specify a custom sub-command for the printer application along with a function to call. Since this printer application does not have a custom sub-command, we pass NULL for both.

The "system_cb" argument specifies a callback for creating the system object. We pass NULL because we want the default system object for this printer application, which supports multiple printers and a web interface.

The "usage_cb" argument specifies a callback from displaying the program usage message. Passing NULL yields the default usage message.

The "data" argument specifies a pointer that will be passed to any of the callback functions. We pass NULL since we do not have any extra contextual information to provide to the callbacks.

The papplMainloop function runs until all processing for the current sub-command is complete, returning the exit status for the program.

Configuration and State Files

Printer applications using the main loop API use a configuration file for server options and a state file for printers and jobs. The files are named based on the base name of the printer application, in this case "hp-printer-app.conf" for the server options and "hp-printer-app.state" for the state file. Server options are loaded from the "/etc" and "/usr/local/etc" directories on regular Unix/Linux systems, "$HOME/snap/BASENAME/common" for snap-based applications, and "/Library/Application Support" on macOS.

The Driver Callback

The PAPPL driver callback is called when the system is creating a new printer object. It receives pointers to the system, driver name, device URI, a driver data structure, an IPP attributes pointer, and the callback data, and it returns a boolean indicating whether the driver callback was successful:

typedef bool (*pappl_pr_driver_cb_t)(pappl_system_t *system,
    const char *driver_name, const char *device_uri,
    pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data);

A driver callback can communicate with the printer via its device URI as needed to configure the driver, however our printer application doesn't need to do that.

The first thing our pcl_callback function does is to set the printer callbacks in the driver data structure:

driver_data->printfile_cb    = pcl_print;
driver_data->rendjob_cb      = pcl_rendjob;
driver_data->rendpage_cb     = pcl_rendpage;
driver_data->rstartjob_cb    = pcl_rstartjob;
driver_data->rstartpage_cb   = pcl_rstartpage;
driver_data->rwriteline_cb   = pcl_rwriteline;
driver_data->status_cb       = pcl_status;

The pcl_print function prints a raw PCL file while the pcl_r functions print raster graphics. The pcl_status updates the printer status.

Next is the printer's native print format as a MIME media type, in this case HP PCL:

driver_data->format          = "application/vnd.hp-pcl";

The default orientation and print quality follow:

driver_data->orient_default  = IPP_ORIENT_NONE;
driver_data->quality_default = IPP_QUALITY_NORMAL;

Then the values for the various drivers. Here are the HP DeskJet driver settings:

if (!strcmp(driver_name, "hp_deskjet"))
{
  /* Make and model name */
  strncpy(driver_data->make_and_model, "HP DeskJet", sizeof(driver_data->make_and_model) - 1);

  /* Pages-per-minute for monochrome and color */
  driver_data->ppm       = 8;
  driver_data->ppm_color = 2;

  /* Three resolutions - 150dpi, 300dpi (default), and 600dpi */
  driver_data->num_resolution  = 3;
  driver_data->x_resolution[0] = 150;
  driver_data->y_resolution[0] = 150;
  driver_data->x_resolution[1] = 300;
  driver_data->y_resolution[1] = 300;
  driver_data->x_resolution[2] = 600;
  driver_data->y_resolution[2] = 600;
  driver_data->x_default = driver_data->y_default = 300;

  /* Four color spaces - black (1-bit and 8-bit), grayscale, and sRGB */
  driver_data->raster_types = PAPPL_PWG_RASTER_TYPE_BLACK_1 | PAPPL_PWG_RASTER_TYPE_BLACK_8 | PAPPL_PWG_RASTER_TYPE_SGRAY_8 | PAPPL_PWG_RASTER_TYPE_SRGB_8;

  /* Color modes: auto (default), monochrome, and color */
  driver_data->color_supported = PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_AUTO_MONOCHROME | PAPPL_COLOR_MODE_COLOR | PAPPL_COLOR_MODE_MONOCHROME;
  driver_data->color_default   = PAPPL_COLOR_MODE_AUTO;

  /* Media sizes with 1/4" left/right and 1/2" top/bottom margins*/
  driver_data->num_media = (int)(sizeof(pcl_hp_deskjet_media) / sizeof(pcl_hp_deskjet_media[0]));
  memcpy(driver_data->media, pcl_hp_deskjet_media, sizeof(pcl_hp_deskjet_media));

  driver_data->left_right = 635;       // 1/4" left and right
  driver_data->bottom_top = 1270;      // 1/2" top and bottom

  /* 1-sided printing only */
  driver_data->sides_supported = PAPPL_SIDES_ONE_SIDED;
  driver_data->sides_default   = PAPPL_SIDES_ONE_SIDED;

  /* Three paper trays (MSN names) */
  driver_data->num_source = 3;
  driver_data->source[0]  = "tray-1";
  driver_data->source[1]  = "manual";
  driver_data->source[2]  = "envelope";

  /* Five media types (MSN names) */
  driver_data->num_type = 5;
  driver_data->type[0] = "stationery";
  driver_data->type[1] = "bond";
  driver_data->type[2] = "special";
  driver_data->type[3] = "transparency";
  driver_data->type[4] = "photographic-glossy";
}

Finally, we fill out the ready and default media for each media source (tray), putting US Letter paper in the regular trays and #10 envelopes in any envelope tray:

// Fill out ready and default media (default == ready media from the first source)
for (i = 0; i < driver_data->num_source; i ++)
{
  pwg_media_t *pwg;                   /* Media size information */

  /* Use US Letter for regular trays, #10 envelope for the envelope tray */
  if (!strcmp(driver_data->source[i], "envelope"))
    strncpy(driver_data->media_ready[i].size_name, "env_10_4.125x9.5in", sizeof(driver_data->media_ready[i].size_name) - 1);
  else
    strncpy(driver_data->media_ready[i].size_name, "na_letter_8.5x11in", sizeof(driver_data->media_ready[i].size_name) - 1);

  /* Set margin and size information */
  if ((pwg = pwgMediaForPWG(driver_data->media_ready[i].size_name)) != NULL)
  {
    driver_data->media_ready[i].bottom_margin = driver_data->bottom_top;
    driver_data->media_ready[i].left_margin   = driver_data->left_right;
    driver_data->media_ready[i].right_margin  = driver_data->left_right;
    driver_data->media_ready[i].size_width    = pwg->width;
    driver_data->media_ready[i].size_length   = pwg->length;
    driver_data->media_ready[i].top_margin    = driver_data->bottom_top;
    strncpy(driver_data->media_ready[i].source, driver_data->source[i], sizeof(driver_data->media_ready[i].source) - 1);
    strncpy(driver_data->media_ready[i].type, driver_data->type[0],  sizeof(driver_data->media_ready[i].type) - 1);
  }
}

driver_data->media_default = driver_data->media_ready[0];

return (true);

The Auto-Add Callback

The PAPPL auto-add callback is called when processing the "autoadd" sub-command. It is called for each new device and is responsible for returning the name of the driver to be used for the device or NULL if no driver is available:

typedef const char *(*pappl_ml_autoadd_cb_t)(const char *device_info,
    const char *device_uri, const char *device_id, void *data);

Our pcl_autoadd function uses the IEEE-1284 device ID string to determine whether one of the drivers will work. The papplDeviceParseID function splits the string into key/value pairs that can be looked up using the cupsGetOption function:

const char      *ret = NULL;            // Return value
int             num_did;                // Number of device ID key/value pairs
cups_option_t   *did;                   // Device ID key/value pairs
const char      *cmd,                   // Command set value
                *pcl;                   // PCL command set pointer


// Parse the IEEE-1284 device ID to see if this is a printer we support...
num_did = papplDeviceParseID(device_id, &did);

The two keys we care about are the "COMMAND SET" (also abbreviated as "CMD") for the list of document formats the printer supports and "MODEL"/"MDL" for the model name. We are looking for the "PCL" format and one of the common model names for HP printers:

// Look at the COMMAND SET (CMD) key for the list of printer languages,,,
if ((cmd = cupsGetOption("COMMAND SET", num_did, did)) == NULL)
  cmd = cupsGetOption("CMD", num_did, did);

if (cmd && (pcl = strstr(cmd, "PCL")) != NULL && (pcl[3] == ',' || !pcl[3]))
{
  // Printer supports HP PCL, now look at the MODEL (MDL) string to see if
  // it is one of the HP models or a generic PCL printer...
  const char *mdl;                      // Model name string

  if ((mdl = cupsGetOption("MODEL", num_did, did)) == NULL)
    mdl = cupsGetOption("MDL", num_did, did);

  if (mdl && (strstr(mdl, "DeskJet") || strstr(mdl, "Photosmart")))
    ret = "hp_deskjet";                 // HP DeskJet/Photosmart printer
  else if (mdl && strstr(mdl, "LaserJet"))
    ret = "hp_laserjet";                // HP LaserJet printer
  else
    ret = "hp_generic";                 // Some other PCL laser printer
}

cupsFreeOptions(num_did, did);

return (ret);

The File Printing Callback

The file printing callback is used when printing a "raw" (printer-ready) file from a client:

typedef bool (*pappl_pr_printfile_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device);

This callback will sometimes send some printer initialization commands followed by the job file and then any cleanup commands. It may also be able to count the number of pages (impressions) in the file, although that is not a requirement. For the HP Printer Application our pcl_print function just copies the file from the job to the device and assumes that the file contains only one page:

int     fd;                     // Job file
ssize_t bytes;                  // Bytes read/written
char    buffer[65536];          // Read/write buffer


papplJobSetImpressions(job, 1);

fd = open(papplJobGetFilename(job), O_RDONLY);

while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
{
  if (papplDeviceWrite(device, buffer, (size_t)bytes) < 0)
  {
    papplLogJob(job, PAPPL_LOGLEVEL_ERROR,
                "Unable to send %d bytes to printer.", (int)bytes);
    close(fd);
    return (false);
  }
}

close(fd);

papplJobSetImpressionsCompleted(job, 1);

return (true);

The Raster Printing Callbacks

The PAPPL raster printing callbacks are used for printing PWG and Apple raster documents, JPEG and PNG images, and other formats that end up as raster data:

typedef bool (*pappl_pr_rstartjob_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device);

typedef bool (*pappl_pr_rstartpage_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device, unsigned page);

typedef bool (*pappl_pr_rwriteline_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device, unsigned y,
    const unsigned char *line);

typedef bool (*pappl_pr_rendpage_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device, unsigned page);

typedef bool (*pappl_pr_rendjob_cb_t)(pappl_job_t *job,
    pappl_pr_options_t *options, pappl_device_t *device);

Each of the raster printing callbacks is expected to send data to the printer using the provided "device" pointer. The "job" argument provides the current job object and the "options" pointer provides the current print job options. The "page" argument specifies the current page number staring at 0.

The pappl_pr_rstartjob_cb_t function is called at the beginning of a job to allow the driver to initialize the printer for the current job.

The pappl_pr_rstartpage_cb_t function is called at the beginning of each page to allow the driver to do any per-page initialization and/or memory allocations and send any printer commands that are necessary to start a new page.

The pappl_pr_rwriteline_cb_t function is called for each raster line on the page and is typically responsible for dithering and compressing the raster data for the printer.

The pappl_pr_rendpage_cb_t function is called at the end of each page where the driver will typically eject the current page.

The pappl_pr_rendjob_cb_t function is called at the end of a job to allow the driver to send any cleanup commands to the printer.

The Identification Callback

The PAPPL identification callback is used to audibly or visibly identify the printer being used:

typedef void (*pappl_pr_identify_cb_t)(pappl_printer_t *printer,
    pappl_identify_actions_t actions, const char *message);

The most common identification method is PAPPL_IDENTIFY_ACTIONS_SOUND which should have the printer make a sound. The PAPPL_IDENTIFY_ACTIONS_DISPLAY and PAPPL_IDENTIFY_ACTIONS_SPEAK methods use the "message" argument to display or speak a message. Finally, the PAPPL_IDENTIFY_ACTIONS_FLASH method flashes a light on the printer.

The HP Printer Application does not have an identification callback since most PCL printers lack a buzzer or light that can be remotely activated.

Note: IPP Everywhere™ requires all printers to support identification. A warning message is logged by PAPPL whenever a driver does not set the identify_cb member of the printer driver data structure.

The Status Callback

The PAPPL status callback is used to update the printer state, supply levels, and/or ready media for the printer:

typedef bool (*pappl_pr_status_cb_t)(pappl_printer_t *printer);

The callback can open a connection to the printer using the papplPrinterOpenDevice function.

The Self-Test Page Callback

The PAPPL self-test page callback is used to generate a self-test page for the printer:

typedef const char *(*pappl_printer_testpage_cb_t)(pappl_printer_t *printer,
    char *buffer, size_t bufsize);

When the callback returns a filename (copied to the specified buffer), that file will be queued as a job for the printer. The callback can also try opening the device using the papplPrinterOpenDevice function to send a printer self-test command instead - in this case the callback must return NULL to indicate there is no file to be printed.

Functions

papplClientGetCSRFToken

Get a unique Cross-Site Request Forgery token string.

char *papplClientGetCSRFToken(pappl_client_t *client, char *buffer, size_t bufsize);

Parameters

client Client
buffer String buffer
bufsize Size of string buffer

Return Value

Token string

Discussion

This function generates and returns a unique Cross-Site Request Forgery token string to be used as the value of a hidden variable in all HTML forms sent in the response and then compared when validating the form data in the subsequent request.

The value is based on the current system session key and client address in order to make replay attacks infeasible.

Note: The papplClientHTMLStartForm function automatically adds the hidden CSRF variable, and the papplClientIsValidForm function validates the value.

papplClientGetCookie

Get a cookie from the client.

char *papplClientGetCookie(pappl_client_t *client, const char *name, char *buffer, size_t bufsize);

Parameters

client Client
name Name of cookie
buffer Value buffer
bufsize Size of value buffer

Return Value

Cookie value or NULL if not set

Discussion

This function gets a HTTP "cookie" value from the client request. NULL is returned if no cookie has been set by a prior request, or if the user has disabled or removed the cookie.

Use the papplClientSetCookie function to set a cookie in a response to a request.

Note: Cookies set with papplClientSetCookie will not be available to this function until the following request.

papplClientGetForm

Get form data from the web client.

int papplClientGetForm(pappl_client_t *client, cups_option_t **form);

Parameters

client Client
form Form variables

Return Value

Number of form variables read

Discussion

For HTTP GET requests, the form data is collected from the request URI. For HTTP POST requests, the form data is read from the client.

The returned form values must be freed using the cupsFreeOptions function.

Note: Because the form data is read from the client connection, this function can only be called once per request.

papplClientGetHTTP

Get the HTTP connection associated with a client object.

http_t *papplClientGetHTTP(pappl_client_t *client);

Parameters

client Client

Return Value

HTTP connection

Discussion

This function returns the HTTP connection associated with the client and is used when sending response data directly to the client using the CUPS httpXxx functions.

papplClientGetHostName

Get the hostname from the client-supplied Host: field.

const char *papplClientGetHostName(pappl_client_t *client);

Parameters

client Client

Return Value

Hostname or NULL for none

Discussion

This function returns the hostname that was used in the request and should be used in any URLs or URIs that you generate.

papplClientGetHostPort

Get the port from the client-supplied Host: field.

int papplClientGetHostPort(pappl_client_t *client);

Parameters

client Client

Return Value

Port number or 0 for none

Discussion

This function returns the port number that was used in the request and should be used in any URLs or URIs that you generate.

papplClientGetJob

Get the target job for an IPP request.

pappl_job_t *papplClientGetJob(pappl_client_t *client);

Parameters

client Client

Return Value

Target job or NULL if none

Discussion

This function returns the job associated with the current IPP request. NULL is returned if the request does not target a job.

papplClientGetLoc

Get the localization data for a client connection.

pappl_loc_t *papplClientGetLoc(pappl_client_t *client);

Parameters

client Client

Return Value

Localization data to use

papplClientGetLocString

Get a localized string for the client.

const char *papplClientGetLocString(pappl_client_t *client, const char *s);

Parameters

client Client
s String to localize

Return Value

Localized string

papplClientGetMethod

Get the HTTP request method.

http_state_t papplClientGetMethod(pappl_client_t *client);

Parameters

client Client

Return Value

HTTP method

Discussion

This function returns the HTTP request method that was used, for example HTTP_STATE_GET for a GET request or HTTP_STATE_POST for a POST request.

papplClientGetOperation

Get the IPP operation code.

ipp_op_t papplClientGetOperation(pappl_client_t *client);

Parameters

client Client

Return Value

IPP operation code

Discussion

This function returns the IPP operation code associated with the current IPP request.

papplClientGetOptions

Get the options from the request URI.

const char *papplClientGetOptions(pappl_client_t *client);

Parameters

client Client

Return Value

Options or NULL if none

Discussion

This function returns any options that were passed in the HTTP request URI. The options are the characters after the "?" character, for example a request URI of "/mypage?name=value" will have an options string of "name=value".

NULL is returned if the request URI did not contain any options.

Note: HTTP GET form variables are normally accessed using the papplClientGetForm function. This function should only be used when getting non-form data.

papplClientGetPrinter

Get the target printer for an IPP request.

pappl_printer_t *papplClientGetPrinter(pappl_client_t *client);

Parameters

client Client

Return Value

Target printer or NULL if none

Discussion

This function returns the printer associated with the current IPP request. NULL is returned if the request does not target a printer.

papplClientGetRequest

Get the IPP request message.

ipp_t *papplClientGetRequest(pappl_client_t *client);

Parameters

client Client

Return Value

IPP request message

Discussion

This function returns the attributes in the current IPP request, for use with the CUPS ippFindAttribute, ippFindNextAttribute, ippFirstAttribute, and ippNextAttribute functions.

papplClientGetResponse

Get the IPP response message.

ipp_t *papplClientGetResponse(pappl_client_t *client);

Parameters

client Client

Return Value

IPP response message

Discussion

This function returns the attributes in the current IPP response, for use with the CUPS ippAddXxx and ippSetXxx functions. Use the papplClientRespondIPP function to set the status code and message, if any.

papplClientGetSystem

Get the containing system for the client.

pappl_system_t *papplClientGetSystem(pappl_client_t *client);

Parameters

client Client

Return Value

System

Discussion

This function returns the system object that contains the client.

papplClientGetURI

Get the HTTP request URI.

const char *papplClientGetURI(pappl_client_t *client);

Parameters

client Client

Return Value

Request URI

Discussion

This function returns the URI that was sent in the current HTTP request.

Note: Any options in the URI are removed and can be accessed separately using the papplClientGetOptions function.

papplClientGetUsername

Get the authenticated username, if any.

const char *papplClientGetUsername(pappl_client_t *client);

Parameters

client Client

Return Value

Authenticated username or NULL if none

Discussion

This function returns the current authenticated username, if any.

papplClientHTMLAuthorize

Handle authorization for the web interface.

bool papplClientHTMLAuthorize(pappl_client_t *client);

Parameters

client Client

Return Value

true if authorized, false otherwise

Discussion

The web interface supports both authentication against user accounts and authentication using a single administrative access password. This function handles the details of authentication for the web interface based on the system authentication service configuration = the "auth_service" argument to papplSystemCreate and any callback set using papplSystemSetAuthCallback.

Note: IPP operation callbacks needing to perform authorization should use the papplClientIsAuthorized function instead.

papplClientHTMLEscape

Send a string to a web browser client.

void papplClientHTMLEscape(pappl_client_t *client, const char *s, size_t slen);

Parameters

client Client
s String to write
slen Number of characters to write (0 for nul-terminated)

Discussion

This function sends the specified string to the web browser client and escapes special characters as HTML entities as needed, for example "&" is sent as &amp;.

papplClientHTMLFooter

Show the web interface footer.

void papplClientHTMLFooter(pappl_client_t *client);

Parameters

client Client

Discussion

This function sends the standard web interface footer followed by a trailing 0-length chunk to finish the current HTTP response. Use the papplSystemSetFooterHTML function to add any custom HTML needed in the footer.

papplClientHTMLHeader

Show the web interface header and title.

void papplClientHTMLHeader(pappl_client_t *client, const char *title, int refresh);

Parameters

client Client
title Title
refresh Refresh time in seconds (0 for no refresh)

Discussion

This function sends the standard web interface header and title. If the "refresh" argument is greater than zero, the page will automatically reload after that many seconds.

Use the papplSystemAddLink function to add system-wide navigation links to the header. Similarly, use papplPrinterAddLink to add printer-specific links, which will appear in the web interface printer if the system is not configured to support multiple printers (the PAPPL_SOPTIONS_MULTI_QUEUE option to papplSystemCreate).

papplClientHTMLPrinterFooter

Show the web interface footer for printers.

void papplClientHTMLPrinterFooter(pappl_client_t *client);

Parameters

client Client

Discussion

This function sends the standard web interface footer for a printer followed by a trailing 0-length chunk to finish the current HTTP response. Use the papplSystemSetFooterHTML function to add any custom HTML needed in the footer.

papplClientHTMLPrinterHeader

Show the web interface header and title for printers.

void papplClientHTMLPrinterHeader(pappl_client_t *client, pappl_printer_t *printer, const char *title, int refresh, const char *label, const char *path_or_url);

Parameters

client Client
printer Printer
title Title
refresh Refresh time in seconds or 0 for none
label Button label or NULL for none
path_or_url Button path or NULL for none

Discussion

This function sends the standard web interface header and title for a printer. If the "refresh" argument is greater than zero, the page will automatically reload after that many seconds.

If "label" and "path_or_url" are non-NULL strings, an additional navigation link is included with the title header - this is typically used for an action button ("Change").

Use the papplSystemAddLink function to add system-wide navigation links to the header. Similarly, use papplPrinterAddLink to add printer-specific links, which will appear in the web interface printer if the system is not configured to support multiple printers (the PAPPL_SOPTIONS_MULTI_QUEUE option to papplSystemCreate).

papplClientHTMLPrintf

Send formatted text to the web browser client, escaping as needed.

void papplClientHTMLPrintf(pappl_client_t *client, const char *format, ...);

Parameters

client Client
format Printf-style format string
... Additional arguments as needed

Discussion

This function sends formatted text to the web browser client using printf-style formatting codes. The format string itself is not escaped to allow for embedded HTML, however strings inserted using the '%c' or %s codes are escaped properly for HTML - "&" is sent as &amp;, etc.

papplClientHTMLPuts

Send a HTML string to the web browser client.

void papplClientHTMLPuts(pappl_client_t *client, const char *s);

Parameters

client Client
s String

Discussion

This function sends a HTML string to the client without performing any escaping of special characters.

papplClientHTMLStartForm

Start a HTML form.

void papplClientHTMLStartForm(pappl_client_t *client, const char *action, bool multipart);

Parameters

client Client
action Form action URL
multipart true if the form allows file uploads, false otherwise

Discussion

This function starts a HTML form with the specified "action" path and includes the CSRF token as a hidden variable. If the "multipart" argument is true, the form is annotated to support file attachments up to 2MiB in size.

papplClientIsAuthorized

Determine whether a client is authorized for administrative requests.

http_status_t papplClientIsAuthorized(pappl_client_t *client);

Parameters

client Client

Return Value

HTTP status

Discussion

This function determines whether a client is authorized to submit an administrative request.

The return value is HTTP_STATUS_CONTINUE if access is authorized, HTTP_STATUS_FORBIDDEN if access is not allowed, HTTP_STATUS_UNAUTHORIZED if authorization is required, or HTTP_STATUS_UPGRADE_REQUIRED if the connection needs to be encrypted. All of these values can be passed to the papplClientRespond function.

papplClientIsEncrypted

Return whether a Client connection is encrypted.

bool papplClientIsEncrypted(pappl_client_t *client);

Parameters

client Client

Return Value

true if encrypted, false otherwise

Discussion

This function returns a boolean value indicating whether a Client connection is encrypted with TLS.

papplClientIsValidForm

Validate HTML form variables.

bool papplClientIsValidForm(pappl_client_t *client, int num_form, cups_option_t *form);

Parameters

client Client
num_form Number of form variables
form Form variables

Return Value

true if the CSRF token is valid, false otherwise

Discussion

This function validates the contents of a HTML form using the CSRF token included as a hidden variable. When sending a HTML form you should use the papplClientStartForm function to start the HTML form and insert the CSRF token for later validation.

Note: Callers are expected to validate all other form variables.

papplClientRespond

Send a regular HTTP response.

bool papplClientRespond(pappl_client_t *client, http_status_t code, const char *content_encoding, const char *type, time_t last_modified, size_t length);

Parameters

client Client
code HTTP status of response
content_encoding Content-Encoding of response
type MIME media type of response
last_modified Last-Modified date/time or 0 for none
length Length of response or 0 for variable-length

Return Value

true on success, false on failure

Discussion

This function sends all of the required HTTP fields and includes standard messages for errors. The following values for "code" are explicitly supported:

  • HTTP_STATUS_OK: The request is successful.
  • HTTP_STATUS_BAD_REQUEST: The client submitted a bad request.
  • HTTP_STATUS_CONTINUE: An authentication challenge is not needed.
  • HTTP_STATUS_FORBIDDEN: Authenticated but not allowed.
  • HTTP_STATUS_METHOD_NOT_ALLOWED: The HTTP method is not supported for the given URI.
  • HTTP_STATUS_UNAUTHORIZED: Not authenticated.
  • HTTP_STATUS_UPGRADE_REQUIRED: Redirects the client to a secure page.

Use the papplClientRespondRedirect when you need to redirect the client to another page.

papplClientRespondIPP

Send an IPP response.

ipp_t *papplClientRespondIPP(pappl_client_t *client, ipp_status_t status, const char *message, ...);

Parameters

client Client
status status-code
message printf-style status-message
... Additional args as needed

Return Value

IPP response message

Discussion

This function sets the return status for an IPP request and returns the current IPP response message. The "status" and "message" arguments replace any existing status-code and "status-message" attribute value that may be already present in the response.

Note: You should call this function prior to adding any response attributes.

papplClientRespondIPPUnsupported

Respond with an unsupported IPP attribute.

void papplClientRespondIPPUnsupported(pappl_client_t *client, ipp_attribute_t *attr);

Parameters

client Client
attr Attribute

Discussion

This function returns a 'client-error-attributes-or-values-not-supported' status code and adds the specified attribute to the unsupported attributes group in the response.

papplClientRespondRedirect

Respond with a redirect to another page.

bool papplClientRespondRedirect(pappl_client_t *client, http_status_t code, const char *path);

Parameters

client Client
code HTTP_STATUS_MOVED_PERMANENTLY or HTTP_STATUS_FOUND
path Redirection path/URL

Return Value

true on success, false otherwise

Discussion

This function sends a HTTP response that redirects the client to another page or URL. The most common "code" value to return is HTTP_STATUS_FOUND.

papplClientSetCookie

Set a cookie for the web browser client.

void papplClientSetCookie(pappl_client_t *client, const char *name, const char *value, int expires);

Parameters

client Client
name Cookie name
value Cookie value
expires Expiration in seconds from now, 0 for a session cookie

Discussion

This function sets the value of a cookie for the client by updating the Set-Cookie header in the HTTP response that will be sent. The "name" and "value" strings must contain only valid characters for a cookie and its value as documented in RFC 6265, which basically means letters, numbers, "@", "-", ".", and "_".

The "expires" argument specifies how long the cookie will remain active in seconds, for example 3600 seconds is one hour and 86400 seconds is one day. If the value is zero or less, a "session" cookie is created instead which will expire as soon as the web browser is closed.

papplClientSetUsername

Set the authenticated username, if any.

void papplClientSetUsername(pappl_client_t *client, const char *username);

Parameters

client Client
username Username or NULL for none

Discussion

This function sets the current authenticated username, if any.

papplCopyString

size_t papplCopyString(char *dst, const char *src, size_t dstsize);

Parameters

dst Destination buffer
src Source string
dstsize Destination size

Return Value

Safely copy a C string.

This function safely copies a C string to a destination buffer.

papplCreateTempFile

Create a temporary file.

int papplCreateTempFile(char *fname, size_t fnamesize, const char *prefix, const char *ext);

Parameters

fname Filename buffer
fnamesize Size of filename buffer
prefix Prefix for filename
ext Filename extension, if any

Return Value

File descriptor or -1 on error

papplDeviceAddScheme

Add a device URI scheme.

void papplDeviceAddScheme(const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devid_cb_t id_cb);

Parameters

scheme URI scheme
dtype Device type (PAPPL_DEVTYPE_CUSTOM_LOCAL or PAPPL_DEVTYPE_CUSTOM_NETWORK)
list_cb List devices callback, if any
open_cb Open callback
close_cb Close callback
read_cb Read callback
write_cb Write callback
status_cb Status callback, if any
id_cb IEEE-1284 device ID callback, if any

Discussion

This function registers a device URI scheme with PAPPL, so that devices using the named scheme can receive print data, report status information, and so forth. PAPPL includes support for the following URI schemes:

  • dnssd: Network printers discovered using DNS-SD.
  • file: Character device files, plain files, and directories.
  • snmp: Network printers discovered using SNMPv1.
  • socket: Network printers using a hostname or numeric IP address.
  • usb: Class 1 (unidirectional) or 2 (bidirectional) USB printers.

The "scheme" parameter specifies the URI scheme and must consist of lowercase letters, digits, "-", "_", and/or ".", for example "x-foo" or "com.example.bar".

The "dtype" parameter specifies the device type and should be PAPPL_DTYPE_CUSTOM_LOCAL for locally connected printers and PAPPL_DTYPE_CUSTOM_NETWORK for network printers.

Each of the callbacks corresponds to one of the papplDevice functions:

  • "list_cb": Implements discovery of devices (optional)
  • "open_cb": Opens communication with a device and allocates any device- specific data as needed
  • "close_cb": Closes communication with a device and frees any device- specific data as needed
  • "read_cb": Reads data from a device
  • "write_cb": Write data to a device
  • "status_cb": Gets basic printer state information from a device (optional)
  • "id_cb": Gets the current IEEE-1284 device ID from a device (optional)

The "open_cb" callback typically calls papplDeviceSetData to store a pointer to contextual information for the connection while the "close_cb", "id_cb", "read_cb", "write_cb", and "status_cb" callbacks typically call papplDeviceGetData to retrieve it.

papplDeviceAddScheme2

Add a device URI scheme with supply-level queries.

void papplDeviceAddScheme2(const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devsupplies_cb_t supplies_cb, pappl_devid_cb_t id_cb);

Parameters

scheme URI scheme
dtype Device type (PAPPL_DEVTYPE_CUSTOM_LOCAL or PAPPL_DEVTYPE_CUSTOM_NETWORK)
list_cb List devices callback, if any
open_cb Open callback
close_cb Close callback
read_cb Read callback
write_cb Write callback
status_cb Status callback, if any
supplies_cb Supply level callback, if any
id_cb IEEE-1284 device ID callback, if any

Discussion

This function registers a device URI scheme with PAPPL, so that devices using the named scheme can receive print data, report status information, and so forth. PAPPL includes support for the following URI schemes:

  • dnssd: Network printers discovered using DNS-SD.
  • file: Character device files, plain files, and directories.
  • snmp: Network printers discovered using SNMPv1.
  • socket: Network printers using a hostname or numeric IP address.
  • usb: Class 1 (unidirectional) or 2 (bidirectional) USB printers.

The "scheme" parameter specifies the URI scheme and must consist of lowercase letters, digits, "-", "_", and/or ".", for example "x-foo" or "com.example.bar".

The "dtype" parameter specifies the device type and should be PAPPL_DTYPE_CUSTOM_LOCAL for locally connected printers and PAPPL_DTYPE_CUSTOM_NETWORK for network printers.

Each of the callbacks corresponds to one of the papplDevice functions:

  • "list_cb": Implements discovery of devices (optional)
  • "open_cb": Opens communication with a device and allocates any device- specific data as needed
  • "close_cb": Closes communication with a device and frees any device- specific data as needed
  • "read_cb": Reads data from a device
  • "write_cb": Write data to a device
  • "status_cb": Gets basic printer state information from a device (optional)
  • "supplies_cb": Gets supply level information from a device (optional)
  • "id_cb": Gets the current IEEE-1284 device ID from a device (optional)

The "open_cb" callback typically calls papplDeviceSetData to store a pointer to contextual information for the connection while the "close_cb", "id_cb", "read_cb", "write_cb", "status_cb", and "supplies_cb" callbacks typically call papplDeviceGetData to retrieve it.

papplDeviceClose

Close a device connection.

void papplDeviceClose(pappl_device_t *device);

Parameters

device Device to close

Discussion

This function flushes any pending write data and closes the connection to a device.

papplDeviceError

Report an error on a device.

void papplDeviceError(pappl_device_t *device, const char *message, ...);

Parameters

device Device
message Printf-style error message
... Additional arguments as needed

Discussion

This function reports an error on a device using the client-supplied callback function. It is normally called from any custom device URI scheme callbacks you implement.

papplDeviceFlush

Flush any buffered data to the device.

void papplDeviceFlush(pappl_device_t *device);

Parameters

device Device

Discussion

This function flushes any pending write data sent using the papplDevicePrintf, papplDevicePuts, or papplDeviceWrite functions to the device.

papplDeviceGetData

Get device-specific data.

void *papplDeviceGetData(pappl_device_t *device);

Parameters

device Device

Return Value

Device data pointer

Discussion

This function returns any device-specific data that has been set by the device open callback. It is normally only called from any custom device URI scheme callbacks you implement.

papplDeviceGetID

Get the IEEE-1284 device ID.

char *papplDeviceGetID(pappl_device_t *device, char *buffer, size_t bufsize);

Parameters

device Device
buffer Buffer for IEEE-1284 device ID
bufsize Size of buffer

Return Value

IEEE-1284 device ID or NULL on failure

Discussion

This function queries the IEEE-1284 device ID from the device and copies it to the provided buffer. The buffer must be at least 64 bytes and should be at least 1024 bytes in length.

Note: This function can block for up to several seconds depending on the type of connection.

papplDeviceGetMetrics

Get the device metrics.

pappl_devmetrics_t *papplDeviceGetMetrics(pappl_device_t *device, pappl_devmetrics_t *metrics);

Parameters

device Device
metrics Buffer for metrics data

Return Value

Metrics data

Discussion

This function returns a copy of the device metrics data, which includes the number, length (in bytes), and duration (in milliseconds) of read, status, and write requests for the current session. This information is normally used for performance measurement and optimization during development of a printer application. It can also be useful diagnostic information.

papplDeviceGetStatus

Get the printer status bits.

pappl_preason_t papplDeviceGetStatus(pappl_device_t *device);

Parameters

device Device

Return Value

IPP "printer-state-reasons" values

Discussion

This function returns the current printer status bits, as applicable to the current device.

The status bits for USB devices come from the original Centronics parallel printer "standard" which was later formally standardized in IEEE 1284-1984 and the USB Device Class Definition for Printing Devices. Some vendor extensions are also supported.

The status bits for network devices come from the hrPrinterDetectedErrorState property that is defined in the SNMP Printer MIB v2 (RFC 3805).

This function returns a pappl_preason_t bitfield which can be passed to the papplPrinterSetReasons function. Use the PAPPL_PREASON_DEVICE_STATUS value as the value of the "remove" argument.

Note: This function can block for several seconds while getting the status information.

papplDeviceGetSupplies

Get the current printer supplies.

int papplDeviceGetSupplies(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies);

Parameters

device Device
max_supplies Maximum supplies
supplies Supplies

Return Value

Number of supplies

Discussion

This function returns the number, type, and level of current printer supply levels, as applicable to the current device.

The supply levels for network devices come from the prtSupplyTable and prtMarkerColorantTable properties that are defined in the SNMP Printer MIB v2 (RFC 3805).

The supply levels for other devices are not standardized and must be queried using other methods.

Note: This function can block for several seconds while getting the supply information.

papplDeviceIsSupported

Determine whether a given URI is supported.

bool papplDeviceIsSupported(const char *uri);

Parameters

uri URI

Return Value

true if supported, false otherwise

Discussion

This function determines whether a given URI or URI scheme is supported as a device.

papplDeviceList

List available devices.

bool papplDeviceList(pappl_devtype_t types, pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data);

Parameters

types Device types
cb Callback function
data User data for callback
err_cb Error callback or NULL for default
err_data Data for error callback

Return Value

true if the callback returned true, false otherwise

Discussion

This function lists the available devices, calling the "cb" function once per device that is discovered/listed. The callback function receives the device URI, IEEE-1284 device ID (if any), and "data" pointer, and returns true to stop listing devices and false to continue.

The "types" argument determines which devices are listed, for example PAPPL_DEVTYPE_ALL will list all types of devices while PAPPL_DEVTYPE_USB only lists USB printers.

Any errors are reported using the supplied "err_cb" function. If you specify NULL for this argument, errors are sent to stderr.

Note: This function will block (not return) until each of the device URI schemes has reported all of the devices or the supplied callback function returns true.

papplDeviceOpen

Open a connection to a device.

pappl_device_t *papplDeviceOpen(const char *device_uri, const char *name, pappl_deverror_cb_t err_cb, void *err_data);

Parameters

device_uri Device URI
name Job name
err_cb Error callback or NULL for default
err_data Data for error callback

Return Value

Device connection or NULL on error

Discussion

This function opens a connection to the specified device URI. The "name" argument provides textual context for the connection and is usually the name (title) of the print job.

Any errors are reported using the supplied "err_cb" function. If you specify NULL for this argument, errors are sent to stderr.

papplDeviceParseID

Parse an IEEE-1284 device ID string.

int papplDeviceParseID(const char *device_id, cups_option_t **pairs);

Parameters

device_id IEEE-1284 device ID string
pairs Key/value pairs

Return Value

Number of key/value pairs

Discussion

This function parses an IEEE-1284 device ID string and returns an array of key/value pairs as a cups_option_t array. The returned array must be freed using the cupsFreeOptions function.

papplDevicePrintf

Write a formatted string.

ssize_t papplDevicePrintf(pappl_device_t *device, const char *format, ...);

Parameters

device Device
format Printf-style format string
... Additional args as needed

Return Value

Number of characters or -1 on error

Discussion

This function buffers a formatted string that will be sent to the device. The "format" argument accepts all printf format specifiers and behaves identically to that function.

Call the papplDeviceFlush function to ensure that the formatted string is immediately sent to the device.

papplDevicePuts

Write a literal string.

ssize_t papplDevicePuts(pappl_device_t *device, const char *s);

Parameters

device Device
s Literal string

Return Value

Number of characters or -1 on error

Discussion

This function buffers a literal string that will be sent to the device. Call the papplDeviceFlush function to ensure that the literal string is immediately sent to the device.

papplDeviceRead

Read from a device.

ssize_t papplDeviceRead(pappl_device_t *device, void *buffer, size_t bytes);

Parameters

device Device
buffer Read buffer
bytes Max bytes to read

Return Value

Number of bytes read or -1 on error

Discussion

This function reads data from the device. Depending on the device, this function may block indefinitely.

papplDeviceRemoveScheme

Remove the named device URI scheme.

void papplDeviceRemoveScheme(const char *scheme);

Parameters

scheme Device URI scheme to remove

Discussion

This function removes support for the named device URI scheme. Use only when you want to disable a URI scheme for security or functional reasons, for example to disable the "file" URI scheme.

papplDeviceRemoveTypes

Remove device URI schemes of the specified types.

void papplDeviceRemoveTypes(pappl_devtype_t types);

Parameters

types Device types to remove

Discussion

This function removes device URI schemes of the specified types. Use only when you want to disable URI schemes for security or functional reasons, for example to disable all network URI schemes.

papplDeviceSetData

Set device-specific data.

void papplDeviceSetData(pappl_device_t *device, void *data);

Parameters

device Device
data Device data pointer

Discussion

This function sets any device-specific data needed to communicate with the device. It is normally only called from the open callback that was registered for the device URI scheme.

papplDeviceWrite

Write to a device.

ssize_t papplDeviceWrite(pappl_device_t *device, const void *buffer, size_t bytes);

Parameters

device Device
buffer Write buffer
bytes Number of bytes to write

Return Value

Number of bytes written or -1 on error

Discussion

This function buffers data that will be sent to the device. Call the papplDeviceFlush function to ensure that the data is immediately sent to the device.

papplGetRand

Return a 32-bit pseudo-random number.

unsigned papplGetRand(void);

Return Value

Random number

Discussion

This function returns a 32-bit pseudo-random number suitable for use as one-time identifiers or nonces. On platforms that provide it, the random numbers are generated (or seeded) using system entropy.

papplGetTempDir

Get the temporary directory.

const char *papplGetTempDir(void);

Return Value

Temporary directory

Discussion

This function gets the current temporary directory.

Note: On Windows, the path separators in the temporary directory are converted to forward slashes as needed for consistency.

papplJobCancel

Cancel a job.

void papplJobCancel(pappl_job_t *job);

Parameters

job Job

Discussion

This function cancels the specified job. If the job is currently being printed, it will be stopped at a convenient time (usually the end of a page) so that the printer will be left in a known state.

papplJobCreatePrintOptions

Create the printer options for a job.

pappl_pr_options_t *papplJobCreatePrintOptions(pappl_job_t *job, unsigned num_pages, bool color);

Parameters

job Job
num_pages Number of pages (0 for unknown)
color Is the document in color?

Return Value

Job options data or NULL on error

Discussion

This function allocates a printer options structure and computes the print options for a job based upon the Job Template attributes submitted in the print request and the default values set in the printer driver data.

The "num_pages" and "color" arguments specify the number of pages and whether the document contains non-grayscale colors - this information typically comes from parsing the job file.

papplJobCreateWithFile

Create a job with a local file.

pappl_job_t *papplJobCreateWithFile(pappl_printer_t *printer, const char *username, const char *format, const char *job_name, int num_options, cups_option_t *options, const char *filename);

Parameters

printer Printer
username Submitting user name
format MIME media type of file
job_name Job name
num_options Number of options
options Options or NULL if none
filename File to print

Return Value

New job object or NULL on error

Discussion

This function creates a new print job with a local file. The "num_options" and "options" parameters specify additional print options, as needed. The file specified by "filename" is removed automatically if it resides in the spool directory.

papplJobDeletePrintOptions

Delete a job options structure.

void papplJobDeletePrintOptions(pappl_pr_options_t *options);

Parameters

options Options

Discussion

This function frees the memory used for a job options structure.

papplJobFilterImage

Filter an image in memory.

bool papplJobFilterImage(pappl_job_t *job, pappl_device_t *device, pappl_pr_options_t *options, const unsigned char *pixels, int width, int height, int depth, int ppi, bool smoothing);

Parameters

job Job
device Device
options Print options
pixels Pointer to the top-left corner of the image data
width Width in columns
height Height in lines
depth Bytes per pixel (1 for grayscale or 3 for sRGB)
ppi Pixels per inch (0 for unknown)
smoothing true to smooth/interpolate the image, false for nearest-neighbor sampling

Return Value

true on success, false otherwise

Discussion

This function will print a grayscale or sRGB image using the printer's raster driver interface, scaling and positioning the image as necessary based on the job options, and printing as many copies as requested.

The image data is an array of grayscale ("depth" = 1) or sRGB ("depth" = 3) pixels starting at the top-left corner of the image.

The image resolution ("ppi") is expressed in pixels per inch and is used for some "print-scaling" modes. Pass 0 if the image has no explicit resolution information.

papplJobGetAttribute

Get an attribute from a job.

ipp_attribute_t *papplJobGetAttribute(pappl_job_t *job, const char *name);

Parameters

job Job
name Attribute name

Return Value

Attribute or NULL if not found

Discussion

This function gets the named IPP attribute from a job. The returned attribute can be examined using the ippGetXxx functions.

papplJobGetCopies

Get the number of copies in the job.

int papplJobGetCopies(pappl_job_t *job);

Parameters

job Job

Return Value

Number of copies

Discussion

This function returns the number of copies to produce of the job's document data.

papplJobGetCopiesCompleted

Get the number of completed copies.

int papplJobGetCopiesCompleted(pappl_job_t *job);

Parameters

job Job

Return Value

Number of completed copies

Discussion

This function returns the number of copies that have been completed.

papplJobGetData

Get per-job driver data.

void *papplJobGetData(pappl_job_t *job);

Parameters

job Job

Return Value

Per-job driver data or NULL if none

Discussion

This function returns the driver data associated with the job. It is normally only called from drivers to maintain state for the processing of the job, for example to store bitmap compression information.

papplJobGetFilename

Get the job's filename.

const char *papplJobGetFilename(pappl_job_t *job);

Parameters

job Job

Return Value

Filename or NULL if none

Discussion

This function returns the filename for the job's document data.

papplJobGetFormat

Get the MIME media type for the job's file.

const char *papplJobGetFormat(pappl_job_t *job);

Parameters

job Job

Return Value

MIME media type or NULL for none

Discussion

This function returns the MIME media type for the job's document data.

papplJobGetID

Get the job ID value.

int papplJobGetID(pappl_job_t *job);

Parameters

job Job

Return Value

Job ID or 0 for none

Discussion

This function returns the job's unique integer identifier.

papplJobGetImpressions

Get the number of impressions (sides) in the job.

int papplJobGetImpressions(pappl_job_t *job);

Parameters

job Job

Return Value

Number of impressions in job

Discussion

This function returns the number of impressions in the job's document data. An impression is one side of an output page.

papplJobGetImpressionsCompleted

Get the number of completed impressions (sides) in the job.

int papplJobGetImpressionsCompleted(pappl_job_t *job);

Parameters

job Job

Return Value

Number of completed impressions in job

Discussion

This function returns the number of impressions that have been printed. An impression is one side of an output page.

papplJobGetMessage

Get the current job message string, if any.

const char *papplJobGetMessage(pappl_job_t *job);

Parameters

job Job

Return Value

Current "job-state-message" value or NULL for none

Discussion

This function returns the current job message string, if any.

papplJobGetName

Get the job name/title.

const char *papplJobGetName(pappl_job_t *job);

Parameters

job Job

Return Value

Job name/title or NULL for none

Discussion

This function returns the name or title of the job.

papplJobGetPrinter

Get the printer for the job.

pappl_printer_t *papplJobGetPrinter(pappl_job_t *job);

Parameters

job Job

Return Value

Printer

Discussion

This function returns the printer containing the job.

papplJobGetReasons

Get the current job state reasons.

pappl_jreason_t papplJobGetReasons(pappl_job_t *job);

Parameters

job Job

Return Value

IPP "job-state-reasons" bits

Discussion

This function returns the current job state reasons bitfield.

papplJobGetState

Get the current job state.

ipp_jstate_t papplJobGetState(pappl_job_t *job);

Parameters

job Job

Return Value

IPP "job-state" value

Discussion

This function returns the current job processing state, which is represented as an enumeration:

  • IPP_JSTATE_ABORTED: Job has been aborted by the system due to an error.
  • IPP_JSTATE_CANCELED: Job has been canceled by a user.
  • IPP_JSTATE_COMPLETED: Job has finished printing.
  • IPP_JSTATE_HELD: Job is being held for some reason, typically because the document data is being received.
  • IPP_JSTATE_PENDING: Job is queued and waiting to be printed.
  • IPP_JSTATE_PROCESSING: Job is being printed.
  • IPP_JSTATE_STOPPED: Job is paused, typically when the printer is not ready.

papplJobGetTimeCompleted

Get the job completion time, if any.

time_t papplJobGetTimeCompleted(pappl_job_t *job);

Parameters

job Job

Return Value

Date/time when the job completed or 0 if not completed

Discussion

This function returns the date and time when the job reached the completed, canceled, or aborted states. 0 is returned if the job is not yet in one of those states.

papplJobGetTimeCreated

Get the job creation time.

time_t papplJobGetTimeCreated(pappl_job_t *job);

Parameters

job Job

Return Value

Date/time when the job was created

Discussion

This function returns the date and time when the job was created.

papplJobGetTimeProcessed

Get the job processing time.

time_t papplJobGetTimeProcessed(pappl_job_t *job);

Parameters

job Job

Return Value

Date/time when the job started processing (printing) or 0 if not yet processed

Discussion

This function returns the date and time when the job started processing (printing).

papplJobGetUsername

Get the name of the user that submitted the job.

const char *papplJobGetUsername(pappl_job_t *job);

Parameters

job Job

Return Value

Username or NULL for unknown

Discussion

This function returns the name of the user that submitted the job.

papplJobHold

Hold a job for printing.

bool papplJobHold(pappl_job_t *job, const char *username, const char *until, time_t until_time);

Parameters

job Job
username User that held the job or NULL for none/system
until "job-hold-until" keyword or NULL
until_time "job-hold-until-time" value or 0 for indefinite

Return Value

true on success, false on failure

Discussion

This function holds a pending job for printing at a later time.

papplJobIsCanceled

Return whether the job is canceled.

bool papplJobIsCanceled(pappl_job_t *job);

Parameters

job Job

Return Value

true if the job is canceled or aborted, false otherwise

Discussion

This function returns true if the job has been canceled or aborted.

papplJobOpenFile

Create or open a file for the document in a job.

int papplJobOpenFile(pappl_job_t *job, char *fname, size_t fnamesize, const char *directory, const char *ext, const char *mode);

Parameters

job Job
fname Filename buffer
fnamesize Size of filename buffer
directory Directory to store in (NULL for default)
ext Extension (NULL for default)
mode Open mode - "r" for reading or "w" for writing

Return Value

File descriptor or -1 on error

Discussion

This function creates or opens a file for a job. The "fname" and "fnamesize" arguments specify the location and size of a buffer to store the job filename, which incorporates the "directory", printer ID, job ID, job name (title), and "ext" values. The job name is "sanitized" to only contain alphanumeric characters.

The "mode" argument is "r" to read an existing job file or "w" to write a new job file. New files are created with restricted permissions for security purposes.

papplJobRelease

Release a job for printing.

bool papplJobRelease(pappl_job_t *job, const char *username);

Parameters

job Job
username User that released the job or NULL for none/system

Return Value

true on success, false on failure

Discussion

This function releases a held job for printing.

papplJobResume

Resume processing of a job.

void papplJobResume(pappl_job_t *job, pappl_jreason_t remove);

Parameters

job Job
remove Reasons to remove from "job-state-reasons"

papplJobRetain

Retain a completed job until the specified time.

bool papplJobRetain(pappl_job_t *job, const char *username, const char *until, int until_interval, time_t until_time);

Parameters

job Job
username User that held the job or NULL for none/system
until "job-retain-until" value or NULL for none
until_interval "job-retain-until-interval" value or 0 for none
until_time "job-retain-until-time" value or 0 for none

Return Value

true on success, false on failure

papplJobSetCopiesCompleted

Add completed copies to the job.

void papplJobSetCopiesCompleted(pappl_job_t *job, int add);

Parameters

job Job
add Number of copies to add

Discussion

This function updates the number of completed impressions in a job. An impression is one side of an output page.

papplJobSetData

Set the per-job driver data pointer.

void papplJobSetData(pappl_job_t *job, void *data);

Parameters

job Job
data Data pointer

Discussion

This function sets the driver data for the specified job. It is normally only called from drivers to maintain state for the processing of the job, for example to store bitmap compression information.

papplJobSetImpressions

Set the number of impressions (sides) in a job.

void papplJobSetImpressions(pappl_job_t *job, int impressions);

Parameters

job Job
impressions Number of impressions/sides

Discussion

This function sets the number of impressions in a job. An impression is one side of an output page.

papplJobSetImpressionsCompleted

Add completed impressions (sides) to the job.

void papplJobSetImpressionsCompleted(pappl_job_t *job, int add);

Parameters

job Job
add Number of impressions/sides to add

Discussion

This function updates the number of completed impressions in a job. An impression is one side of an output page.

papplJobSetMessage

Set the job message string.

void papplJobSetMessage(pappl_job_t *job, const char *message, ...);

Parameters

job Job
message Printf-style message string
... Additional arguments as needed

Discussion

This function sets the job message string using a printf-style format string.

Note: The maximum length of the job message string is 1023 bytes.

papplJobSetReasons

Set the job state reasons bit values.

void papplJobSetReasons(pappl_job_t *job, pappl_jreason_t add, pappl_jreason_t remove);

Parameters

job Job
add IPP "job-state-reasons" bit value(s) to add
remove IPP "job-state-reasons" bit value(s) to remove

Discussion

This function updates the job state reasons bitfield. The "remove" bits are cleared first, then the "add" bits are set.

papplJobSuspend

Temporarily stop processing of a job.

void papplJobSuspend(pappl_job_t *job, pappl_jreason_t add);

Parameters

job Job
add Reasons to add to "job-state-reasons"

papplLocFormatString

Format a localized string into a buffer.

const char *papplLocFormatString(pappl_loc_t *loc, char *buffer, size_t bufsize, const char *key, ...);

Parameters

loc Localization data
buffer Output buffer
bufsize Size of output buffer
key Printf-style key string to localize
... Additional arguments as needed

Return Value

Localized formatted string

Discussion

This function formats a localized string into a buffer using the specified localization data. Numbers are formatted according to the locale and language used.

papplLocGetDefaultMediaSizeName

Get the default media size name associated with a locale.

const char *papplLocGetDefaultMediaSizeName(void);

Return Value

PWG media size name

Discussion

This function returns the default PWG media size name corresponding to the current locale. Currently only "na_letter_8.5x11in" or "iso_a4_210x297mm" are returned.

papplLocGetString

Get a localized version of a key string.

const char *papplLocGetString(pappl_loc_t *loc, const char *key);

Parameters

loc Localization data
key Key text

Return Value

Localized text string

Discussion

This function looks up the specified key string in the localization data and returns either the localized value or the original key string if no localization is available.

papplLog

Log a message for the system.

void papplLog(pappl_system_t *system, pappl_loglevel_t level, const char *message, ...);

Parameters

system System
level Log level
message Printf-style message string
... Additional arguments as needed

Discussion

This function sends a message to the system's log file. The "level" argument specifies the urgency of the message:

  • PAPPL_LOGLEVEL_DEBUG: A debugging message.
  • PAPPL_LOGLEVEL_ERROR: An error message.
  • PAPPL_LOGLEVEL_FATAL: A fatal error message.
  • PAPPL_LOGLEVEL_INFO: An informational message.
  • PAPPL_LOGLEVEL_WARN: A warning message.

The "message" argument specifies a printf-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters.

papplLogClient

Log a message for a client.

void papplLogClient(pappl_client_t *client, pappl_loglevel_t level, const char *message, ...);

Parameters

client Client
level Log level
message Printf-style message string
... Additional arguments as needed

Discussion

This function sends a client message to the system's log file. The "level" argument specifies the urgency of the message:

  • PAPPL_LOGLEVEL_DEBUG: A debugging message.
  • PAPPL_LOGLEVEL_ERROR: An error message.
  • PAPPL_LOGLEVEL_FATAL: A fatal error message.
  • PAPPL_LOGLEVEL_INFO: An informational message.
  • PAPPL_LOGLEVEL_WARN: A warning message.

The "message" argument specifies a printf-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters.

papplLogDevice

Log a device error for the system...

void papplLogDevice(const char *message, void *data);

Parameters

message Message
data System

Discussion

This function sends a device error message to the system's log file.

papplLogJob

Log a message for a job.

void papplLogJob(pappl_job_t *job, pappl_loglevel_t level, const char *message, ...);

Parameters

job Job
level Log level
message Printf-style message string
... Additional arguments as needed

Discussion

This function sends a job message to the system's log file. The "level" argument specifies the urgency of the message:

  • PAPPL_LOGLEVEL_DEBUG: A debugging message.
  • PAPPL_LOGLEVEL_ERROR: An error message.
  • PAPPL_LOGLEVEL_FATAL: A fatal error message.
  • PAPPL_LOGLEVEL_INFO: An informational message.
  • PAPPL_LOGLEVEL_WARN: A warning message.

The "message" argument specifies a printf-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters.

papplLogPrinter

Log a message for a printer.

void papplLogPrinter(pappl_printer_t *printer, pappl_loglevel_t level, const char *message, ...);

Parameters

printer Printer
level Log level
message Printf-style message string
... Additional arguments as needed

Discussion

This function sends a printer message to the system's log file. The "level" argument specifies the urgency of the message:

  • PAPPL_LOGLEVEL_DEBUG: A debugging message.
  • PAPPL_LOGLEVEL_ERROR: An error message.
  • PAPPL_LOGLEVEL_FATAL: A fatal error message.
  • PAPPL_LOGLEVEL_INFO: An informational message.
  • PAPPL_LOGLEVEL_WARN: A warning message.

The "message" argument specifies a printf-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters.

papplMainloop

Run a standard main loop for printer applications.

int papplMainloop(int argc, char *argv[], const char *version, const char *footer_html, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_driver_cb_t driver_cb, const char *subcmd_name, pappl_ml_subcmd_cb_t subcmd_cb, pappl_ml_system_cb_t system_cb, pappl_ml_usage_cb_t usage_cb, void *data);

Parameters

argc Number of command line arguments
argv[] Command line arguments
version Version number
footer_html Footer HTML or NULL for none
num_drivers Number of drivers
drivers Drivers
autoadd_cb Auto-add callback or NULL for none
driver_cb Driver callback
subcmd_name Sub-command name or NULL for none
subcmd_cb Sub-command callback or NULL for none
system_cb System callback or NULL for default
usage_cb Usage callback or NULL for default
data Context pointer

Return Value

Exit status

Discussion

This function runs a standard main loop for a printer application. The "argc" and "argv" arguments are those provided to the main function.

The "version" argument specifies a numeric version number for the printer application that conforms to semantic versioning guidelines with up to four numbers, for example "1.2.3.4".

The "footer_html" argument specifies HTML text to use in the footer of the web interface. If NULL, the footer is omitted.

The "num_drivers", "drivers", and "driver_cb" arguments specify a list of drivers and the driver callback for printers. Specify 0 and NULL if the drivers are configured in the system callback. The "autoadd_cb" argument specifies a callback for automatically adding new printers with the "autoadd" sub-command and for auto-detecting the driver when adding manually.

The "usage_cb" argument specifies a callback that displays a usage/help summary. If NULL, a generic summary is shown as needed.

The "subcmd_name" and "subcmd_cb" arguments specify the name and a callback for a custom sub-command. If NULL, no custom sub-commands will be supported.

The "system_cb" argument specifies a function that will create a new pappl_system_t object. If NULL, a default system object is created.

The "data" argument provides application-specific data for each of the callbacks.

papplMainloopShutdown

Request a shutdown of a running system.

void papplMainloopShutdown(void);

Discussion

This function requests that the system started by papplMainloop be shutdown.

papplPrinterAddLink

Add a printer link to the navigation header.

void papplPrinterAddLink(pappl_printer_t *printer, const char *label, const char *path_or_url, pappl_loptions_t options);

Parameters

printer Printer
label Label string
path_or_url Path or URL
options Link options

Discussion

This function adds a navigation link for a printer. The "path_or_url" argument specifies a absolute path such as "/ipp/print/example/page" or an absolute URL such as "https://www.example.com/". The "options" argument specifies where the link is shown and whether the link should redirect an absolute path to the secure ("https://.../path") web interface.

papplPrinterCancelAllJobs

Cancel all jobs on the printer.

void papplPrinterCancelAllJobs(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function cancels all jobs on the printer. If any job is currently being printed, it will be stopped at a convenient time (usually the end of a page) so that the printer will be left in a known state.

papplPrinterCloseDevice

Close the device associated with the printer.

void papplPrinterCloseDevice(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function closes the device for a printer. The device must have been previously opened using the papplPrinterOpenDevice function.

papplPrinterCreate

Create a new printer.

pappl_printer_t *papplPrinterCreate(pappl_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_id, const char *device_uri);

Parameters

system System
printer_id printer-id value or 0 for new
printer_name Human-readable printer name
driver_name Driver name
device_id IEEE-1284 device ID
device_uri Device URI

Return Value

Printer or NULL on error

Discussion

This function creates a new printer (service) on the specified system. The "type" argument specifies the type of service to create and must currently be the value PAPPL_SERVICE_TYPE_PRINT.

The "printer_id" argument specifies a positive integer identifier that is unique to the system. If you specify a value of 0 a new identifier will be assigned.

The "driver_name" argument specifies a named driver for the printer, from the list of drivers registered with the papplSystemSetPrinterDrivers function.

The "device_id" and "device_uri" arguments specify the IEEE-1284 device ID and device URI strings for the printer.

On error, this function sets the errno variable to one of the following values:

  • EEXIST: A printer with the specified name already exists.
  • EINVAL: Bad values for the arguments were specified.
  • EIO: The driver callback failed.
  • ENOENT: No driver callback has been set.
  • ENOMEM: Ran out of memory.

papplPrinterDelete

Delete a printer.

void papplPrinterDelete(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function deletes a printer from a system, freeing all memory and canceling all jobs as needed.

papplPrinterDisable

Stop accepting jobs on a printer.

void papplPrinterDisable(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function stops accepting jobs on a printer.

papplPrinterEnable

Start accepting jobs on a printer.

void papplPrinterEnable(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function starts accepting jobs on a printer.

papplPrinterFindJob

Find a job.

pappl_job_t *papplPrinterFindJob(pappl_printer_t *printer, int job_id);

Parameters

printer Printer
job_id Job ID

Return Value

Job or NULL if not found

Discussion

This function finds a job submitted to a printer using its integer ID value.

papplPrinterGetContact

Get the "printer-contact" value.

pappl_contact_t *papplPrinterGetContact(pappl_printer_t *printer, pappl_contact_t *contact);

Parameters

printer Printer
contact Contact

Return Value

Contact

Discussion

This function copies the current printer contact information to the buffer pointed to by the "contact" argument.

papplPrinterGetDNSSDName

Get the current DNS-SD service name.

char *papplPrinterGetDNSSDName(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

DNS-SD service name or NULL for none

Discussion

This function copies the current DNS-SD service name to the buffer pointed to by the "buffer" argument.

papplPrinterGetDeviceID

Get the IEEE-1284 device ID of the printer.

const char *papplPrinterGetDeviceID(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

IEEE-1284 device ID string

Discussion

This function returns the IEEE-1284 device ID of the printer.

papplPrinterGetDeviceURI

Get the URI of the device associated with the printer.

const char *papplPrinterGetDeviceURI(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Device URI string

Discussion

This function returns the device URI for the printer.

papplPrinterGetDriverAttributes

Get a copy of the current driver attributes.

ipp_t *papplPrinterGetDriverAttributes(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Copy of driver attributes

Discussion

This function returns a copy the current driver attributes. Use the ippDelete function to free the memory used for the attributes when you are done.

papplPrinterGetDriverData

Get the current print driver data.

pappl_pr_driver_data_t *papplPrinterGetDriverData(pappl_printer_t *printer, pappl_pr_driver_data_t *data);

Parameters

printer Printer
data Pointer to driver data structure to fill

Return Value

Driver data or NULL if none

Discussion

This function copies the current print driver data, defaults, and ready (loaded) media information into the specified buffer.

papplPrinterGetDriverName

Get the driver name for a printer.

const char *papplPrinterGetDriverName(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Driver name or NULL for none

Discussion

This function returns the driver name for the printer.

papplPrinterGetGeoLocation

Get the current geo-location as a "geo:" URI.

char *papplPrinterGetGeoLocation(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

"geo:" URI or NULL for unknown

Discussion

This function copies the currently configured geographic location as a "geo:" URI to the buffer pointed to by the "buffer" argument.

papplPrinterGetID

Get the printer ID.

int papplPrinterGetID(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

"printer-id" value or 0 for none

Discussion

This function returns the printer's unique positive integer identifier.

papplPrinterGetImpressionsCompleted

Get the number of impressions (sides) that have been printed.

int papplPrinterGetImpressionsCompleted(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Number of printed impressions/sides

Discussion

This function returns the number of impressions that have been printed. An impression is one side of an output page.

papplPrinterGetLocation

Get the location string.

char *papplPrinterGetLocation(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

Location or NULL for none

Discussion

This function copies the printer's human-readable location to the buffer pointed to by the "buffer" argument.

papplPrinterGetMaxActiveJobs

Get the maximum number of active (queued) jobs allowed by the printer.

int papplPrinterGetMaxActiveJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Maximum number of active jobs, 0 for unlimited

Discussion

This function returns the maximum number of active jobs that the printer supports, as configured by the papplPrinterSetMaxActiveJobs function.

papplPrinterGetMaxCompletedJobs

Get the maximum number of jobs retained for history by the printer.

int papplPrinterGetMaxCompletedJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Maximum number of completed jobs, 0 for unlimited

Discussion

This function returns the maximum number of jobs that are retained in the job history as configured by the papplPrinterSetMaxCompletedJobs function.

papplPrinterGetMaxPreservedJobs

Get the maximum number of jobs preserved by the printer.

int papplPrinterGetMaxPreservedJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Maximum number of preserved jobs, 0 for none

Discussion

This function returns the maximum number of jobs that are retained (including document data) in the job history as configured by the papplPrinterSetMaxPreservedJobs function.

papplPrinterGetName

Get the printer name.

const char *papplPrinterGetName(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Printer name

Discussion

This function returns the printer's human-readable name.

papplPrinterGetNextJobID

Get the next job ID.

int papplPrinterGetNextJobID(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Next job ID or 0 for none

Discussion

This function returns the positive integer identifier that will be used for the next job that is created.

papplPrinterGetNumberOfActiveJobs

Get the number of active print jobs.

int papplPrinterGetNumberOfActiveJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Number of active print jobs

Discussion

This function returns the number of print jobs that are either printing or waiting to be printed.

papplPrinterGetNumberOfCompletedJobs

Get the number of completed print jobs.

int papplPrinterGetNumberOfCompletedJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Number of completed print jobs

Discussion

This function returns the number of print jobs that have been aborted, canceled, or completed.

papplPrinterGetNumberOfJobs

Get the total number of print jobs.

int papplPrinterGetNumberOfJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Total number of print jobs

Discussion

This function returns the number of print jobs that are printing, waiting to be printed, have been aborted, have been canceled, or have completed.

papplPrinterGetOrganization

Get the organization name.

char *papplPrinterGetOrganization(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

Organization name or NULL for none

Discussion

This function copies the printer's organization name to the buffer pointed to by the "buffer" argument.

papplPrinterGetOrganizationalUnit

Get the organizational unit name.

char *papplPrinterGetOrganizationalUnit(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

Organizational unit name or NULL for none

Discussion

This function copies the printer's organizational unit name to the buffer pointed to by the "buffer" argument.

papplPrinterGetPath

Get the URL path for a printer web page.

char *papplPrinterGetPath(pappl_printer_t *printer, const char *subpath, char *buffer, size_t bufsize);

Parameters

printer Printer
subpath Sub-path or NULL for none
buffer String buffer
bufsize Size of string buffer

Return Value

URI path or NULL on error

Discussion

This function generates and returns the URL path for the printer's web page. The "subpath" argument specifies an optional sub-path for a specific printer web page.

papplPrinterGetPrintGroup

Get the print authorization group, if any.

char *papplPrinterGetPrintGroup(pappl_printer_t *printer, char *buffer, size_t bufsize);

Parameters

printer Printer
buffer String buffer
bufsize Size of string buffer

Return Value

Print authorization group name or NULL for none

Discussion

This function copies the printer's authorization group name to the buffer pointed to by the "buffer" argument.

papplPrinterGetReasons

Get the current "printer-state-reasons" bit values.

pappl_preason_t papplPrinterGetReasons(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

"printer-state-reasons" bit values

Discussion

This function returns the current printer state reasons bitfield, which can be updated by the printer driver and/or by the papplPrinterSetReasons function.

papplPrinterGetState

Get the current "printer-state" value.

ipp_pstate_t papplPrinterGetState(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

"printer-state" value

Discussion

This function returns the current printer state as an enumeration:

  • IPP_PSTATE_IDLE: The printer is idle and has no jobs to process.
  • IPP_PSTATE_PROCESSING: The printer is processing a job and/or producing output.
  • IPP_PSTATE_STOPPED: The printer is stopped for maintenance.

papplPrinterGetSupplies

Get the current "printer-supplies" values.

int papplPrinterGetSupplies(pappl_printer_t *printer, int max_supplies, pappl_supply_t *supplies);

Parameters

printer Printer
max_supplies Maximum number of supplies
supplies Array for supplies

Return Value

Number of values

Discussion

This function copies the current printer supply values to the specified array. The "max_supplies" and "supplies" arguments can be 0 and NULL to query the number of supplies used.

The return value is the actual number of supplies used by the printer, regardless of the size of the array.

papplPrinterGetSystem

Get the system associated with the printer.

pappl_system_t *papplPrinterGetSystem(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

System

Discussion

This function returns a pointer to the system object that contains the printer.

papplPrinterHoldNewJobs

Hold new jobs for printing.

bool papplPrinterHoldNewJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

true on success, false on failure

Discussion

This function holds any new jobs for printing and is typically used prior to performing printer maintenance. Existing jobs will finish printing but new jobs will be held until you call papplPrinterReleaseHeldNewJobs.

papplPrinterIsAcceptingJobs

Return whether the printer is accepting jobs.

bool papplPrinterIsAcceptingJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

true if the printer is accepting jobs, false otherwise

Discussion

This function returns a boolean value indicating whether a printer is accepting jobs.

papplPrinterIsDeleted

Return whether a printer is in the process of being deleted.

bool papplPrinterIsDeleted(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

true is printer is being deleted, false otherwise

Discussion

This function returns a boolean value indicating whether a printer is being deleted.

papplPrinterIsHoldingNewJobs

Return whether the printer is holding new jobs.

bool papplPrinterIsHoldingNewJobs(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

true if the printer is holding new jobs, false otherwise

Discussion

This function returns a boolean value indicating whether a printer is holding new jobs.

papplPrinterIterateActiveJobs

Iterate over the active jobs.

void papplPrinterIterateActiveJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit);

Parameters

printer Printer
cb Callback function
data Callback data
job_index First job to iterate (1-based)
limit Maximum jobs to iterate or 0 for no limit

Discussion

This function iterates over jobs that are either printing or waiting to be printed. The specified callback "cb" will be called once per job with the data pointer "data".

The "job_index" argument specifies the first job in the list to iterate, where 1 is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use 0 to iterate an unlimited number of jobs.

papplPrinterIterateAllJobs

Iterate over all the jobs.

void papplPrinterIterateAllJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit);

Parameters

printer Printer
cb Callback function
data Callback data
job_index First job to iterate (1-based)
limit Maximum jobs to iterate, 0 for no limit

Discussion

This function iterates over all jobs. The specified callback "cb" will be called once per job with the data pointer "data".

The "job_index" argument specifies the first job in the list to iterate, where 1 is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use 0 to iterate an unlimited number of jobs.

papplPrinterIterateCompletedJobs

Iterate over the completed jobs.

void papplPrinterIterateCompletedJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit);

Parameters

printer Printer
cb Callback function
data Callback data
job_index First job to iterate (1-based)
limit Maximum jobs to iterate, 0 for no limit

Discussion

This function iterates over jobs that are aborted, canceled, or completed. The specified callback "cb" will be called once per job with the data pointer "data".

The "job_index" argument specifies the first job in the list to iterate, where 1 is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use 0 to iterate an unlimited number of jobs.

papplPrinterOpenDevice

Open the device associated with a printer.

pappl_device_t *papplPrinterOpenDevice(pappl_printer_t *printer);

Parameters

printer Printer

Return Value

Device or NULL if not possible

Discussion

This function opens the printer's device. NULL is returned if the device is already in use, for example while a job is being printed.

The returned device must be closed using the papplPrinterCloseDevice function.

papplPrinterOpenFile

Create or open a file for a printer.

int papplPrinterOpenFile(pappl_printer_t *printer, char *fname, size_t fnamesize, const char *directory, const char *resname, const char *ext, const char *mode);

Parameters

printer Printer
fname Filename buffer
fnamesize Size of filename buffer
directory Directory to store in (NULL for default)
resname Resource name
ext Extension (NULL for none)
mode Open mode - "r" for reading or "w" for writing

Return Value

File descriptor or -1 on error

Discussion

This function creates, opens, or removes a file for a printer. The "fname" and "fnamesize" arguments specify the location and size of a buffer to store the printer filename, which incorporates the "directory", printer ID, resource name, and "ext" values. The resource name is "sanitized" to only contain alphanumeric characters.

The "mode" argument is "r" to read an existing printer file, "w" to write a new printer file, or "x" to remove an existing printer file. New files are created with restricted permissions for security purposes.

For the "r" and "w" modes, the return value is the file descriptor number on success or -1 on error. For the "x" mode, the return value is 0 on success and -1 on error. The errno variable is set appropriately on error.

papplPrinterPause

Pause (stop) a printer.

void papplPrinterPause(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function pauses a printer. If the printer is currently processing (printing) a job, it will be completed before the printer is stopped.

papplPrinterReleaseHeldNewJobs

Release any previously held jobs for printing.

bool papplPrinterReleaseHeldNewJobs(pappl_printer_t *printer, const char *username);

Parameters

printer Printer
username User that released the held jobs or NULL for none/system

Return Value

true on success, false on failure

Discussion

This function releases all jobs that were previously held due to a prior call to papplPrinterHoldNewJobs.

papplPrinterRemoveLink

Remove a printer link from the navigation header.

void papplPrinterRemoveLink(pappl_printer_t *printer, const char *label);

Parameters

printer Printer
label Label string

Discussion

This function removes the named link for the printer.

papplPrinterResume

Resume (start) a printer.

void papplPrinterResume(pappl_printer_t *printer);

Parameters

printer Printer

Discussion

This function resumes a printer and starts processing any pending jobs.

papplPrinterSetContact

Set the "printer-contact" value.

void papplPrinterSetContact(pappl_printer_t *printer, pappl_contact_t *contact);

Parameters

printer Printer
contact Contact

Discussion

This function sets the printer's contact information.

papplPrinterSetDNSSDName

Set the DNS-SD service name.

void papplPrinterSetDNSSDName(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value DNS-SD service name or NULL for none

Discussion

This function sets the printer's DNS-SD service name. If NULL, the printer will stop advertising the printer.

papplPrinterSetDriverData

Set the driver data.

bool papplPrinterSetDriverData(pappl_printer_t *printer, pappl_pr_driver_data_t *data, ipp_t *attrs);

Parameters

printer Printer
data Driver data
attrs Additional capability attributes or NULL for none

Return Value

true on success, false on failure

Discussion

This function validates and sets the driver data, including all defaults and ready (loaded) media.

Note: This function regenerates all of the driver-specific capability attributes like "media-col-database", "sides-supported", and so forth. Use the papplPrinterSetDriverDefaults or papplPrinterSetReadyMedia functions to efficiently change the "xxx-default" or "xxx-ready" values, respectively.

papplPrinterSetDriverDefaults

Set the default print option values.

bool papplPrinterSetDriverDefaults(pappl_printer_t *printer, pappl_pr_driver_data_t *data, int num_vendor, cups_option_t *vendor);

Parameters

printer Printer
data Driver data
num_vendor Number of vendor options
vendor Vendor options

Return Value

true on success or false on failure

Discussion

This function validates and sets the printer's default print options.

Note: Unlike papplPrinterSetPrintDriverData, this function only changes the "xxx_default" members of the driver data and is considered lightweight.

papplPrinterSetGeoLocation

Set the geo-location value as a "geo:" URI.

void papplPrinterSetGeoLocation(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value "geo:" URI or NULL for unknown

Discussion

This function sets the printer's geographic location as a "geo:" URI. If NULL, the location is cleared to the 'unknown' value.

papplPrinterSetImpressionsCompleted

Add impressions (sides) to the total count of printed impressions.

void papplPrinterSetImpressionsCompleted(pappl_printer_t *printer, int add);

Parameters

printer Printer
add Number of impressions/sides to add

Discussion

This function adds to the printer's impressions counter. An impression is one side of an output page.

papplPrinterSetLocation

Set the location string.

void papplPrinterSetLocation(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value Location ("Bob's Office", etc.) or NULL for none

Discussion

This function sets the printer's human-readable location string. If NULL, the location is cleared.

papplPrinterSetMaxActiveJobs

Set the maximum number of active jobs for the printer.

void papplPrinterSetMaxActiveJobs(pappl_printer_t *printer, int max_active_jobs);

Parameters

printer Printer
max_active_jobs Maximum number of active jobs, 0 for unlimited

Discussion

This function sets the maximum number of jobs that can be spooled on the printer at one time.

Note: This limit does not apply to streaming raster formats such as PWG Raster since they are not spooled.

papplPrinterSetMaxCompletedJobs

Set the maximum number of completed jobs for the printer.

void papplPrinterSetMaxCompletedJobs(pappl_printer_t *printer, int max_completed_jobs);

Parameters

printer Printer
max_completed_jobs Maximum number of completed jobs, 0 for unlimited

Discussion

This function sets the maximum number of aborted, canceled, or completed jobs that are retained in the job history.

papplPrinterSetMaxPreservedJobs

Set the maximum number of preserved jobs for the printer.

void papplPrinterSetMaxPreservedJobs(pappl_printer_t *printer, int max_preserved_jobs);

Parameters

printer Printer
max_preserved_jobs Maximum number of preserved jobs, 0 for none

Discussion

This function sets the maximum number of aborted, canceled, or completed jobs that are preserved (with document data) in the job history.

papplPrinterSetNextJobID

Set the next "job-id" value.

void papplPrinterSetNextJobID(pappl_printer_t *printer, int next_job_id);

Parameters

printer Printer
next_job_id Next "job-id" value

Discussion

This function sets the next unique positive integer identifier that will be used for a job.

Note: This function is normally only called once to restore the previous state of the printer.

papplPrinterSetOrganization

Set the organization name.

void papplPrinterSetOrganization(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value Organization name or NULL for none

Discussion

This function sets the printer's organization name. If NULL the value is cleared.

papplPrinterSetOrganizationalUnit

Set the organizational unit name.

void papplPrinterSetOrganizationalUnit(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value Organizational unit name or NULL for none

Discussion

This function sets the printer's organizational unit name. If NULL the value is cleared.

papplPrinterSetPrintGroup

Set the print authorization group, if any.

void papplPrinterSetPrintGroup(pappl_printer_t *printer, const char *value);

Parameters

printer Printer
value Print authorization group or NULL for none

Discussion

This function sets the printer's authorization group. If NULL, the group is cleared.

Note: The authorization group is only used if the system is created with a named authorization service.

papplPrinterSetReadyMedia

Set the ready (loaded) media.

bool papplPrinterSetReadyMedia(pappl_printer_t *printer, int num_ready, pappl_media_col_t *ready);

Parameters

printer Printer
num_ready Number of ready media
ready Array of ready media

Return Value

true on success or false on failure

Discussion

This function validates and sets the printer's ready (loaded) media.

papplPrinterSetReasons

Add or remove values from "printer-state-reasons".

void papplPrinterSetReasons(pappl_printer_t *printer, pappl_preason_t add, pappl_preason_t remove);

Parameters

printer Printer
add "printer-state-reasons" bit values to add or PAPPL_PREASON_NONE for none
remove "printer-state-reasons" bit values to remove or PAPPL_PREASON_NONE for none

Discussion

This function updates the printer state reasons bitfield by clearing any bit values in the "remove" argument and setting any bit values in the "add" argument.

papplPrinterSetSupplies

Set/update the supplies for a printer.

void papplPrinterSetSupplies(pappl_printer_t *printer, int num_supplies, pappl_supply_t *supplies);

Parameters

printer Printer
num_supplies Number of supplies
supplies Array of supplies

Discussion

This function updates the supply information for the printer.

papplPrinterSetUSB

Set the USB vendor and product IDs for a printer.

void papplPrinterSetUSB(pappl_printer_t *printer, unsigned vendor_id, unsigned product_id, pappl_uoptions_t options, const char *storagefile, pappl_pr_usb_cb_t usb_cb, void *usb_cbdata);

Parameters

printer Printer
vendor_id USB vendor ID
product_id USB product ID
options USB gadget options
storagefile USB storage file, if any
usb_cb USB processing callback, if any
usb_cbdata USB processing callback data, if any

Discussion

This function sets the USB vendor and product IDs for a printer as well as specifying USB gadget options when the printer is registered with the USB device controller.

The usb_cb argument specifies a processing callback that is called for every byte of data sent from the USB host and which is responsible for interpreting the data, writing data to the device, and handling back-channel data.

Note: USB gadget functionality is currently only available when running on Linux with compatible hardware such as the Raspberry Pi Zero and 4B.

papplSubscriptionCancel

Cancel a subscription.

void papplSubscriptionCancel(pappl_subscription_t *sub);

Parameters

sub Subscription

Discussion

This function cancels a subscription.

papplSubscriptionCreate

Create a subscription.

pappl_subscription_t *papplSubscriptionCreate(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, int sub_id, pappl_event_t events, const char *username, const char *language, const void *data, size_t datalen, int interval, int lease);

Parameters

system System
printer Printer, if any
job Job, if any
sub_id Subscription ID or 0 for new
events Notification events
username Owner
language Language
data User data, if any
datalen Length of user data
interval Notification interval
lease Lease duration or 0 for unlimited

Return Value

Subscription

Discussion

This function creates a new system, printer, or job event subscription.

papplSubscriptionGetEvents

Return a subscription's events.

pappl_event_t papplSubscriptionGetEvents(pappl_subscription_t *sub);

Parameters

sub Subscription

Return Value

IPP "notify-events" bit field

Discussion

This function returns a subscription's events.

papplSubscriptionGetID

Return a subscription's numeric identifier.

int papplSubscriptionGetID(pappl_subscription_t *sub);

Parameters

sub Subscription

Return Value

Subscription ID

Discussion

This function returns a subscription's numeric identifier.

papplSubscriptionGetJob

Return a subscription's associated job, if any.

pappl_job_t *papplSubscriptionGetJob(pappl_subscription_t *sub);

Parameters

sub Subscription

Return Value

Job or NULL if not a job subscription

Discussion

This function returns a subscription's associated job, if any.

papplSubscriptionGetPrinter

Return a subscription's associated printer, if any.

pappl_printer_t *papplSubscriptionGetPrinter(pappl_subscription_t *sub);

Parameters

sub Subscription

Return Value

Printer or NULL if not a printer subscription

Discussion

This function returns a subscription's associated printer, if any.

papplSubscriptionGetUsername

Return a subscription's owner.

const char *papplSubscriptionGetUsername(pappl_subscription_t *sub);

Parameters

sub Subscription

Return Value

Owner

Discussion

This function returns a subscription's owner.

papplSubscriptionRenew

Renew a subscription.

void papplSubscriptionRenew(pappl_subscription_t *sub, int lease);

Parameters

sub Subscription
lease Lease duration in seconds (0 for indefinite)

papplSystemAddEvent

Add a notification event.

void papplSystemAddEvent(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, const char *message, ...);

Parameters

system System
printer Associated printer, if any
job Associated job, if any
event IPP "notify-events" bit value
message printf-style message string
... Additional arguments as needed

papplSystemAddLink

Add a link to the navigation header.

void papplSystemAddLink(pappl_system_t *system, const char *label, const char *path_or_url, pappl_loptions_t options);

Parameters

system System
label Label string
path_or_url Path or URL
options Link options

Discussion

This function adds a navigation link for the system. The "path_or_url" argument specifies a absolute path such as "/page" or an absolute URL such as "https://www.example.com/". The "options" argument specifies where the link is shown and whether the link should redirect an absolute path to the secure ("https://.../path") web interface.

papplSystemAddListeners

Add network or domain socket listeners.

bool papplSystemAddListeners(pappl_system_t *system, const char *name);

Parameters

system System
name Hostname, domain socket filename, or NULL

Return Value

true on success, false on failure

Discussion

This function adds socket listeners. The "name" parameter specifies the listener address. Names starting with a slash (/) specify a UNIX domain socket path, otherwise the name is treated as a fully-qualified domain name or numeric IPv4 or IPv6 address. If name is NULL, the "any" addresses are used ("0.0.0.0" and "[::]").

Listeners cannot be added after papplSystemRun is called.

papplSystemAddMIMEFilter

Add a file filter to the system.

void papplSystemAddMIMEFilter(pappl_system_t *system, const char *srctype, const char *dsttype, pappl_mime_filter_cb_t cb, void *data);

Parameters

system System
srctype Source MIME media type (constant) string
dsttype Destination MIME media type (constant) string
cb Filter callback function
data Filter callback data

Discussion

This function adds a file filter to the system to be used for processing different kinds of document data in print jobs. The "srctype" and "dsttype" arguments specify the source and destination MIME media types as constant strings. A destination MIME media type of "image/pwg-raster" specifies a filter that uses the driver's raster interface. Other destination types imply direct submission to the output device using the papplDeviceXxx functions.

Note: This function may not be called while the system is running.

papplSystemAddResourceCallback

Add a dynamic resource that uses a callback function.

void papplSystemAddResourceCallback(pappl_system_t *system, const char *path, const char *format, pappl_resource_cb_t cb, void *data);

Parameters

system System object
path Resource path
format MIME media type for content such as "text/html"
cb Callback function
data Callback data

Discussion

This function adds a dynamic resource at the specified path. When a client GET or POST request is received at the specified path, the "cb" function will be called with the client pointer and "data" pointer to respond to it.

Resource callbacks are most often used to implement custom web pages.

Note: Any custom web page that is added prior to calling the papplSystemRun function will replace the corresponding standard web page at the same path.

papplSystemAddResourceData

Add a static data resource.

void papplSystemAddResourceData(pappl_system_t *system, const char *path, const char *format, const void *data, size_t datalen);

Parameters

system System object
path Resource path
format MIME media type such as "image/png"
data Resource data
datalen Size of resource data

Discussion

This function adds a static resource at the specified path. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system.

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddResourceDirectory

Add external files in a directory as resources.

void papplSystemAddResourceDirectory(pappl_system_t *system, const char *basepath, const char *directory);

Parameters

system System object
basepath Base resource path
directory Directory containing resource files

Discussion

This function adds static resources from the specified directory under the specified path. The directory is scanned and only those files present at the time of the call are available, and those files must remain stable for as long as the resources are added to the system..

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddResourceFile

Add an external file as a resource.

void papplSystemAddResourceFile(pappl_system_t *system, const char *path, const char *format, const char *filename);

Parameters

system System object
path Resource path
format MIME media type such as "image/png"
filename Filename

Discussion

This function adds a static resource at the specified path. The provided file is not copied to the resource and must remain stable for as long as the resource is added to the system.

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddResourceString

Add a static data resource as a C string.

void papplSystemAddResourceString(pappl_system_t *system, const char *path, const char *format, const char *data);

Parameters

system System object
path Resource path
format MIME media type such as "image/png"
data Resource data

Discussion

This function adds a static resource at the specified path. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system.

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddStringsData

Add a static localization file resource.

void papplSystemAddStringsData(pappl_system_t *system, const char *path, const char *language, const char *data);

Parameters

system System object
path Resource path
language ISO language tag such as "en-US", "fr-CA", etc.
data Nul-terminated string containing strings file data

Discussion

This function adds a static localization resource at the specified path. Localization files use the NeXTStep strings ("text/strings") format defined in PWG Candidate Standard 5100.13-2013. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system.

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddStringsFile

Add an external localization file resource.

void papplSystemAddStringsFile(pappl_system_t *system, const char *path, const char *language, const char *filename);

Parameters

system System object
path Resource path
language ISO language tag such as "en-US", "fr-CA", etc.
filename Filename

Discussion

This function adds a static localization resource at the specified path. Localization files use the NeXTStep strings ("text/strings") format defined in PWG Candidate Standard 5100.13-2013. The provided file is not copied to the resource and must remain stable for as long as the resource is added to the system.

Note: Any resource that is added prior to calling the papplSystemRun function will replace the corresponding standard resource at the same path.

papplSystemAddTimerCallback

Add a timer callback to a system.

bool papplSystemAddTimerCallback(pappl_system_t *system, time_t start, int interval, pappl_timer_cb_t cb, void *cb_data);

Parameters

system System
start Start time in seconds or 0 for the current time
interval Repeat interval in seconds or 0 for no repeat
cb Callback function
cb_data Callback data

Return Value

true on success, false on error

Discussion

This function schedules a function that will be called on the main run loop thread at the specified time and optionally every "interval" seconds thereafter. The timing accuracy is typically within a few milliseconds but is not guaranteed. Since the callback is run on the main run loop thread, functions should create a new thread for any long-running operations.

The callback function receives the "system" and "cb_data" pointers and returns true to repeat the timer or false to remove it:

bool my_timer_cb(pappl_system_t *system, void *cb_data)
{
  ... do periodic task ...
  return (true); // repeat the timer
}

papplSystemCleanJobs

Clean out old (completed) jobs.

void papplSystemCleanJobs(pappl_system_t *system);

Parameters

system System

Discussion

This function deletes all old (completed) jobs above the limit set by the papplPrinterSetMaxCompletedJobs function. The level may temporarily exceed this limit if the jobs were completed within the last 60 seconds.

Note: This function is normally called automatically from the papplSystemRun function.

papplSystemCreate

Create a system object.

pappl_system_t *papplSystemCreate(pappl_soptions_t options, const char *name, int port, const char *subtypes, const char *spooldir, const char *logfile, pappl_loglevel_t loglevel, const char *auth_service, bool tls_only);

Parameters

options Server options
name System name
port Port number or 0 for auto
subtypes DNS-SD sub-types or NULL for none
spooldir Spool directory or NULL for default
logfile Log file or NULL for default
loglevel Log level
auth_service PAM authentication service or NULL for none
tls_only Only support TLS connections?

Return Value

System object

Discussion

This function creates a new system object, which is responsible for managing all the printers, jobs, and resources used by the printer application.

The "options" argument specifies which options are enabled for the server:

  • PAPPL_SOPTIONS_NONE: No options.
  • PAPPL_SOPTIONS_DNSSD_HOST: When resolving DNS-SD service name collisions, use the DNS-SD hostname instead of a serial number or UUID.
  • PAPPL_SOPTIONS_WEB_LOG: Include the log file web page.
  • PAPPL_SOPTIONS_MULTI_QUEUE: Support multiple printers.
  • PAPPL_SOPTIONS_WEB_NETWORK: Include the network settings web page.
  • PAPPL_SOPTIONS_RAW_SOCKET: Accept jobs via raw sockets starting on port 9100 (all but Windows).
  • PAPPL_SOPTIONS_WEB_REMOTE: Allow remote queue management.
  • PAPPL_SOPTIONS_WEB_SECURITY: Include the security settings web page.
  • PAPPL_SOPTIONS_WEB_INTERFACE: Include the standard printer and job monitoring web pages.
  • PAPPL_SOPTIONS_WEB_TLS: Include the TLS settings page.
  • PAPPL_SOPTIONS_USB_PRINTER: Accept jobs via USB for the default printer (embedded Linux only).

The "name" argument specifies a human-readable name for the system.

The "port" argument specifies the port number to bind to. A value of 0 will cause an available port number to be assigned when the first listener is added with the papplSystemAddListeners function.

The "subtypes" argument specifies one or more comma-delimited DNS-SD service sub-types such as "_print" and "_universal".

The "spooldir" argument specifies the location of job files. If NULL, a temporary directory is created.

The "logfile" argument specifies where to send log messages. If NULL, the log messages are written to a temporary file.

The "loglevel" argument specifies the initial logging level.

The "auth_service" argument specifies a PAM authentication service name. If NULL, no user authentication will be provided.

The "tls_only" argument controls whether the printer application will accept unencrypted connections. In general, this argument should always be false (allow unencrypted connections) since not all clients support encrypted printing.

papplSystemCreatePrinters

Create newly discovered printers.

bool papplSystemCreatePrinters(pappl_system_t *system, pappl_devtype_t types, pappl_pr_create_cb_t cb, void *cb_data);

Parameters

system System
types Device types
cb Callback function
cb_data Callback data

Return Value

true if printers were added, false otherwise

Discussion

This function lists all devices specified by "types" and attempts to add any new printers that are found. The callback function "cb" is invoked for each printer that is added.

papplSystemDelete

Delete a system object.

void papplSystemDelete(pappl_system_t *system);

Parameters

system System object

Discussion

Note: A system object cannot be deleted while the system is running.

papplSystemFindLoc

Find a localization for the given printer and language.

pappl_loc_t *papplSystemFindLoc(pappl_system_t *system, const char *language);

Parameters

system System
language Language

Return Value

Localization or NULL if none

papplSystemFindPrinter

Find a printer by resource, ID, or device URI.

pappl_printer_t *papplSystemFindPrinter(pappl_system_t *system, const char *resource, int printer_id, const char *device_uri);

Parameters

system System
resource Resource path or NULL
printer_id Printer ID or 0
device_uri Device URI or NULL

Return Value

Printer or NULL if none

Discussion

This function finds a printer contained in the system using its resource path, unique integer identifier, or device URI. If none of these is specified, the current default printer is returned.

papplSystemFindSubscription

Find a subscription.

pappl_subscription_t *papplSystemFindSubscription(pappl_system_t *system, int sub_id);

Parameters

system System
sub_id Subscription ID

Return Value

Subscription or NULL if not found.

Discussion

This function finds the numbered event notification subscription on a system.

papplSystemGetAdminGroup

Get the current administrative group, if any.

char *papplSystemGetAdminGroup(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Admin group or NULL if none

Discussion

This function copies the current administrative group, if any, to the specified buffer.

papplSystemGetAuthService

Get the PAM authorization service, if any.

const char *papplSystemGetAuthService(pappl_system_t *system);

Parameters

system System

Return Value

PAM authorization service or NULL if none

Discussion

This function returns the PAM authorization service being used by the system for authentication, if any.

papplSystemGetContact

Get the "system-contact" value.

pappl_contact_t *papplSystemGetContact(pappl_system_t *system, pappl_contact_t *contact);

Parameters

system System
contact Contact

Return Value

Contact

Discussion

This function copies the current system contact information to the specified buffer.

papplSystemGetDNSSDName

Get the current DNS-SD service name.

char *papplSystemGetDNSSDName(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Current DNS-SD service name or NULL for none

Discussion

This function copies the current DNS-SD service name of the system, if any, to the specified buffer.

papplSystemGetDefaultPrintGroup

Get the default print group, if any.

char *papplSystemGetDefaultPrintGroup(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Default print group or NULL if none

Discussion

This function copies the current default print group, if any, to the specified buffer.

papplSystemGetDefaultPrinterID

Get the current "default-printer-id" value.

int papplSystemGetDefaultPrinterID(pappl_system_t *system);

Parameters

system System

Return Value

"default-printer-id" value

Discussion

This function returns the positive integer identifier for the current default printer or 0 if there is no default printer.

papplSystemGetFooterHTML

Get the footer HTML for the web interface, if any.

const char *papplSystemGetFooterHTML(pappl_system_t *system);

Parameters

system System

Return Value

Footer HTML or NULL if none

Discussion

This function returns the HTML for the web page footer, if any. The footer HTML can be set using the papplSystemSetFooterHTML function.

papplSystemGetGeoLocation

Get the system geo-location string, if any.

char *papplSystemGetGeoLocation(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

"geo:" URI or NULL for none

Discussion

This function copies the current system geographic location as a "geo:" URI to the specified buffer.

papplSystemGetHostName

Get the system hostname.

char *papplSystemGetHostName(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Hostname

Discussion

This function copies the current system hostname to the specified buffer.

papplSystemGetHostPort

Get the port number for network connections to the system.

int papplSystemGetHostPort(pappl_system_t *system);

Parameters

system System

Return Value

Port number

Discussion

This function returns the port number that is used for network connections to the system.

papplSystemGetLocation

Get the system location string, if any.

char *papplSystemGetLocation(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Location string or NULL for none

Discussion

This function copies the current human-readable location, if any, to the specified buffer.

papplSystemGetLogLevel

Get the system log level.

pappl_loglevel_t papplSystemGetLogLevel(pappl_system_t *system);

Parameters

system System

Return Value

Log level

Discussion

This function returns the current system log level as an enumeration.

papplSystemGetMaxClients

Get the maximum number of clients.

int papplSystemGetMaxClients(pappl_system_t *system);

Parameters

system System

Return Value

Maximum number of clients

Discussion

This function gets the maximum number of simultaneous clients that are allowed by the system.

papplSystemGetMaxImageSize

Get the maximum supported size for images.

size_t papplSystemGetMaxImageSize(pappl_system_t *system, int *max_width, int *max_height);

Parameters

system System
max_width Maximum width in columns
max_height Maximum height in lines

Return Value

Maximum image size (uncompressed)

Discussion

This function retrieves the image size limits in bytes (uncompressed), columns, and lines.

papplSystemGetMaxLogSize

Get the maximum log file size.

size_t papplSystemGetMaxLogSize(pappl_system_t *system);

Parameters

system System

Return Value

Maximum log file size or 0 for none

Discussion

This function gets the maximum log file size, which is only used when logging directly to a file. When the limit is reached, the current log file is renamed to "filename.O" and a new log file is created. Set the maximum size to 0 to disable log file rotation.

The default maximum log file size is 1MiB or 1048576 bytes.

papplSystemGetMaxSubscriptions

Get the maximum number of event subscriptions.

size_t papplSystemGetMaxSubscriptions(pappl_system_t *system);

Parameters

system System

Return Value

Maximum number of subscriptions or 0

Discussion

This function gets the maximum number of event subscriptions that are allowed. A maximum of 0 means there is no limit.

The default maximum number of event subscriptions is 100.

papplSystemGetName

Get the system name.

char *papplSystemGetName(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Name string

Discussion

This function copies the current system name to the specified buffer.

papplSystemGetNextPrinterID

Get the next "printer-id" value.

int papplSystemGetNextPrinterID(pappl_system_t *system);

Parameters

system System

Return Value

Next "printer-id" value

Discussion

This function returns the positive integer identifier that will be used for the next printer that is created.

papplSystemGetOptions

Get the system options.

pappl_soptions_t papplSystemGetOptions(pappl_system_t *system);

Parameters

system System

Return Value

System options

Discussion

This function returns the system options as a bitfield.

papplSystemGetOrganization

Get the system organization string, if any.

char *papplSystemGetOrganization(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Organization string or NULL for none

Discussion

This function copies the current organization name, if any, to the specified buffer.

papplSystemGetOrganizationalUnit

Get the system organizational unit string, if any.

char *papplSystemGetOrganizationalUnit(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Organizational unit string or NULL for none

Discussion

This function copies the current organizational unit name, if any, to the specified buffer.

papplSystemGetPassword

Get the current web site access password.

char *papplSystemGetPassword(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Password hash

Discussion

This function copies the current web site password hash, if any, to the specified buffer.

Note: The access password is only used when the PAM authentication service is not set.

papplSystemGetServerHeader

Get the Server: header for HTTP responses.

const char *papplSystemGetServerHeader(pappl_system_t *system);

Parameters

system System

Return Value

Server: header string or NULL for none

Discussion

This function returns the value of the HTTP "Server:" header that is used by the system.

papplSystemGetSessionKey

Get the current session key.

char *papplSystemGetSessionKey(pappl_system_t *system, char *buffer, size_t bufsize);

Parameters

system System
buffer String buffer
bufsize Size of string buffer

Return Value

Session key

Discussion

This function copies the current session key to the specified buffer. The session key is used for web interface forms to provide CSRF protection and is refreshed periodically.

papplSystemGetTLSOnly

Get the TLS-only state of the system.

bool papplSystemGetTLSOnly(pappl_system_t *system);

Parameters

system System

Return Value

true if the system is only accepting TLS encrypted connections, false otherwise

Discussion

This function returns whether the system will only accept encrypted connections.

papplSystemGetUUID

Get the "system-uuid" value.

const char *papplSystemGetUUID(pappl_system_t *system);

Parameters

system System

Return Value

"system-uuid" value

Discussion

This function returns the system's UUID value.

papplSystemGetVersions

Get the firmware names and versions.

int papplSystemGetVersions(pappl_system_t *system, int max_versions, pappl_version_t *versions);

Parameters

system System
max_versions Maximum number of versions to return
versions Versions array or NULL for don't care

Return Value

Number of firmware versions

Discussion

This function copies the system firmware information to the specified buffer. The return value is always the number of firmware versions that have been set using the papplSystemSetVersions function, regardless of the value of the "max_versions" argument.

papplSystemHashPassword

Generate a password hash using salt and password strings.

char *papplSystemHashPassword(pappl_system_t *system, const char *salt, const char *password, char *buffer, size_t bufsize);

Parameters

system System
salt Existing password hash or NULL to generate a new hash
password Plain-text password string
buffer String buffer
bufsize Size of string buffer

Return Value

Hashed password

Discussion

This function generates a password hash using the "salt" and "password" strings. The "salt" string should be NULL to generate a new password hash or the value of an existing password hash to verify that a given plaintext "password" string matches the password hash.

Note: Hashed access passwords are only used when the PAM authentication service is not set.

papplSystemIsRunning

Return whether the system is running.

bool papplSystemIsRunning(pappl_system_t *system);

Parameters

system System

Return Value

true if the system is running, false otherwise

Discussion

This function returns whether the system is running.

papplSystemIsShutdown

Return whether the system has been shutdown.

bool papplSystemIsShutdown(pappl_system_t *system);

Parameters

system System

Return Value

true if the system is shutdown, false otherwise

Discussion

This function returns whether the system is shutdown or scheduled to shutdown.

papplSystemIteratePrinters

Iterate all of the printers.

void papplSystemIteratePrinters(pappl_system_t *system, pappl_printer_cb_t cb, void *data);

Parameters

system System
cb Callback function
data Callback data

Discussion

This function iterates each of the printers managed by the system. The "cb" function is called once per printer with the "system" and "data" values.

papplSystemLoadState

Load the previous system state.

bool papplSystemLoadState(pappl_system_t *system, const char *filename);

Parameters

system System
filename File to load

Return Value

true on success, false on failure

Discussion

This function loads the previous system state from a file created by the papplSystemSaveState function. The system state contains all of the system object values, the list of printers, and the jobs for each printer.

When loading a printer definition, if the printer cannot be created (e.g., because the driver name is no longer valid) then that printer and all of its job history will be lost. In the case of a bad driver name, a printer application's driver callback can perform any necessary mapping of the driver name, including the use its auto-add callback to find a compatible new driver.

Note: This function must be called prior to papplSystemRun.

papplSystemMatchDriver

const char *papplSystemMatchDriver(pappl_system_t *system, const char *device_id);

Parameters

system System
device_id IEEE-1284 device ID string

Return Value

Match a driver to an IEEE-1284 device ID.

papplSystemRemoveLink

Remove a link from the navigation header.

void papplSystemRemoveLink(pappl_system_t *system, const char *label);

Parameters

system System
label Label string

Discussion

This function removes the named link for the system.

papplSystemRemoveResource

Remove a resource at the specified path.

void papplSystemRemoveResource(pappl_system_t *system, const char *path);

Parameters

system System object
path Resource path

Discussion

This function removes a resource at the specified path.

papplSystemRemoveTimerCallback

Remove a timer callback.

void papplSystemRemoveTimerCallback(pappl_system_t *system, pappl_timer_cb_t cb, void *cb_data);

Parameters

system System
cb Callback function
cb_data Callback data

Discussion

This function removes all matching timer callbacks from the specified system. Both the callback function and data must match to remove a timer.

papplSystemRun

Run the printer application.

void papplSystemRun(pappl_system_t *system);

Parameters

system System

Discussion

This function runs the printer application, accepting new connections, handling requests, and processing jobs as needed. It returns once the system is shutdown, either through an IPP request or SIGTERM.

papplSystemSaveState

Save the current system state.

bool papplSystemSaveState(pappl_system_t *system, const char *filename);

Parameters

system System
filename File to save

Return Value

true on success, false on failure

Discussion

This function saves the current system state to a file. It is typically used with the papplSystemSetSaveCallback function to periodically save the state:

papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState,
    (void *)filename);

papplSystemSetAdminGroup

Set the administrative group.

void papplSystemSetAdminGroup(pappl_system_t *system, const char *value);

Parameters

system System
value Admin group

Discussion

This function sets the group name used for administrative requests such as adding or deleting a printer.

Note: The administrative group is only used when the PAM authorization service is also set when the system is created.

papplSystemSetAuthCallback

Set an authentication callback for the specified scheme.

void papplSystemSetAuthCallback(pappl_system_t *system, const char *auth_scheme, pappl_auth_cb_t auth_cb, void *auth_cbdata);

Parameters

system System
auth_scheme Authentication scheme
auth_cb Callback function
auth_cbdata Callback data

Discussion

This function sets the authentication callback that is used for Client requests. The authentication callback is used for every Client request containing the WWW-Authenticate header (HTTP_FIELD_WWW_AUTHENTICATE). The callback returns one of the following status codes:

  • HTTP_STATUS_CONTINUE if the authentication succeeded,
  • HTTP_STATUS_UNAUTHORIZED if the authentication failed, or
  • HTTP_STATUS_FORBIDDEN if the authentication succeeded but the user is not part of the specified group.

Note: The authentication callback can only be set prior to calling papplSystemRun.

papplSystemSetContact

Set the "system-contact" value.

void papplSystemSetContact(pappl_system_t *system, pappl_contact_t *contact);

Parameters

system System
contact Contact

Discussion

This function sets the system contact value.

papplSystemSetDNSSDName

Set the DNS-SD service name.

void papplSystemSetDNSSDName(pappl_system_t *system, const char *value);

Parameters

system System
value DNS-SD service name or NULL for none

Discussion

This function sets the DNS-SD service name of the system. If NULL, the DNS-SD registration is removed.

papplSystemSetDefaultPrintGroup

Set the default print group.

void papplSystemSetDefaultPrintGroup(pappl_system_t *system, const char *value);

Parameters

system System
value Default print group or NULL for none

Discussion

This function sets the default group name used for print requests.

Note: The default print group is only used when the PAM authorization service is also set when the system is created.

papplSystemSetDefaultPrinterID

Set the "default-printer-id" value.

void papplSystemSetDefaultPrinterID(pappl_system_t *system, int default_printer_id);

Parameters

system System
default_printer_id "default-printer-id" value

Discussion

This function sets the default printer using its unique positive integer identifier.

papplSystemSetEventCallback

Set a callback for monitoring system events.

void papplSystemSetEventCallback(pappl_system_t *system, pappl_event_cb_t event_cb, void *event_data);

Parameters

system System
event_cb Event callback function
event_data Event callback data

Discussion

This function sets a callback function to receive event notifications from the system.

papplSystemSetFooterHTML

Set the footer HTML for the web interface.

void papplSystemSetFooterHTML(pappl_system_t *system, const char *html);

Parameters

system System
html Footer HTML or NULL for none

Discussion

This function sets the footer HTML for the web interface.

Note: The footer HTML can only be set prior to calling papplSystemRun.

papplSystemSetGeoLocation

Set the geographic location string.

void papplSystemSetGeoLocation(pappl_system_t *system, const char *value);

Parameters

system System
value "geo:" URI or NULL for none

Discussion

This function sets the geographic location of the system as a "geo:" URI. If NULL, the location is cleared.

papplSystemSetHostName

Set the system hostname.

void papplSystemSetHostName(pappl_system_t *system, const char *value);

Parameters

system System
value Hostname or NULL for default

Discussion

This function sets the system hostname. If NULL, the default hostname is used.

papplSystemSetLocation

Set the system location string, if any.

void papplSystemSetLocation(pappl_system_t *system, const char *value);

Parameters

system System
value Location or NULL for none

Discussion

This function sets the human-readable location of the system. If NULL, the location is cleared.

papplSystemSetLogLevel

Set the system log level

void papplSystemSetLogLevel(pappl_system_t *system, pappl_loglevel_t loglevel);

Parameters

system System
loglevel Log Level

Discussion

This function sets the log level as an enumeration.

papplSystemSetMIMECallback

Set the MIME typing callback for the system.

void papplSystemSetMIMECallback(pappl_system_t *system, pappl_mime_cb_t cb, void *data);

Parameters

system System
cb Callback function
data Callback data

Discussion

This function sets a custom MIME typing callback for the system. The MIME typing callback extends the built-in MIME typing support for other media types that are supported by the application, typically vendor print formats.

The callback function receives a buffer containing the initial bytes of the document data, the length of the buffer, and the callback data. It can then return NULL if the content is not recognized or a constant string containing the MIME media type, for example "application/vnd.hp-pcl" for HP PCL print data.

papplSystemSetMaxClients

Set the maximum number of clients.

void papplSystemSetMaxClients(pappl_system_t *system, int max_clients);

Parameters

system System
max_clients Maximum number of clients or 0 for auto

Discussion

This function sets the maximum number of simultaneous clients that are allowed by the system from 0 (auto) to 32768 (half of the available TCP port numbers).

The default maximum number of clients is based on available system resources.

papplSystemSetMaxImageSize

Set the maximum allowed JPEG/PNG image sizes.

void papplSystemSetMaxImageSize(pappl_system_t *system, size_t max_size, int max_width, int max_height);

Parameters

system System
max_size Maximum image size (uncompressed) or 0 for default
max_width Maximum image width in columns or 0 for default
max_height Maximum image height in lines or 0 for default

Discussion

This function sets the maximum size allowed for JPEG and PNG images. The default limits are 16384x16384 and 1/10th the maximum memory the current process can use or 1GiB, whichever is less.

papplSystemSetMaxLogSize

Set the maximum log file size in bytes.

void papplSystemSetMaxLogSize(pappl_system_t *system, size_t maxsize);

Parameters

system System
maxsize Maximum log size in bytes or 0 for none

Discussion

This function sets the maximum log file size in bytes, which is only used when logging directly to a file. When the limit is reached, the current log file is renamed to "filename.O" and a new log file is created. Set the maximum size to 0 to disable log file rotation.

The default maximum log file size is 1MiB or 1048576 bytes.

papplSystemSetMaxSubscriptions

Set the maximum number of event subscriptions.

void papplSystemSetMaxSubscriptions(pappl_system_t *system, size_t max_subscriptions);

Parameters

system System
max_subscriptions Maximum number of subscriptions or 0 for no limit

Discussion

This function Sets the maximum number of event subscriptions that are allowed. A maximum of 0 means there is no limit.

The default maximum number of event subscriptions is 100.

papplSystemSetNetworkCallbacks

Set the network configuration callbacks.

void papplSystemSetNetworkCallbacks(pappl_system_t *system, pappl_network_get_cb_t get_cb, pappl_network_set_cb_t set_cb, void *cb_data);

Parameters

system System
get_cb "Get networks" callback
set_cb "Set networks" callback
cb_data Callback data

Discussion

This function sets the network configuration callbacks for a system. The "get" callback reads the configuration of all network interfaces and stores them in an array of pappl_network_t structures that is passed to the callback. The "set" callback writes the configuration of all network interfaces and returns a boolean value indicating whether the configuration has been written successfully.

papplSystemSetNextPrinterID

Set the next "printer-id" value.

void papplSystemSetNextPrinterID(pappl_system_t *system, int next_printer_id);

Parameters

system System
next_printer_id Next "printer-id" value

Discussion

This function sets the unique positive integer identifier that will be used for the next printer that is created. It is typically only called as part of restoring the state of a system.

Note: The next printer ID can only be set prior to calling papplSystemRun.

papplSystemSetOperationCallback

Set the IPP operation callback.

void papplSystemSetOperationCallback(pappl_system_t *system, pappl_ipp_op_cb_t cb, void *data);

Parameters

system System
cb Callback function
data Callback data

Discussion

This function sets a custom IPP operation handler for the system that is called for any IPP operations that are not handled by the built-in IPP services.

Note: The operation callback can only be set prior to calling papplSystemRun.

papplSystemSetOrganization

Set the system organization string, if any.

void papplSystemSetOrganization(pappl_system_t *system, const char *value);

Parameters

system System
value Organization or NULL for none

Discussion

This function sets the organization name for the system. If NULL, the name is cleared.

papplSystemSetOrganizationalUnit

Set the system organizational unit string, if any.

void papplSystemSetOrganizationalUnit(pappl_system_t *system, const char *value);

Parameters

system System
value Organizational unit or NULL for none

Discussion

This function sets the organizational unit name for the system. If NULL, the name is cleared.

papplSystemSetPassword

Set the access password hash string.

void papplSystemSetPassword(pappl_system_t *system, const char *hash);

Parameters

system System
hash Hash string

Discussion

This function sets the hash for the web access password. The hash string is generated using the papplSystemHashPassword function.

Note: The access password is only used when the PAM authentication service is not set.

papplSystemSetPrinterDrivers

Set the list of drivers and the driver callbacks.

void papplSystemSetPrinterDrivers(pappl_system_t *system, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_create_cb_t create_cb, pappl_pr_driver_cb_t driver_cb, void *data);

Parameters

system System
num_drivers Number of drivers
drivers Drivers
autoadd_cb Auto-add callback function or NULL if none
create_cb Printer creation callback function or NULL if none
driver_cb Driver initialization callback function
data Callback data

Discussion

This function sets the lists of printer drivers, the optional auto-add callback function, the optional creation callback, and the required driver initialization callback function.

The auto-add callback ("autoadd_cb") finds a compatible driver name for the specified printer. It is used when the client or user specifies the "auto" driver name, and for the "autoadd" sub-command for the papplMainloop API.

The creation callback ("create_cb") is called at the end of printer creation to make any common changes or additions to a new printer. It is typically used to add extra web pages, add per-printer static resources, and/or initialize the contact and location information.

The driver initialization callback ("driver_cb") is called to initialize the pappl_pr_driver_data_t structure, which provides all of the printer capabilities and callbacks for printing.

papplSystemSetSaveCallback

Set the save callback.

void papplSystemSetSaveCallback(pappl_system_t *system, pappl_save_cb_t cb, void *data);

Parameters

system System
cb Callback function
data Callback data

Discussion

This function sets a callback that is used to periodically save the current system state. Typically the callback function ("cb") is papplSystemSaveState and the callback data ("data") is the name of the state file:

papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState,
    (void *)filename);

Note: The save callback can only be set prior to calling papplSystemRun.

papplSystemSetUUID

Set the system UUID.

void papplSystemSetUUID(pappl_system_t *system, const char *value);

Parameters

system System
value UUID

Discussion

This function sets the system UUID value, overriding the default (generated) value. It is typically used when restoring the state of a previous incarnation of the system.

Note: The UUID can only be set prior to calling papplSystemRun.

papplSystemSetVersions

Set the firmware names and versions.

void papplSystemSetVersions(pappl_system_t *system, int num_versions, pappl_version_t *versions);

Parameters

system System
num_versions Number of versions
versions Firmware versions

Discussion

This function sets the names and versions of each firmware/software component of the printer application.

papplSystemSetWiFiCallbacks

Set Wi-Fi callbacks.

void papplSystemSetWiFiCallbacks(pappl_system_t *system, pappl_wifi_join_cb_t join_cb, pappl_wifi_list_cb_t list_cb, pappl_wifi_status_cb_t status_cb, void *data);

Parameters

system System
join_cb Join callback
list_cb List callback
status_cb Status callback
data Callback data pointer

Discussion

This function sets the 802.11 Wi-Fi interface callbacks for the system. The "join_cb" is used to join a Wi-Fi network, the "list_cb" is used to list available networks, and the "status_cb" is used to query the current Wi-Fi network connection status and Secure Set Identifier (SSID). The "join_cb" and "status_cb" functions are used to support getting and setting the IPP "printer-wifi-state", "printer-wifi-ssid", and "printer-wifi-password" attributes, while the "list_cb" function enables changing the Wi-Fi network from the network web interface, if enabled.

Note: The Wi-Fi callbacks can only be set prior to calling papplSystemRun.

papplSystemShutdown

Shutdown the system.

void papplSystemShutdown(pappl_system_t *system);

Parameters

system System

Discussion

This function tells the system to perform an orderly shutdown of all printers and to terminate the main loop.

Data Types

pappl_auth_cb_t

Authentication callback

typedef http_status_t (*pappl_auth_cb_t)(pappl_client_t *client, const char *group, gid_t groupid, void *cb_data);

pappl_client_t

Client connection object

typedef struct _pappl_client_s pappl_client_t;

pappl_color_mode_t

Bitfield for IPP "print-color-mode" values

typedef unsigned pappl_color_mode_t;

pappl_contact_t

Contact information

typedef struct pappl_contact_s pappl_contact_t;

pappl_content_t

Bitfield for IPP "print-content-optimize" values

typedef unsigned pappl_content_t;

pappl_default_cb_t

papplIterateDefaults callback

typedef void (*pappl_default_cb_t)(ipp_attribute_t *attr, void *data);

pappl_devclose_cb_t

Device close callback

typedef void (*pappl_devclose_cb_t)(pappl_device_t *device);

pappl_deverror_cb_t

Device error callback

typedef void (*pappl_deverror_cb_t)(const char *message, void *err_data);

pappl_device_cb_t

Device callback - return true to stop, false to continue

typedef bool (*pappl_device_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data);

pappl_device_t

Device connection object

typedef struct _pappl_device_s pappl_device_t;

pappl_devid_cb_t

Device ID callback

typedef char *(*pappl_devid_cb_t)(pappl_device_t *device, char *buffer, size_t bufsize);

pappl_devlist_cb_t

Device list callback

typedef bool (*pappl_devlist_cb_t)(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data);

pappl_devmetrics_t

Device metrics

typedef struct pappl_devmetrics_s pappl_devmetrics_t;

pappl_devopen_cb_t

Device open callback

typedef bool (*pappl_devopen_cb_t)(pappl_device_t *device, const char *device_uri, const char *name);

pappl_devread_cb_t

Device read callback

typedef ssize_t (*pappl_devread_cb_t)(pappl_device_t *device, void *buffer, size_t bytes);

pappl_devstatus_cb_t

Device status callback

typedef pappl_preason_t (*pappl_devstatus_cb_t)(pappl_device_t *device);

pappl_devsupplies_cb_t

Device supplies callback

typedef int (*pappl_devsupplies_cb_t)(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies);

pappl_devtype_t

Device type bitfield

typedef unsigned pappl_devtype_t;

pappl_devwrite_cb_t

Device write callback

typedef ssize_t (*pappl_devwrite_cb_t)(pappl_device_t *device, const void *buffer, size_t bytes);

pappl_dither_t[16][16]

16x16 dither array

typedef unsigned char pappl_dither_t[16][16];

pappl_duplex_t

Duplex printing support

typedef enum pappl_duplex_e pappl_duplex_t;

pappl_event_cb_t

System event callback

typedef void (*pappl_event_cb_t)(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, void *data);

pappl_event_t

Bitfield for IPP "notify-events" attribute

typedef unsigned int pappl_event_t;

pappl_finishings_t

Bitfield for IPP "finishings" values

typedef unsigned pappl_finishings_t;

pappl_icon_t

Printer PNG icon structure

typedef struct pappl_icon_s pappl_icon_t;

pappl_identify_actions_t

Bitfield for IPP "identify-actions" values

typedef unsigned pappl_identify_actions_t;

pappl_ipp_op_cb_t

IPP operation callback function

typedef bool (*pappl_ipp_op_cb_t)(pappl_client_t *client, void *data);

pappl_job_cb_t

papplIterateXxxJobs callback function

typedef void (*pappl_job_cb_t)(pappl_job_t *job, void *data);

pappl_job_t

Job object

typedef struct _pappl_job_s pappl_job_t;

pappl_jreason_t

Bitfield for IPP "job-state-reasons" values

typedef unsigned int pappl_jreason_t;

pappl_kind_t

Bitfield for IPP "printer-kind" values

typedef unsigned pappl_kind_t;

pappl_label_mode_t

Bitfield for IPP "label-mode-xxx" values

typedef unsigned short pappl_label_mode_t;

pappl_loc_t

Localization data

typedef struct _pappl_loc_s pappl_loc_t;

pappl_loglevel_t

Log levels

typedef enum pappl_loglevel_e pappl_loglevel_t;

pappl_loptions_t

Bitfield for link options

typedef unsigned short pappl_loptions_t;

pappl_media_col_t

Media details structure

typedef struct pappl_media_col_s pappl_media_col_t;

pappl_media_tracking_t

Bitfield for IPP "media-tracking" values

typedef unsigned short pappl_media_tracking_t;

pappl_mime_cb_t

MIME typing callback function

typedef const char *(*pappl_mime_cb_t)(const unsigned char *header, size_t headersize, void *data);

pappl_mime_filter_cb_t

Filter callback function

typedef bool (*pappl_mime_filter_cb_t)(pappl_job_t *job, pappl_device_t *device, void *data);

pappl_ml_subcmd_cb_t

Sub-command callback

typedef int (*pappl_ml_subcmd_cb_t)(const char *base_name, int num_options, cups_option_t *options, int num_files, char **files, void *data);

pappl_ml_system_cb_t

System callback

typedef pappl_system_t *(*pappl_ml_system_cb_t)(int num_options, cups_option_t *options, void *data);

pappl_ml_usage_cb_t

Program usage callback

typedef void (*pappl_ml_usage_cb_t)(void *data);

pappl_netconf_t

Network configuration mode

typedef enum pappl_netconf_e pappl_netconf_t;

pappl_network_get_cb_t

Get networks callback

typedef size_t (*pappl_network_get_cb_t)(pappl_system_t *system, void *cb_data, size_t max_networks, pappl_network_t *networks);

pappl_network_set_cb_t

Set networks callback

typedef bool (*pappl_network_set_cb_t)(pappl_system_t *system, void *cb_data, size_t num_networks, pappl_network_t *networks);

pappl_network_t

Network interface information

typedef struct pappl_network_s pappl_network_t;

pappl_pr_autoadd_cb_t

Auto-add callback

typedef const char *(*pappl_pr_autoadd_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data);

pappl_pr_create_cb_t

Printer creation callback

typedef void (*pappl_pr_create_cb_t)(pappl_printer_t *printer, void *data);

pappl_pr_delete_cb_t

Printer deletion callback

typedef void (*pappl_pr_delete_cb_t)(pappl_printer_t *printer, pappl_pr_driver_data_t *data);

pappl_pr_driver_cb_t

Driver callback function

typedef bool (*pappl_pr_driver_cb_t)(pappl_system_t *system, const char *driver_name, const char *device_uri, const char *device_id, pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data);

pappl_pr_driver_data_t

Print driver data

typedef struct pappl_pr_driver_data_s pappl_pr_driver_data_t;

pappl_pr_driver_t

Printer driver information

typedef struct pappl_pr_driver_s pappl_pr_driver_t;

pappl_pr_identify_cb_t

Identify-Printer callback

typedef void (*pappl_pr_identify_cb_t)(pappl_printer_t *printer, pappl_identify_actions_t actions, const char *message);

pappl_pr_options_t

Combined print job options

typedef struct pappl_pr_options_s pappl_pr_options_t;

pappl_pr_printfile_cb_t

Print a "raw" job callback

typedef bool (*pappl_pr_printfile_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device);

pappl_pr_rendjob_cb_t

End a raster job callback

typedef bool (*pappl_pr_rendjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device);

pappl_pr_rendpage_cb_t

End a raster page callback

typedef bool (*pappl_pr_rendpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page);

pappl_pr_rstartjob_cb_t

Start a raster job callback

typedef bool (*pappl_pr_rstartjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device);

pappl_pr_rstartpage_cb_t

Start a raster page callback

typedef bool (*pappl_pr_rstartpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page);

pappl_pr_rwriteline_cb_t

Write a line of raster graphics callback

typedef bool (*pappl_pr_rwriteline_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned y, const unsigned char *line);

pappl_pr_status_cb_t

Update printer status callback

typedef bool (*pappl_pr_status_cb_t)(pappl_printer_t *printer);

pappl_pr_testpage_cb_t

Print a test page callback

typedef const char *(*pappl_pr_testpage_cb_t)(pappl_printer_t *printer, char *buffer, size_t bufsize);

pappl_pr_usb_cb_t

Raw USB IO callback

typedef ssize_t (*pappl_pr_usb_cb_t)(pappl_printer_t *printer, pappl_device_t *device, void *buffer, size_t bufsize, size_t bytes, void *data);

pappl_preason_t

Bitfield for IPP "printer-state-reasons" values

typedef unsigned int pappl_preason_t;

pappl_printer_cb_t

Printer iterator callback function

typedef void (*pappl_printer_cb_t)(pappl_printer_t *printer, void *data);

pappl_printer_t

Printer object

typedef struct _pappl_printer_s pappl_printer_t;

pappl_raster_type_t

Bitfield for IPP "pwg-raster-document-type-supported" values

typedef unsigned pappl_raster_type_t;

pappl_resource_cb_t

Dynamic resource callback function

typedef bool (*pappl_resource_cb_t)(pappl_client_t *client, void *data);

pappl_save_cb_t

Save callback function

typedef bool (*pappl_save_cb_t)(pappl_system_t *system, void *data);

pappl_scaling_t

Bitfield for IPP "print-scaling" values

typedef unsigned pappl_scaling_t;

pappl_sides_t

Bitfield for IPP "sides" values

typedef unsigned pappl_sides_t;

pappl_soptions_t

Bitfield for system options

typedef unsigned pappl_soptions_t;

pappl_subscription_t

Subscription object

typedef struct _pappl_subscription_s pappl_subscription_t;

pappl_supply_color_t

"printer-supply" color values

typedef enum pappl_supply_color_e pappl_supply_color_t;

pappl_supply_t

Supply data

typedef struct pappl_supply_s pappl_supply_t;

pappl_supply_type_t

IPP "printer-supply" type values

typedef enum pappl_supply_type_e pappl_supply_type_t;

pappl_system_t

System object

typedef struct _pappl_system_s pappl_system_t;

pappl_timer_cb_t

Timer callback function

typedef bool (*pappl_timer_cb_t)(pappl_system_t *system, void *cb_data);

pappl_uoptions_t

USB gadget options bitfield

typedef unsigned pappl_uoptions_t;

pappl_version_t

Firmware version information

typedef struct pappl_version_s pappl_version_t;

pappl_wifi_join_cb_t

Wi-Fi join callback

typedef bool (*pappl_wifi_join_cb_t)(pappl_system_t *system, void *data, const char *ssid, const char *psk);

pappl_wifi_list_cb_t

Wi-Fi list callback

typedef int (*pappl_wifi_list_cb_t)(pappl_system_t *system, void *data, cups_dest_t **ssids);

pappl_wifi_state_t

"printer-wifi-state" values

typedef enum pappl_wifi_state_e pappl_wifi_state_t;

pappl_wifi_status_cb_t

Wi-Fi status callback

typedef pappl_wifi_t *(*pappl_wifi_status_cb_t)(pappl_system_t *system, void *data, pappl_wifi_t *wifi_data);

pappl_wifi_t

Wi-Fi status/configuration information

typedef struct pappl_wifi_s pappl_wifi_t;

Structures

pappl_contact_s

Contact information

struct pappl_contact_s {
    char email[256];
    char name[256];
    char telephone[256];
};

Members

email[256] Contact email address
name[256] Contact name
telephone[256] Contact phone number

pappl_devmetrics_s

Device metrics

struct pappl_devmetrics_s {
    size_t read_bytes;
    size_t read_msecs;
    size_t read_requests;
    size_t status_msecs;
    size_t status_requests;
    size_t write_bytes;
    size_t write_msecs;
    size_t write_requests;
};

Members

read_bytes Total number of bytes read
read_msecs Total number of milliseconds spent reading
read_requests Total number of read requests
status_msecs Total number of milliseconds spent getting status
status_requests Total number of status requests
write_bytes Total number of bytes written
write_msecs Total number of milliseconds spent writing
write_requests Total number of write requests

pappl_icon_s

Printer PNG icon structure

struct pappl_icon_s {
    const void *data;
    size_t datalen;
    char filename[256];
};

Members

data PNG icon data, if any
datalen Size of PNG icon data
filename[256] External filename, if any

pappl_media_col_s

Media details structure

struct pappl_media_col_s {
    int bottom_margin;
    int left_margin;
    int left_offset;
    int right_margin;
    int size_length;
    char size_name[64];
    int size_width;
    char source[64];
    int top_margin;
    int top_offset;
    pappl_media_tracking_t tracking;
    char type[64];
};

Members

bottom_margin Bottom margin in hundredths of millimeters
left_margin Left margin in hundredths of millimeters
left_offset Left offset in hundredths of millimeters
right_margin Right margin in hundredths of millimeters
size_length Height in hundredths of millimeters
size_name[64] PWG media size name
size_width Width in hundredths of millimeters
source[64] PWG media source name
top_margin Top margin in hundredths of millimeters
top_offset Top offset in hundredths of millimeters
tracking Media tracking
type[64] PWG media type name

pappl_network_s

Network interface information

struct pappl_network_s {
    http_addr_t addr4;
    http_addr_t addr6;
    pappl_netconf_t config4;
    pappl_netconf_t config6;
    http_addr_t dns[2];
    char domain[64];
    http_addr_t gateway4;
    http_addr_t gateway6;
    char ident[256];
    http_addr_t linkaddr6;
    http_addr_t mask4;
    char name[64];
    unsigned prefix6;
    bool up;
};

Members

addr4 IPv4 address
addr6 IPv6 address
config4 IPv4 configuration mode
config6 IPv6 configuration mode
dns[2] DNS server addresses, if any
domain[64] Domain name, if any
gateway4 IPv4 router/gateway address
gateway6 IPv6 router address
ident[256] Interface identifier
linkaddr6 IPv6 link-local address (read-only)
mask4 IPv4 netmask
name[64] Interface name
prefix6 IPv6 prefix length
up Is this interface up (read-only)?

pappl_pr_driver_data_s

Printer driver data

struct pappl_pr_driver_data_s {
    const char *bin[PAPPL_MAX_BIN];
    int bin_default;
    bool borderless;
    int bottom_top;
    pappl_color_mode_t color_default;
    pappl_color_mode_t color_supported;
    pappl_content_t content_default;
    int darkness_configured;
    int darkness_default;
    int darkness_supported;
    pappl_pr_delete_cb_t delete_cb;
    pappl_duplex_t duplex;
    void *extension;
    const char *features[PAPPL_MAX_VENDOR];
    pappl_finishings_t finishings;
    pappl_raster_type_t force_raster_type;
    const char *format;
    pappl_dither_t gdither;
    bool has_supplies;
    pappl_icon_t icons[3];
    pappl_pr_identify_cb_t identify_cb;
    pappl_identify_actions_t identify_default;
    pappl_identify_actions_t identify_supported;
    bool input_face_up;
    pappl_kind_t kind;
    int left_offset_supported[2];
    int left_right;
    char make_and_model[128];
    const char *media[PAPPL_MAX_MEDIA];
    pappl_media_col_t media_default;
    pappl_media_col_t media_ready[PAPPL_MAX_SOURCE];
    pappl_label_mode_t mode_configured;
    pappl_label_mode_t mode_supported;
    int num_bin;
    int num_features;
    int num_media;
    int num_resolution;
    int num_source;
    int num_type;
    int num_vendor;
    ipp_orient_t orient_default;
    bool output_face_up;
    pappl_dither_t pdither;
    int ppm;
    int ppm_color;
    pappl_pr_printfile_cb_t printfile_cb;
    ipp_quality_t quality_default;
    pappl_raster_type_t raster_types;
    pappl_pr_rendjob_cb_t rendjob_cb;
    pappl_pr_rendpage_cb_t rendpage_cb;
    pappl_pr_rstartjob_cb_t rstartjob_cb;
    pappl_pr_rstartpage_cb_t rstartpage_cb;
    pappl_pr_rwriteline_cb_t rwriteline_cb;
    pappl_scaling_t scaling_default;
    pappl_sides_t sides_default;
    pappl_sides_t sides_supported;
    const char *source[PAPPL_MAX_SOURCE];
    int speed_default;
    int speed_supported[2];
    pappl_pr_status_cb_t status_cb;
    int tear_offset_configured;
    int tear_offset_supported[2];
    pappl_pr_testpage_cb_t testpage_cb;
    int top_offset_supported[2];
    pappl_media_tracking_t tracking_supported;
    const char *type[PAPPL_MAX_TYPE];
    const char *vendor[PAPPL_MAX_VENDOR];
    int x_default;
    int x_resolution[PAPPL_MAX_RESOLUTION];
    int y_default;
    int y_resolution[PAPPL_MAX_RESOLUTION];
};

Members

bin[PAPPL_MAX_BIN] Output bins
bin_default Default output bin
borderless Borderless margins supported?
bottom_top Bottom and top margins in hundredths of millimeters
color_default "print-color-mode-default" value
color_supported "print-color-mode" values
content_default "print-content-default" value
darkness_configured printer-darkness-configured
darkness_default print-darkness-default
darkness_supported printer/print-darkness-supported (0 for none)
delete_cb Printer deletion callback
duplex Duplex printing modes supported
extension Extension data (managed by driver)
features[PAPPL_MAX_VENDOR] "ipp-features-supported" values
finishings "finishings-supported" values
force_raster_type Force a particular raster type?
format Printer-specific format
gdither 'auto', 'text', and 'graphic' dither array
has_supplies Printer has supplies to report
icons[3] "printer-icons" values
identify_cb Identify-Printer callback
identify_default "identify-actions-default" values
identify_supported "identify-actions-supported" values
input_face_up Does input media come in face-up?
kind "printer-kind" values
left_offset_supported[2] media-left-offset-supported (0,0 for none)
left_right Left and right margins in hundredths of millimeters
make_and_model[128] "printer-make-and-model" value
media[PAPPL_MAX_MEDIA] Supported media
media_default Default media
media_ready[PAPPL_MAX_SOURCE] Ready media
mode_configured label-mode-configured
mode_supported label-mode-supported
num_bin Number of output bins
num_features Number of "ipp-features-supported" values
num_media Number of supported media
num_resolution Number of printer resolutions
num_source Number of media sources (trays/rolls)
num_type Number of media types
num_vendor Number of vendor attributes
orient_default "orientation-requested-default" value
output_face_up Does output media come out face-up?
pdither 'photo' dither array
ppm "pages-per-minute" value
ppm_color "pages-per-minute-color" value, if any
printfile_cb Print (raw) file callback
quality_default "print-quality-default" value
raster_types "pwg-raster-document-type-supported" values
rendjob_cb End raster job callback
rendpage_cb End raster page callback
rstartjob_cb Start raster job callback
rstartpage_cb Start raster page callback
rwriteline_cb Write raster line callback
scaling_default "print-scaling-default" value
sides_default "sides-default" value
sides_supported "sides-supported" values
source[PAPPL_MAX_SOURCE] Media sources
speed_default print-speed-default
speed_supported[2] print-speed-supported (0,0 for none)
status_cb Status callback
tear_offset_configured label-tear-offset-configured
tear_offset_supported[2] label-tear-offset-supported (0,0 for none)
testpage_cb Test page callback
top_offset_supported[2] media-top-offset-supported (0,0 for none)
tracking_supported media-tracking-supported
type[PAPPL_MAX_TYPE] Media types
vendor[PAPPL_MAX_VENDOR] Vendor attribute names
x_default Default horizontal resolution
x_resolution[PAPPL_MAX_RESOLUTION] Horizontal printer resolutions
y_default Default vertical resolution
y_resolution[PAPPL_MAX_RESOLUTION] Vertical printer resolutions

pappl_pr_driver_s

Printer driver information

struct pappl_pr_driver_s {
    const char *description;
    const char *device_id;
    void *extension;
    const char *name;
};

Members

description Driver description (usually the make and model)
device_id IEEE-1284 device ID
extension Extension data pointer
name Driver name

pappl_pr_options_s

Combined print job options

struct pappl_pr_options_s {
    int copies;
    int darkness_configured;
    pappl_dither_t dither;
    pappl_finishings_t finishings;
    unsigned first_page;
    cups_page_header_t header;
    unsigned last_page;
    pappl_media_col_t media;
    unsigned num_pages;
    int num_vendor;
    ipp_orient_t orientation_requested;
    char output_bin[64];
    pappl_color_mode_t print_color_mode;
    pappl_content_t print_content_optimize;
    int print_darkness;
    ipp_quality_t print_quality;
    pappl_scaling_t print_scaling;
    int print_speed;
    int printer_resolution[2];
    pappl_sides_t sides;
    cups_option_t *vendor;
};

Members

copies "copies" value
darkness_configured "printer-darkness-configured" value
dither Dither array, if any
finishings "finishings" value(s)
first_page First page in page-ranges, starting at 1
header Raster header
last_page Last page in page-ranges, starting at 1
media "media"/"media-col" value
num_pages Number of pages in job
num_vendor Number of vendor options
orientation_requested "orientation-requested" value
output_bin[64] "output-bin" value
print_color_mode "print-color-mode" value
print_content_optimize "print-content-optimize" value
print_darkness "print-darkness" value
print_quality "print-quality" value
print_scaling "print-scaling" value
print_speed "print-speed" value
printer_resolution[2] "printer-resolution" value in dots per inch
sides "sides" value
vendor Vendor options

pappl_supply_s

Supply data

struct pappl_supply_s {
    pappl_supply_color_t color;
    char description[256];
    bool is_consumed;
    int level;
    pappl_supply_type_t type;
};

Members

color Color, if any
description[256] Description
is_consumed Is this a supply that is consumed?
level Level (0-100, -1 = unknown)
type Type

pappl_version_s

Firmware version information

struct pappl_version_s {
    char name[64];
    char patches[64];
    char sversion[64];
    unsigned short version[4];
};

Members

name[64] "xxx-firmware-name" value
patches[64] "xxx-firmware-patches" value
sversion[64] "xxx-firmware-string-version" value
version[4] "xxx-firmware-version" value

pappl_wifi_s

Wi-Fi status/configuration information

struct pappl_wifi_s {
    char ssid[128];
    pappl_wifi_state_t state;
};

Members

ssid[128] Current "printer-wifi-ssid" value
state Current "printer-wifi-state" value

Constants

pappl_color_mode_e

IPP "print-color-mode" bit values

Constants

PAPPL_COLOR_MODE_AUTO 'auto' - Automatic color/monochrome print mode
PAPPL_COLOR_MODE_AUTO_MONOCHROME 'auto-monochrome' - Automatic monochrome/process monochrome print mode
PAPPL_COLOR_MODE_BI_LEVEL 'bi-level' - B&W (threshold) print mode
PAPPL_COLOR_MODE_COLOR 'color' - Full color print mode
PAPPL_COLOR_MODE_MONOCHROME 'monochrome' - Grayscale print mode using 1 color
PAPPL_COLOR_MODE_PROCESS_MONOCHROME 'process-monochrome' - Grayscale print mode using multiple colors

pappl_content_e

IPP "print-content-optimize" bit values

Constants

PAPPL_CONTENT_AUTO 'auto': Automatically determine content
PAPPL_CONTENT_GRAPHIC 'graphic': Optimize for vector graphics
PAPPL_CONTENT_PHOTO 'photo': Optimize for photos/continuous tone images
PAPPL_CONTENT_TEXT 'text': Optimize for text
PAPPL_CONTENT_TEXT_AND_GRAPHIC 'text-and-graphic': Optimize for text and vector graphics

pappl_devtype_e

Device type bit values

Constants

PAPPL_DEVTYPE_ALL All printers
PAPPL_DEVTYPE_CUSTOM_LOCAL Local printer using a custom interface or protocol
PAPPL_DEVTYPE_CUSTOM_NETWORK Network printer using a custom interface or protocol
PAPPL_DEVTYPE_DNS_SD Network printers discovered via DNS-SD/mDNS
PAPPL_DEVTYPE_FILE Local file/directory
PAPPL_DEVTYPE_LOCAL All local printers
PAPPL_DEVTYPE_NETWORK All network printers
PAPPL_DEVTYPE_SNMP Network printers discovered via SNMP
PAPPL_DEVTYPE_SOCKET Network printers using raw socket
PAPPL_DEVTYPE_USB USB printers

pappl_duplex_e

Duplex printing support

Constants

PAPPL_DUPLEX_FLIPPED Duplex with flipped back sides
PAPPL_DUPLEX_MANUAL_TUMBLE Duplex with back side rotated 180 degrees for short-edge duplex
PAPPL_DUPLEX_NONE No duplex printing support
PAPPL_DUPLEX_NORMAL Duplex with normal back sides
PAPPL_DUPLEX_ROTATED Duplex with back side rotated 180 degrees for long-edge duplex

pappl_event_e

IPP "notify-events" bit values

Constants

PAPPL_EVENT_ALL All events
PAPPL_EVENT_DOCUMENT_ALL All 'document-xxx' events
PAPPL_EVENT_DOCUMENT_COMPLETED 'document-completed'
PAPPL_EVENT_DOCUMENT_CONFIG_CHANGED 'document-config-changed'
PAPPL_EVENT_DOCUMENT_CREATED 'document-created'
PAPPL_EVENT_DOCUMENT_FETCHABLE 'document-fetchable'
PAPPL_EVENT_DOCUMENT_STATE_ALL All 'document-xxx' state events
PAPPL_EVENT_DOCUMENT_STATE_CHANGED 'document-state-changed'
PAPPL_EVENT_DOCUMENT_STOPPED 'document-stopped'
PAPPL_EVENT_JOB_ALL All 'job-xxx' events
PAPPL_EVENT_JOB_COMPLETED 'job-completed'
PAPPL_EVENT_JOB_CONFIG_CHANGED 'job-config-changed'
PAPPL_EVENT_JOB_CREATED 'job-created'
PAPPL_EVENT_JOB_FETCHABLE 'job-fetchable'
PAPPL_EVENT_JOB_PROGRESS 'job-progress'
PAPPL_EVENT_JOB_STATE_ALL All 'job-xxx' state events
PAPPL_EVENT_JOB_STATE_CHANGED 'job-state-changed'
PAPPL_EVENT_JOB_STOPPED 'job-stopped'
PAPPL_EVENT_NONE 'none'
PAPPL_EVENT_PRINTER_ALL All 'printer-xxx' events
PAPPL_EVENT_PRINTER_CONFIG_ALL All 'printer-xxx' configuration events
PAPPL_EVENT_PRINTER_CONFIG_CHANGED 'printer-config-changed'
PAPPL_EVENT_PRINTER_CREATED 'printer-created'
PAPPL_EVENT_PRINTER_DELETED 'printer-deleted'
PAPPL_EVENT_PRINTER_FINISHINGS_CHANGED 'printer-finishings-changed'
PAPPL_EVENT_PRINTER_MEDIA_CHANGED 'printer-media-changed'
PAPPL_EVENT_PRINTER_QUEUE_ORDER_CHANGED 'printer-queue-order-changed'
PAPPL_EVENT_PRINTER_RESTARTED 'printer-restarted'
PAPPL_EVENT_PRINTER_SHUTDOWN 'printer-shutdown'
PAPPL_EVENT_PRINTER_STATE_ALL All 'printer-xxx' state events
PAPPL_EVENT_PRINTER_STATE_CHANGED 'printer-state-changed'
PAPPL_EVENT_PRINTER_STOPPED 'printer-stopped'
PAPPL_EVENT_RESOURCE_CANCELED 'resource-canceled'
PAPPL_EVENT_RESOURCE_CONFIG_CHANGED 'resource-config-changed'
PAPPL_EVENT_RESOURCE_CREATED 'resource-created'
PAPPL_EVENT_RESOURCE_INSTALLED 'resource-installed'
PAPPL_EVENT_RESOURCE_STATE_CHANGED 'resource-state-changed'
PAPPL_EVENT_SYSTEM_CONFIG_CHANGED 'system-config-changed'
PAPPL_EVENT_SYSTEM_STATE_CHANGED 'system-state-changed'
PAPPL_EVENT_SYSTEM_STOPPED 'system-stopped'

pappl_finishings_e

IPP "finishings" bit values

Constants

PAPPL_FINISHINGS_NONE 'none'
PAPPL_FINISHINGS_PUNCH 'punch'
PAPPL_FINISHINGS_STAPLE 'staple'
PAPPL_FINISHINGS_TRIM 'trim'

pappl_identify_actions_e

IPP "identify-actions" bit values

Constants

PAPPL_IDENTIFY_ACTIONS_DISPLAY 'display': Display a message
PAPPL_IDENTIFY_ACTIONS_FLASH 'flash': Flash the display or a light
PAPPL_IDENTIFY_ACTIONS_NONE No actions
PAPPL_IDENTIFY_ACTIONS_SOUND 'sound': Make a sound
PAPPL_IDENTIFY_ACTIONS_SPEAK 'speak': Speak a message

pappl_jreason_e

IPP "job-state-reasons" bit values

Constants

PAPPL_JREASON_ABORTED_BY_SYSTEM 'aborted-by-system'
PAPPL_JREASON_COMPRESSION_ERROR 'compression-error'
PAPPL_JREASON_DOCUMENT_FORMAT_ERROR 'document-format-error'
PAPPL_JREASON_DOCUMENT_PASSWORD_ERROR 'document-password-error'
PAPPL_JREASON_DOCUMENT_PERMISSION_ERROR 'document-permission-error'
PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR 'document-unprintable-error'
PAPPL_JREASON_ERRORS_DETECTED 'errors-detected'
PAPPL_JREASON_JOB_CANCELED_AFTER_TIMEOUT 'job-canceled-after-timeout'
PAPPL_JREASON_JOB_CANCELED_AT_DEVICE 'job-canceled-at-device'
PAPPL_JREASON_JOB_CANCELED_BY_USER 'job-canceled-by-user'
PAPPL_JREASON_JOB_COMPLETED_SUCCESSFULLY 'job-completed-successfully'
PAPPL_JREASON_JOB_COMPLETED_WITH_ERRORS 'job-completed-with-errors'
PAPPL_JREASON_JOB_COMPLETED_WITH_WARNINGS 'job-completed-with-warnings'
PAPPL_JREASON_JOB_DATA_INSUFFICIENT 'job-data-insufficient'
PAPPL_JREASON_JOB_FETCHABLE 'job-fetchable'
PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED 'job-hold-until-specified'
PAPPL_JREASON_JOB_INCOMING 'job-incoming'
PAPPL_JREASON_JOB_PRINTING 'job-printing'
PAPPL_JREASON_JOB_QUEUED 'job-queued'
PAPPL_JREASON_JOB_SPOOLING 'job-spooling'
PAPPL_JREASON_JOB_SUSPENDED_FOR_APPROVAL 'job-suspended-for-approval'
PAPPL_JREASON_NONE 'none'
PAPPL_JREASON_PRINTER_STOPPED 'printer-stopped'
PAPPL_JREASON_PRINTER_STOPPED_PARTLY 'printer-stopped-partly'
PAPPL_JREASON_PROCESSING_TO_STOP_POINT 'processing-to-stop-point'
PAPPL_JREASON_QUEUED_IN_DEVICE 'queued-in-device'
PAPPL_JREASON_WARNINGS_DETECTED 'warnings-detected'

pappl_kind_e

IPP "printer-kind" bit values

Constants

PAPPL_KIND_DISC 'disc'
PAPPL_KIND_DOCUMENT 'document'
PAPPL_KIND_ENVELOPE 'envelope'
PAPPL_KIND_LABEL 'label'
PAPPL_KIND_LARGE_FORMAT 'large-format'
PAPPL_KIND_PHOTO 'photo'
PAPPL_KIND_POSTCARD 'postcard'
PAPPL_KIND_RECEIPT 'receipt'
PAPPL_KIND_ROLL 'roll'

pappl_label_mode_e

IPP "label-mode-xxx" bit values

Constants

PAPPL_LABEL_MODE_APPLICATOR 'applicator'
PAPPL_LABEL_MODE_CUTTER 'cutter'
PAPPL_LABEL_MODE_CUTTER_DELAYED 'cutter-delayed'
PAPPL_LABEL_MODE_KIOSK 'kiosk'
PAPPL_LABEL_MODE_PEEL_OFF 'peel-off'
PAPPL_LABEL_MODE_PEEL_OFF_PREPEEL 'peel-off-prepeel'
PAPPL_LABEL_MODE_REWIND 'rewind'
PAPPL_LABEL_MODE_RFID 'rfid'
PAPPL_LABEL_MODE_TEAR_OFF 'tear-off'

pappl_loglevel_e

Log levels

Constants

PAPPL_LOGLEVEL_DEBUG Debug message
PAPPL_LOGLEVEL_ERROR Error message
PAPPL_LOGLEVEL_FATAL Fatal message
PAPPL_LOGLEVEL_INFO Informational message
PAPPL_LOGLEVEL_UNSPEC Not specified
PAPPL_LOGLEVEL_WARN Warning message

pappl_loptions_e

Link option bits

Constants

PAPPL_LOPTIONS_CONFIGURATION Link shown in configuration section
PAPPL_LOPTIONS_HTTPS_REQUIRED Link requires HTTPS
PAPPL_LOPTIONS_JOB Link shown in job(s) section
PAPPL_LOPTIONS_LOGGING Link shown in logging section
PAPPL_LOPTIONS_NAVIGATION Link shown in navigation bar
PAPPL_LOPTIONS_NETWORK Link shown in network section
PAPPL_LOPTIONS_OTHER Link shown in other section
PAPPL_LOPTIONS_PRINTER Link shown in printer(s) section
PAPPL_LOPTIONS_SECURITY Link shown in security section
PAPPL_LOPTIONS_STATUS Link shown in status section
PAPPL_LOPTIONS_TLS Link shown in TLS section

pappl_media_tracking_e

IPP "media-tracking" bit values

Constants

PAPPL_MEDIA_TRACKING_CONTINUOUS 'continuous'
PAPPL_MEDIA_TRACKING_GAP 'gap'
PAPPL_MEDIA_TRACKING_MARK 'mark'
PAPPL_MEDIA_TRACKING_WEB 'web'

pappl_netconf_e

Network configuration mode

Constants

PAPPL_NETCONF_DHCP Full DHCP
PAPPL_NETCONF_DHCP_MANUAL DHCP with manual IP address
PAPPL_NETCONF_MANUAL Manual IP, netmask, and router
PAPPL_NETCONF_OFF Turn network interface off

pappl_preason_e

IPP "printer-state-reasons" bit values

Constants

PAPPL_PREASON_COVER_OPEN 'cover-open'
PAPPL_PREASON_DEVICE_STATUS Supported papplDeviceGetStatus bits
PAPPL_PREASON_DOOR_OPEN 'door-open'
PAPPL_PREASON_IDENTIFY_PRINTER_REQUESTED 'identify-printer-requested'
PAPPL_PREASON_INPUT_TRAY_MISSING 'input-tray-missing'
PAPPL_PREASON_MARKER_SUPPLY_EMPTY 'marker-supply-empty'
PAPPL_PREASON_MARKER_SUPPLY_LOW 'marker-supply-low'
PAPPL_PREASON_MARKER_WASTE_ALMOST_FULL 'marker-waste-almost-full'
PAPPL_PREASON_MARKER_WASTE_FULL 'marker-waste-full'
PAPPL_PREASON_MEDIA_EMPTY 'media-empty'
PAPPL_PREASON_MEDIA_JAM 'media-jam'
PAPPL_PREASON_MEDIA_LOW 'media-low'
PAPPL_PREASON_MEDIA_NEEDED 'media-needed'
PAPPL_PREASON_NONE 'none'
PAPPL_PREASON_OFFLINE 'offline'
PAPPL_PREASON_OTHER 'other'
PAPPL_PREASON_SPOOL_AREA_FULL 'spool-area-full'
PAPPL_PREASON_TONER_EMPTY 'toner-empty'
PAPPL_PREASON_TONER_LOW 'toner-low'

pappl_raster_type_e

IPP "pwg-raster-document-type-supported" bit values

Constants

PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_16 16-bit per component AdobeRGB
PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8 8-bit per component AdobeRGB
PAPPL_PWG_RASTER_TYPE_BLACK_1 1-bit (device) black
PAPPL_PWG_RASTER_TYPE_BLACK_16 16-bit (device) black
PAPPL_PWG_RASTER_TYPE_BLACK_8 8-bit (device) black
PAPPL_PWG_RASTER_TYPE_CMYK_16 16-bit per component (device) CMYK
PAPPL_PWG_RASTER_TYPE_CMYK_8 8-bit per component (device) CMYK
PAPPL_PWG_RASTER_TYPE_NONE Do not force a particular raster type
PAPPL_PWG_RASTER_TYPE_RGB_16 16-bit per component (device) RGB
PAPPL_PWG_RASTER_TYPE_RGB_8 8-bit per component (device) RGB
PAPPL_PWG_RASTER_TYPE_SGRAY_16 16-bit grayscale with 2.2 gamma
PAPPL_PWG_RASTER_TYPE_SGRAY_8 8-bit grayscale with 2.2 gamma
PAPPL_PWG_RASTER_TYPE_SRGB_16 16-bit per component sRGB
PAPPL_PWG_RASTER_TYPE_SRGB_8 8-bit per component sRGB

pappl_scaling_e

IPP "print-scaling" bit values

Constants

PAPPL_SCALING_AUTO 'auto': Scale to fit (non-borderless) or fill (borderless) if larger, otherwise center
PAPPL_SCALING_AUTO_FIT 'auto-fit': Scale to fit if larger, otherwise center
PAPPL_SCALING_FILL 'fill': Scale to fill the media
PAPPL_SCALING_FIT 'fit': Scale to fit within margins
PAPPL_SCALING_NONE 'none': No scaling (center/crop)

pappl_sides_e

IPP "sides" bit values

Constants

PAPPL_SIDES_ONE_SIDED 'one-sided'
PAPPL_SIDES_TWO_SIDED_LONG_EDGE 'two-sided-long-edge'
PAPPL_SIDES_TWO_SIDED_SHORT_EDGE 'two-sided-short-edge'

pappl_soptions_e

System option bits

Constants

PAPPL_SOPTIONS_DNSSD_HOST Use hostname in DNS-SD service names instead of serial number/UUID
PAPPL_SOPTIONS_MULTI_QUEUE Support multiple printers
PAPPL_SOPTIONS_NONE No options
PAPPL_SOPTIONS_NO_TLS  PAPPL 1.1 Disable TLS support
PAPPL_SOPTIONS_RAW_SOCKET Accept jobs via raw sockets
PAPPL_SOPTIONS_USB_PRINTER Accept jobs via USB for default printer (embedded Linux only)
PAPPL_SOPTIONS_WEB_INTERFACE Enable the standard web pages
PAPPL_SOPTIONS_WEB_LOG Enable the log file page
PAPPL_SOPTIONS_WEB_NETWORK Enable the network settings page
PAPPL_SOPTIONS_WEB_REMOTE Allow remote queue management (vs. localhost only)
PAPPL_SOPTIONS_WEB_SECURITY Enable the user/password settings page
PAPPL_SOPTIONS_WEB_TLS Enable the TLS settings page

pappl_supply_color_e

"printer-supply" color values

Constants

PAPPL_SUPPLY_COLOR_BLACK Black ink/toner (photo or matte)
PAPPL_SUPPLY_COLOR_CYAN Cyan ink/toner
PAPPL_SUPPLY_COLOR_GRAY Gray ink (sometimes marketed as light gray)
PAPPL_SUPPLY_COLOR_GREEN Green ink
PAPPL_SUPPLY_COLOR_LIGHT_CYAN Light cyan ink
PAPPL_SUPPLY_COLOR_LIGHT_GRAY Light gray ink (sometimes marketed as light light gray)
PAPPL_SUPPLY_COLOR_LIGHT_MAGENTA Light magenta ink
PAPPL_SUPPLY_COLOR_MAGENTA Magenta ink/toner
PAPPL_SUPPLY_COLOR_MULTIPLE Multiple-color ink
PAPPL_SUPPLY_COLOR_NO_COLOR No color (waste tank, etc.)
PAPPL_SUPPLY_COLOR_ORANGE Orange ink
PAPPL_SUPPLY_COLOR_VIOLET Violet ink
PAPPL_SUPPLY_COLOR_YELLOW Yellow ink/toner

pappl_supply_type_e

IPP "printer-supply" type values

Constants

PAPPL_SUPPLY_TYPE_BANDING_SUPPLY Banding finisher supplies
PAPPL_SUPPLY_TYPE_BINDING_SUPPLY Binding finisher supplies
PAPPL_SUPPLY_TYPE_CLEANER_UNIT Cleaning unit
PAPPL_SUPPLY_TYPE_CORONA_WIRE Corona wire (laser printers)
PAPPL_SUPPLY_TYPE_COVERS Cover finisher supplies
PAPPL_SUPPLY_TYPE_DEVELOPER Developer supply
PAPPL_SUPPLY_TYPE_FUSER Fuser (laser printers)
PAPPL_SUPPLY_TYPE_FUSER_CLEANING_PAD Fuser cleaning pad (laser printers)
PAPPL_SUPPLY_TYPE_FUSER_OIL Fuser oil supply (laser printers)
PAPPL_SUPPLY_TYPE_FUSER_OILER Fuser oiler (laser printers)
PAPPL_SUPPLY_TYPE_FUSER_OIL_WICK Fuser oil wick (laser printers)
PAPPL_SUPPLY_TYPE_GLUE_WATER_ADDITIVE Glue water additive
PAPPL_SUPPLY_TYPE_INK Ink supply
PAPPL_SUPPLY_TYPE_INK_CARTRIDGE Ink cartridge
PAPPL_SUPPLY_TYPE_INK_RIBBON Ink ribbon supply
PAPPL_SUPPLY_TYPE_INSERTS Insert finisher supplies
PAPPL_SUPPLY_TYPE_OPC Optical photoconductor (laser printers)
PAPPL_SUPPLY_TYPE_OTHER Other supply
PAPPL_SUPPLY_TYPE_PAPER_WRAP Wrap finisher supplies
PAPPL_SUPPLY_TYPE_RIBBON_WAX Wax ribbon supply
PAPPL_SUPPLY_TYPE_SHRINK_WRAP Shrink wrap
PAPPL_SUPPLY_TYPE_SOLID_WAX Solid wax supply
PAPPL_SUPPLY_TYPE_STAPLES Staple finisher supplies
PAPPL_SUPPLY_TYPE_STITCHING_WIRE Staple/stitch finisher supplies
PAPPL_SUPPLY_TYPE_TONER Toner supply
PAPPL_SUPPLY_TYPE_TONER_CARTRIDGE Toner cartridge
PAPPL_SUPPLY_TYPE_TRANSFER_UNIT Transfer unit (laser printers)
PAPPL_SUPPLY_TYPE_UNKNOWN Unknown supply
PAPPL_SUPPLY_TYPE_WASTE_INK Waste ink
PAPPL_SUPPLY_TYPE_WASTE_PAPER Waste paper
PAPPL_SUPPLY_TYPE_WASTE_TONER Waste toner
PAPPL_SUPPLY_TYPE_WASTE_WATER Waste water
PAPPL_SUPPLY_TYPE_WASTE_WAX Waste wax
PAPPL_SUPPLY_TYPE_WATER Water supply

pappl_uoptions_e

USB gadget options

Constants

PAPPL_UOPTIONS_ETHERNET Include USB ethernet gadget
PAPPL_UOPTIONS_NONE No options (just USB printer)
PAPPL_UOPTIONS_SERIAL Include USB serial gadget
PAPPL_UOPTIONS_STORAGE Include USB mass storage gadget
PAPPL_UOPTIONS_STORAGE_READONLY USB mass storage gadget is read-only
PAPPL_UOPTIONS_STORAGE_REMOVABLE USB mass storage gadget is removable

pappl_wifi_state_e

"printer-wifi-state" values

Constants

PAPPL_WIFI_STATE_CANNOT_JOIN 'cannot-join'
PAPPL_WIFI_STATE_JOINING 'joining'
PAPPL_WIFI_STATE_NOT_CONFIGURED 'not-configured'
PAPPL_WIFI_STATE_NOT_VISIBLE 'not-visible'
PAPPL_WIFI_STATE_OFF 'off'
PAPPL_WIFI_STATE_ON 'on'
pappl-1.4.9/install-sh000077500000000000000000000127041476704353100146630ustar00rootroot00000000000000#!/bin/sh # # Install a program, script, or datafile. # # Copyright 2008-2012 by Apple Inc. # # This script is not compatible with BSD (or any other) install program, as it # allows owner and group changes to fail with a warning and makes sure that the # destination directory permissions are as specified - BSD install and the # original X11 install script did not change permissions of existing # directories. It also does not support the transform options since CUPS does # not use them... # # Original script from X11R5 (mit/util/scripts/install.sh) # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # Force umask to 022... umask 022 # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" gzipprog="${GZIPPROG-gzip}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" gzipcp() { # gzipcp from to $gzipprog -9 <"$1" >"$2" } while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue ;; -d) dir_arg=true shift continue ;; -m) chmodcmd="$chmodprog $2" shift shift continue ;; -o) chowncmd="$chownprog $2" shift shift continue ;; -g) chgrpcmd="$chgrpprog $2" shift shift continue ;; -s) stripcmd="$stripprog" shift continue ;; -z) instcmd="gzipcp" shift continue ;; *) if [ x"$src" = x ]; then src="$1" else dst="$1" fi shift continue ;; esac done if [ x"$src" = x ]; then echo "install-sh: No input file specified" exit 1 fi if [ x"$dir_arg" != x ]; then dst="$src" src="" if [ -d "$dst" ]; then instcmd=: else instcmd=$mkdirprog fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ ! -f "$src" -a ! -d "$src" ]; then echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ]; then echo "install: No destination specified" exit 1 fi # If destination is a directory, append the input filename. if [ -d "$dst" ]; then dst="$dst/`basename $src`" fi fi ## this sed command emulates the dirname command dstdir="`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`" # Make sure that the destination directory exists. # This part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ]; then $doit $mkdirprog "${pathcomp}"; fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ]; then # Make a directory... $doit $instcmd $dst || exit 1 # Allow chown/chgrp to fail, but log a warning if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst || echo "warning: Unable to change owner of $dst!"; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst || echo "warning: Unable to change group of $dst!"; fi if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst || exit 1; fi else # Install a file... dstfile="`basename $dst`" # Check the destination file - for libraries just use the "-x" option # to strip... case "$dstfile" in *.a | *.dylib | *.sl | *.sl.* | *.so | *.so.*) stripopt="-x" ;; *) stripopt="" ;; esac # Make a temp file name in the proper directory. dsttmp="$dstdir/#inst.$$#" # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp || exit 1 # Update permissions and strip as needed, then move to the final name. # If the chmod, strip, rm, or mv commands fail, remove the installed # file... if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripopt "$dsttmp" || echo "warning: Unable to strip $dst!"; fi if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp" || echo "warning: Unable to change owner of $dst!"; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp" || echo "warning: Unable to change group of $dst!"; fi trap "rm -f ${dsttmp}" 0 && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; fi && $doit $rmcmd -f "$dstdir/$dstfile" && $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" fi exit 0 pappl-1.4.9/man/000077500000000000000000000000001476704353100134265ustar00rootroot00000000000000pappl-1.4.9/man/Makefile000066400000000000000000000020021476704353100150600ustar00rootroot00000000000000# # Man page makefile for the Printer Application Framework # # Copyright © 2020 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # include ../Makedefs MAN1 = \ pappl.1 \ pappl-makeresheader.1 MAN3 = \ pappl-client.3 \ pappl-device.3 \ pappl-job.3 \ pappl-log.3 \ pappl-mainloop.3 \ pappl-printer.3 \ pappl-resource.3 \ pappl-system.3 # Make everything all: # Clean everything clean: # Clean all non-distribution files distclean: clean # Update dependencies depend: # Install everything install: echo Installing man pages in $(BUILDROOT)/$(mandir)/man1... $(INSTALL) -d -m 755 $(BUILDROOT)/$(mandir)/man1 for file in $(MAN1); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)/$(mandir)/man1; \ done echo Installing man pages in $(BUILDROOT)/$(mandir)/man3... $(INSTALL) -d -m 755 $(BUILDROOT)/$(mandir)/man3 for file in $(MAN3); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)/$(mandir)/man3; \ done # Test everything test: pappl-1.4.9/man/pappl-client-body.man000066400000000000000000000131561476704353100174540ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_client_s .B pappl_client_t; .PP .I char * .br .BI papplClientGetCSRFToken "(pappl_client_t *client, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplClientGetCookie "(pappl_client_t *client, const char *name, char *buffer, size_t bufsize);" .PP .I int .br .BI papplClientGetForm "(pappl_client_t *client, cups_option_t **form);" .PP .I const char * .br .BI papplClientGetHostName "(pappl_client_t *client);" .PP .I int .br .BI papplClientGetHostPort "(pappl_client_t *client);" .PP .I http_t * .br .BI papplClientGetHTTP "(pappl_client_t *client);" .PP .I pappl_job_t * .br .BI papplClientGetJob "(pappl_client_t *client);" .PP .I http_state_t .br .BI papplClientGetMethod "(pappl_client_t *client);" .PP .I ipp_op_t .br .BI papplClientGetOperation "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetOptions "(pappl_client_t *client);" .PP .I pappl_printer_t * .br .BI papplClientGetPrinter "(pappl_client_t *client);" .PP .I ipp_t * .br .BI papplClientGetRequest "(pappl_client_t *client);" .PP .I ipp_t * .br .BI papplClientGetResponse "(pappl_client_t *client);" .PP .I pappl_system_t * .br .BI papplClientGetSystem "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetURI "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetUsername "(pappl_client_t *client);" .PP .I bool .br .BI papplClientHTMLAuthorize "(pappl_client_t *client);" .PP .I void .br .BI papplClientHTMLEscape "(pappl_client_t *client, const char *s, size_t slen);" .PP .I void .br .BI papplClientHTMLFooter "(pappl_client_t *client);" .PP .I void .br .BI papplClientHTMLHeader "(pappl_client_t *client, const char *title, int refresh);" .PP .I void .br .BI papplClientHTMLPrintf "(pappl_client_t *client, const char *format, ...);" .PP .I void .br .BI papplClientHTMLPuts "(pappl_client_t *client, const char *s);" .PP .I void .br .BI papplClientHTMLStartForm "(pappl_client_t *client, const char *action, bool multipart);" .PP .I http_status_t .br .BI papplClientIsAuthorized "(pappl_client_t *client);" .PP .I bool .br .BI papplClientRespond "(pappl_client_t *client, http_status_t code, const char *content_coding, const char *type, time_t last_modified, size_t length);" .PP .I ipp_t * .br .BI papplClientRespondIPP "(pappl_client_t *client, ipp_status_t status, const char *message, ...);" .PP .I bool .br .BI papplClientRespondRedirect "(pappl_client_t *client, http_status_t code, const char *path);" .PP .I void .br .BI papplClientSetCookie "(pappl_client_t *client, const char * name, const char *value, int expires);" .PP .I bool .br .BI papplClientValidateForm "(pappl_client_t *client, int num_form, cups_option_t *form);" .SH DESCRIPTION The .B PAPPL client functions provide access to client connections. Client connections and the life cycle of the .B pappl_client_t objects are managed automatically by the system object for the printer application. .PP The .B papplClientGet functions get the current values for various client-supplied request data. .SH RESPONDING TO CLIENT REQUESTS The .B papplClientRespond function starts a HTTP response to a client request. The .B papplClientHTMLHeader and .B papplClientHTMLFooter functions send standard HTML headers and footers for the printer application's configured web interface while the .B papplClientHTMLEscape, papplClientHTMLPrintf, papplClientHTMLPuts, and .B papplClientHTMLStartForm functions send HTML messages or strings. Use the .B papplClientGetHTTP and (CUPS) .B httpWrite2 functions to send arbitrary data in a client response. Cookies can be included in web browser requests using the .B papplClientSetCookie function. .PP The .B papplClientRespondIPP function starts an IPP response. Use the various CUPS .B ippAdd functions to add attributes to the response message. .PP The .B papplClientRespondRedirect function sends a redirection response to the client. .SH HTML FORMS .B PAPPL provides the .B papplClientGetCSRFToken, papplClientGetForm, papplClientHTMLStartForm and .B papplClientValidateForm functions to securely manage HTML forms. .PP The .B papplClientHTMLStartForm function starts a HTML form and inserts a hidden variable containing a CSRF token that was generated by .B PAPPL from a secure session key that is periodically updated. Upon receipt of a follow-up form submission request, the .B papplClientGetForm and .B papplClientValidateForm functions can be used to securely read the form data (including any file attachments) and validate the hidden CSRF token. .SH AUTHENTICATION AND AUTHORIZATION .B PAPPL supports both user-based authentication using PAM modules and a simple cookie-based password authentication mechanism that is used to limit administrative access through the web interface. .PP The .B papplHTMLAuthorize function authorizes access to the web interface and handles displaying an authentication form on the client's web browser. The return value indicates whether the client is authorized to access the web page. .PP The .B papplIsAuthorized function can be used to determine whether the current client is authorized to perform administrative operations and is normally only used for IPP clients. Local users are always authorized while remote users must provide credentials (typically a username and password) for access. This function will return an HTTP status code that can be provided to the .B httpClientSendResponse function. The value .I HTTP_STATUS_CONTINUE indicates that authorization is granted and the request should continue. The .B papplGetUsername function can be used to obtain the authenticated user identity. pappl-1.4.9/man/pappl-client.3000066400000000000000000000535371476704353100161170ustar00rootroot00000000000000.TH pappl-client 3 "pappl client functions" "2025-03-20" "pappl client functions" .SH NAME pappl-client \- pappl client functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_client_s .B pappl_client_t; .PP .I char * .br .BI papplClientGetCSRFToken "(pappl_client_t *client, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplClientGetCookie "(pappl_client_t *client, const char *name, char *buffer, size_t bufsize);" .PP .I int .br .BI papplClientGetForm "(pappl_client_t *client, cups_option_t **form);" .PP .I const char * .br .BI papplClientGetHostName "(pappl_client_t *client);" .PP .I int .br .BI papplClientGetHostPort "(pappl_client_t *client);" .PP .I http_t * .br .BI papplClientGetHTTP "(pappl_client_t *client);" .PP .I pappl_job_t * .br .BI papplClientGetJob "(pappl_client_t *client);" .PP .I http_state_t .br .BI papplClientGetMethod "(pappl_client_t *client);" .PP .I ipp_op_t .br .BI papplClientGetOperation "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetOptions "(pappl_client_t *client);" .PP .I pappl_printer_t * .br .BI papplClientGetPrinter "(pappl_client_t *client);" .PP .I ipp_t * .br .BI papplClientGetRequest "(pappl_client_t *client);" .PP .I ipp_t * .br .BI papplClientGetResponse "(pappl_client_t *client);" .PP .I pappl_system_t * .br .BI papplClientGetSystem "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetURI "(pappl_client_t *client);" .PP .I const char * .br .BI papplClientGetUsername "(pappl_client_t *client);" .PP .I bool .br .BI papplClientHTMLAuthorize "(pappl_client_t *client);" .PP .I void .br .BI papplClientHTMLEscape "(pappl_client_t *client, const char *s, size_t slen);" .PP .I void .br .BI papplClientHTMLFooter "(pappl_client_t *client);" .PP .I void .br .BI papplClientHTMLHeader "(pappl_client_t *client, const char *title, int refresh);" .PP .I void .br .BI papplClientHTMLPrintf "(pappl_client_t *client, const char *format, ...);" .PP .I void .br .BI papplClientHTMLPuts "(pappl_client_t *client, const char *s);" .PP .I void .br .BI papplClientHTMLStartForm "(pappl_client_t *client, const char *action, bool multipart);" .PP .I http_status_t .br .BI papplClientIsAuthorized "(pappl_client_t *client);" .PP .I bool .br .BI papplClientRespond "(pappl_client_t *client, http_status_t code, const char *content_coding, const char *type, time_t last_modified, size_t length);" .PP .I ipp_t * .br .BI papplClientRespondIPP "(pappl_client_t *client, ipp_status_t status, const char *message, ...);" .PP .I bool .br .BI papplClientRespondRedirect "(pappl_client_t *client, http_status_t code, const char *path);" .PP .I void .br .BI papplClientSetCookie "(pappl_client_t *client, const char * name, const char *value, int expires);" .PP .I bool .br .BI papplClientValidateForm "(pappl_client_t *client, int num_form, cups_option_t *form);" .SH DESCRIPTION The .B PAPPL client functions provide access to client connections. Client connections and the life cycle of the .B pappl_client_t objects are managed automatically by the system object for the printer application. .PP The .B papplClientGet functions get the current values for various client-supplied request data. .SH RESPONDING TO CLIENT REQUESTS The .B papplClientRespond function starts a HTTP response to a client request. The .B papplClientHTMLHeader and .B papplClientHTMLFooter functions send standard HTML headers and footers for the printer application's configured web interface while the .B papplClientHTMLEscape, papplClientHTMLPrintf, papplClientHTMLPuts, and .B papplClientHTMLStartForm functions send HTML messages or strings. Use the .B papplClientGetHTTP and (CUPS) .B httpWrite2 functions to send arbitrary data in a client response. Cookies can be included in web browser requests using the .B papplClientSetCookie function. .PP The .B papplClientRespondIPP function starts an IPP response. Use the various CUPS .B ippAdd functions to add attributes to the response message. .PP The .B papplClientRespondRedirect function sends a redirection response to the client. .SH HTML FORMS .B PAPPL provides the .B papplClientGetCSRFToken, papplClientGetForm, papplClientHTMLStartForm and .B papplClientValidateForm functions to securely manage HTML forms. .PP The .B papplClientHTMLStartForm function starts a HTML form and inserts a hidden variable containing a CSRF token that was generated by .B PAPPL from a secure session key that is periodically updated. Upon receipt of a follow-up form submission request, the .B papplClientGetForm and .B papplClientValidateForm functions can be used to securely read the form data (including any file attachments) and validate the hidden CSRF token. .SH AUTHENTICATION AND AUTHORIZATION .B PAPPL supports both user-based authentication using PAM modules and a simple cookie-based password authentication mechanism that is used to limit administrative access through the web interface. .PP The .B papplHTMLAuthorize function authorizes access to the web interface and handles displaying an authentication form on the client's web browser. The return value indicates whether the client is authorized to access the web page. .PP The .B papplIsAuthorized function can be used to determine whether the current client is authorized to perform administrative operations and is normally only used for IPP clients. Local users are always authorized while remote users must provide credentials (typically a username and password) for access. This function will return an HTTP status code that can be provided to the .B httpClientSendResponse function. The value .I HTTP_STATUS_CONTINUE indicates that authorization is granted and the request should continue. The .B papplGetUsername function can be used to obtain the authenticated user identity. .SH FUNCTIONS .SS papplClientGetCSRFToken Get a unique Cross-Site Request Forgery token string. .PP .nf char * papplClientGetCSRFToken ( pappl_client_t *client, char *buffer, size_t bufsize ); .fi .PP This function generates and returns a unique Cross-Site Request Forgery token string to be used as the value of a hidden variable in all HTML forms sent in the response and then compared when validating the form data in the subsequent request. .PP The value is based on the current system session key and client address in order to make replay attacks infeasible. .PP .IP 5 Note: The \fIpapplClientHTMLStartForm\fR function automatically adds the .IP 5 hidden CSRF variable, and the \fIpapplClientIsValidForm\fR function .IP 5 validates the value. .SS papplClientGetCookie Get a cookie from the client. .PP .nf char * papplClientGetCookie ( pappl_client_t *client, const char *name, char *buffer, size_t bufsize ); .fi .PP This function gets a HTTP "cookie" value from the client request. \fBNULL\fR is returned if no cookie has been set by a prior request, or if the user has disabled or removed the cookie. .PP Use the \fIpapplClientSetCookie\fR function to set a cookie in a response to a request. .PP .IP 5 Note: Cookies set with \fIpapplClientSetCookie\fR will not be available to .IP 5 this function until the following request. .SS papplClientGetForm Get form data from the web client. .PP .nf int papplClientGetForm ( pappl_client_t *client, cups_option_t **form ); .fi .PP For HTTP GET requests, the form data is collected from the request URI. For HTTP POST requests, the form data is read from the client. .PP The returned form values must be freed using the \fBcupsFreeOptions\fR function. .PP .IP 5 Note: Because the form data is read from the client connection, this .IP 5 function can only be called once per request. .SS papplClientGetHTTP Get the HTTP connection associated with a client object. .PP .nf http_t * papplClientGetHTTP ( pappl_client_t *client ); .fi .PP This function returns the HTTP connection associated with the client and is used when sending response data directly to the client using the CUPS \fBhttpXxx\fR functions. .SS papplClientGetHostName Get the hostname from the client-supplied Host: field. .PP .nf const char * papplClientGetHostName ( pappl_client_t *client ); .fi .PP This function returns the hostname that was used in the request and should be used in any URLs or URIs that you generate. .SS papplClientGetHostPort Get the port from the client-supplied Host: field. .PP .nf int papplClientGetHostPort ( pappl_client_t *client ); .fi .PP This function returns the port number that was used in the request and should be used in any URLs or URIs that you generate. .SS papplClientGetJob Get the target job for an IPP request. .PP .nf pappl_job_t * papplClientGetJob ( pappl_client_t *client ); .fi .PP This function returns the job associated with the current IPP request. \fBNULL\fR is returned if the request does not target a job. .SS papplClientGetLoc Get the localization data for a client connection. .PP .nf pappl_loc_t * papplClientGetLoc ( pappl_client_t *client ); .fi .SS papplClientGetLocString Get a localized string for the client. .PP .nf const char * papplClientGetLocString ( pappl_client_t *client, const char *s ); .fi .SS papplClientGetMethod Get the HTTP request method. .PP .nf http_state_t papplClientGetMethod ( pappl_client_t *client ); .fi .PP This function returns the HTTP request method that was used, for example \fBHTTP_STATE_GET\fR for a GET request or \fBHTTP_STATE_POST\fR for a POST request. .SS papplClientGetOperation Get the IPP operation code. .PP .nf ipp_op_t papplClientGetOperation ( pappl_client_t *client ); .fi .PP This function returns the IPP operation code associated with the current IPP request. .SS papplClientGetOptions Get the options from the request URI. .PP .nf const char * papplClientGetOptions ( pappl_client_t *client ); .fi .PP This function returns any options that were passed in the HTTP request URI. The options are the characters after the "?" character, for example a request URI of "/mypage?name=value" will have an options string of "name=value". .PP \fBNULL\fR is returned if the request URI did not contain any options. .PP .IP 5 Note: HTTP GET form variables are normally accessed using the .IP 5 \fIpapplClientGetForm\fR function. This function should only be used when .IP 5 getting non-form data. .SS papplClientGetPrinter Get the target printer for an IPP request. .PP .nf pappl_printer_t * papplClientGetPrinter ( pappl_client_t *client ); .fi .PP This function returns the printer associated with the current IPP request. \fBNULL\fR is returned if the request does not target a printer. .SS papplClientGetRequest Get the IPP request message. .PP .nf ipp_t * papplClientGetRequest ( pappl_client_t *client ); .fi .PP This function returns the attributes in the current IPP request, for use with the CUPS \fBippFindAttribute\fR, \fBippFindNextAttribute\fR, \fBippFirstAttribute\fR, and \fBippNextAttribute\fR functions. .SS papplClientGetResponse Get the IPP response message. .PP .nf ipp_t * papplClientGetResponse ( pappl_client_t *client ); .fi .PP This function returns the attributes in the current IPP response, for use with the CUPS \fBippAddXxx\fR and \fBippSetXxx\fR functions. Use the \fIpapplClientRespondIPP\fR function to set the status code and message, if any. .SS papplClientGetSystem Get the containing system for the client. .PP .nf pappl_system_t * papplClientGetSystem ( pappl_client_t *client ); .fi .PP This function returns the system object that contains the client. .SS papplClientGetURI Get the HTTP request URI. .PP .nf const char * papplClientGetURI ( pappl_client_t *client ); .fi .PP This function returns the URI that was sent in the current HTTP request. .PP .IP 5 Note: Any options in the URI are removed and can be accessed separately .IP 5 using the \fIpapplClientGetOptions\fR function. .SS papplClientGetUsername Get the authenticated username, if any. .PP .nf const char * papplClientGetUsername ( pappl_client_t *client ); .fi .PP This function returns the current authenticated username, if any. .SS papplClientHTMLAuthorize Handle authorization for the web interface. .PP .nf bool papplClientHTMLAuthorize ( pappl_client_t *client ); .fi .PP The web interface supports both authentication against user accounts and authentication using a single administrative access password. This function handles the details of authentication for the web interface based on the system authentication service configuration = the "auth_service" argument to \fIpapplSystemCreate\fR and any callback set using \fIpapplSystemSetAuthCallback\fR. .PP .IP 5 Note: IPP operation callbacks needing to perform authorization should use .IP 5 the \fIpapplClientIsAuthorized\fR function instead. .SS papplClientHTMLEscape Send a string to a web browser client. .PP .nf void papplClientHTMLEscape ( pappl_client_t *client, const char *s, size_t slen ); .fi .PP This function sends the specified string to the web browser client and escapes special characters as HTML entities as needed, for example "&" is sent as \fB&\fR. .SS papplClientHTMLFooter Show the web interface footer. .PP .nf void papplClientHTMLFooter ( pappl_client_t *client ); .fi .PP This function sends the standard web interface footer followed by a trailing 0-length chunk to finish the current HTTP response. Use the \fIpapplSystemSetFooterHTML\fR function to add any custom HTML needed in the footer. .SS papplClientHTMLHeader Show the web interface header and title. .PP .nf void papplClientHTMLHeader ( pappl_client_t *client, const char *title, int refresh ); .fi .PP This function sends the standard web interface header and title. If the "refresh" argument is greater than zero, the page will automatically reload after that many seconds. .PP Use the \fIpapplSystemAddLink\fR function to add system-wide navigation links to the header. Similarly, use \fIpapplPrinterAddLink\fR to add printer-specific links, which will appear in the web interface printer if the system is not configured to support multiple printers (the \fBPAPPL_SOPTIONS_MULTI_QUEUE\fR option to \fIpapplSystemCreate\fR). .SS papplClientHTMLPrinterFooter Show the web interface footer for printers. .PP .nf void papplClientHTMLPrinterFooter ( pappl_client_t *client ); .fi .PP This function sends the standard web interface footer for a printer followed by a trailing 0-length chunk to finish the current HTTP response. Use the \fIpapplSystemSetFooterHTML\fR function to add any custom HTML needed in the footer. .SS papplClientHTMLPrinterHeader Show the web interface header and title for printers. .PP .nf void papplClientHTMLPrinterHeader ( pappl_client_t *client, pappl_printer_t *printer, const char *title, int refresh, const char *label, const char *path_or_url ); .fi .PP This function sends the standard web interface header and title for a printer. If the "refresh" argument is greater than zero, the page will automatically reload after that many seconds. .PP If "label" and "path_or_url" are non-\fBNULL\fR strings, an additional navigation link is included with the title header - this is typically used for an action button ("Change"). .PP Use the \fIpapplSystemAddLink\fR function to add system-wide navigation links to the header. Similarly, use \fIpapplPrinterAddLink\fR to add printer-specific links, which will appear in the web interface printer if the system is not configured to support multiple printers (the \fBPAPPL_SOPTIONS_MULTI_QUEUE\fR option to \fIpapplSystemCreate\fR). .SS papplClientHTMLPrintf Send formatted text to the web browser client, escaping as needed. .PP .nf void papplClientHTMLPrintf ( pappl_client_t *client, const char *format, ... ); .fi .PP This function sends formatted text to the web browser client using \fBprintf\fR-style formatting codes. The format string itself is not escaped to allow for embedded HTML, however strings inserted using the '%c' or \fB%s\fR codes are escaped properly for HTML - "&" is sent as \fB&\fR, etc. .SS papplClientHTMLPuts Send a HTML string to the web browser client. .PP .nf void papplClientHTMLPuts ( pappl_client_t *client, const char *s ); .fi .PP This function sends a HTML string to the client without performing any escaping of special characters. .SS papplClientHTMLStartForm Start a HTML form. .PP .nf void papplClientHTMLStartForm ( pappl_client_t *client, const char *action, bool multipart ); .fi .PP This function starts a HTML form with the specified "action" path and includes the CSRF token as a hidden variable. If the "multipart" argument is \fBtrue\fR, the form is annotated to support file attachments up to 2MiB in size. .SS papplClientIsAuthorized Determine whether a client is authorized for administrative requests. .PP .nf http_status_t papplClientIsAuthorized ( pappl_client_t *client ); .fi .PP This function determines whether a client is authorized to submit an administrative request. .PP The return value is \fBHTTP_STATUS_CONTINUE\fR if access is authorized, \fBHTTP_STATUS_FORBIDDEN\fR if access is not allowed, \fBHTTP_STATUS_UNAUTHORIZED\fR if authorization is required, or \fBHTTP_STATUS_UPGRADE_REQUIRED\fR if the connection needs to be encrypted. All of these values can be passed to the \fIpapplClientRespond\fR function. .SS papplClientIsEncrypted Return whether a Client connection is encrypted. .PP .nf bool papplClientIsEncrypted ( pappl_client_t *client ); .fi .PP This function returns a boolean value indicating whether a Client connection is encrypted with TLS. .SS papplClientIsValidForm Validate HTML form variables. .PP .nf bool papplClientIsValidForm ( pappl_client_t *client, int num_form, cups_option_t *form ); .fi .PP This function validates the contents of a HTML form using the CSRF token included as a hidden variable. When sending a HTML form you should use the \fIpapplClientStartForm\fR function to start the HTML form and insert the CSRF token for later validation. .PP .IP 5 Note: Callers are expected to validate all other form variables. .SS papplClientRespond Send a regular HTTP response. .PP .nf bool papplClientRespond ( pappl_client_t *client, http_status_t code, const char *content_encoding, const char *type, time_t last_modified, size_t length ); .fi .PP This function sends all of the required HTTP fields and includes standard messages for errors. The following values for "code" are explicitly supported: .PP .IP \(bu 5 \fBHTTP_STATUS_OK\fR: The request is successful. .IP \(bu 5 \fBHTTP_STATUS_BAD_REQUEST\fR: The client submitted a bad request. .IP \(bu 5 \fBHTTP_STATUS_CONTINUE\fR: An authentication challenge is not needed. .IP \(bu 5 \fBHTTP_STATUS_FORBIDDEN\fR: Authenticated but not allowed. .IP \(bu 5 \fBHTTP_STATUS_METHOD_NOT_ALLOWED\fR: The HTTP method is not supported for the given URI. .IP \(bu 5 \fBHTTP_STATUS_UNAUTHORIZED\fR: Not authenticated. .IP \(bu 5 \fBHTTP_STATUS_UPGRADE_REQUIRED\fR: Redirects the client to a secure page. .PP Use the \fIpapplClientRespondRedirect\fR when you need to redirect the client to another page. .SS papplClientRespondIPP Send an IPP response. .PP .nf ipp_t * papplClientRespondIPP ( pappl_client_t *client, ipp_status_t status, const char *message, ... ); .fi .PP This function sets the return status for an IPP request and returns the current IPP response message. The "status" and "message" arguments replace any existing status-code and "status-message" attribute value that may be already present in the response. .PP .IP 5 Note: You should call this function prior to adding any response .IP 5 attributes. .SS papplClientRespondIPPUnsupported Respond with an unsupported IPP attribute. .PP .nf void papplClientRespondIPPUnsupported ( pappl_client_t *client, ipp_attribute_t *attr ); .fi .PP This function returns a 'client-error-attributes-or-values-not-supported' status code and adds the specified attribute to the unsupported attributes group in the response. .SS papplClientRespondRedirect Respond with a redirect to another page. .PP .nf bool papplClientRespondRedirect ( pappl_client_t *client, http_status_t code, const char *path ); .fi .PP This function sends a HTTP response that redirects the client to another page or URL. The most common "code" value to return is \fBHTTP_STATUS_FOUND\fR. .SS papplClientSetCookie Set a cookie for the web browser client. .PP .nf void papplClientSetCookie ( pappl_client_t *client, const char *name, const char *value, int expires ); .fi .PP This function sets the value of a cookie for the client by updating the \fBSet-Cookie\fR header in the HTTP response that will be sent. The "name" and "value" strings must contain only valid characters for a cookie and its value as documented in RFC 6265, which basically means letters, numbers, "@", "-", ".", and "_". .PP The "expires" argument specifies how long the cookie will remain active in seconds, for example \fB3600\fR seconds is one hour and \fB86400\fR seconds is one day. If the value is zero or less, a "session" cookie is created instead which will expire as soon as the web browser is closed. .SS papplClientSetUsername Set the authenticated username, if any. .PP .nf void papplClientSetUsername ( pappl_client_t *client, const char *username ); .fi .PP This function sets the current authenticated username, if any. .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-device-body.man000066400000000000000000000056171476704353100174400ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_device_s .B pappl_device_t; .PP .I void .br .BI papplDeviceAddScheme "(const char *scheme, pappl_dtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb);" .PP .I void .br .BI papplDeviceClose "(pappl_device_t *device);" .PP .I void .br .BI papplDeviceError "(pappl_device_t *device, const char *message, ...);" .PP .I void .br .BI papplDeviceFlush "(pappl_device_t *device);" .PP .I void * .br .BI papplDeviceGetData "(pappl_device_t *device);" .PP .I pappl_dmetrics_t * .br .BI papplDeviceGetMetrics "(pappl_device_t *device, pappl_dmetrics_t *metrics);" .PP .I pappl_preason_t .br .BI papplDeviceGetStatus "(pappl_device_t *device);" .PP .I bool .br .BI papplDeviceList "(pappl_dtype_t types, pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data);" .PP .I pappl_device_t * .br .BI papplDeviceOpen "(const char *device_uri, const char *name, pappl_deverror_cb_t err_cb, void *err_data);" .PP .I int .br .BI papplDeviceParse1284ID "(const char *device_id, cups_option_t **pairs);" .PP .I ssize_t .br .BI papplDevicePrintf "(pappl_device_t *device, const char *format, ...);" .PP .I ssize_t .br .BI papplDevicePuts "(pappl_device_t *device, const char *s);" .PP .I ssize_t .br .BI papplDeviceRead "(pappl_device_t *device, void *buffer, size_t bytes);" .PP .I void .br .BI papplDeviceSetData "(pappl_device_t *device, void *data);" .PP .I ssize_t .br .BI papplDeviceWrite "(pappl_device_t *device, const void *buffer, size_t bytes);" .SH DESCRIPTION The .B PAPPL device functions provide access to output device connections and to list available output devices. Output devices are accessed using Uniform Resource Identifier (URI) strings such as "file:///path/to/file-or-directory", "socket://11.22.33.44", and "usb://make/model?serial=number". .PP The .B papplDeviceList function lists available output devices, providing each available output device to the supplied callback function. The list only contains devices whose URI scheme supports discovery, at present USB printers and network printers that advertise themselves using DNS-SD/mDNS and/or SNMPv1. .PP The .B papplDeviceOpen function opens a connection to an output device using its URI. The .B papplDeviceClose function closes the connection. .PP The .B papplDevicePrintf, papplDevicePuts, and .B papplDeviceWrite functions send data to the device, while the .B papplDeviceRead function reads data from the device. .PP The .B papplDeviceGetMetrics function gets statistical information about all communications with the device while it has been open, while the .B papplDeviceGetStatus function gets the hardware status of a device and maps it to the .B pappl_preason_t bitfield. pappl-1.4.9/man/pappl-device.3000066400000000000000000000454521476704353100160750ustar00rootroot00000000000000.TH pappl-device 3 "pappl device functions" "2025-03-20" "pappl device functions" .SH NAME pappl-device \- pappl device functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_device_s .B pappl_device_t; .PP .I void .br .BI papplDeviceAddScheme "(const char *scheme, pappl_dtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb);" .PP .I void .br .BI papplDeviceClose "(pappl_device_t *device);" .PP .I void .br .BI papplDeviceError "(pappl_device_t *device, const char *message, ...);" .PP .I void .br .BI papplDeviceFlush "(pappl_device_t *device);" .PP .I void * .br .BI papplDeviceGetData "(pappl_device_t *device);" .PP .I pappl_dmetrics_t * .br .BI papplDeviceGetMetrics "(pappl_device_t *device, pappl_dmetrics_t *metrics);" .PP .I pappl_preason_t .br .BI papplDeviceGetStatus "(pappl_device_t *device);" .PP .I bool .br .BI papplDeviceList "(pappl_dtype_t types, pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data);" .PP .I pappl_device_t * .br .BI papplDeviceOpen "(const char *device_uri, const char *name, pappl_deverror_cb_t err_cb, void *err_data);" .PP .I int .br .BI papplDeviceParse1284ID "(const char *device_id, cups_option_t **pairs);" .PP .I ssize_t .br .BI papplDevicePrintf "(pappl_device_t *device, const char *format, ...);" .PP .I ssize_t .br .BI papplDevicePuts "(pappl_device_t *device, const char *s);" .PP .I ssize_t .br .BI papplDeviceRead "(pappl_device_t *device, void *buffer, size_t bytes);" .PP .I void .br .BI papplDeviceSetData "(pappl_device_t *device, void *data);" .PP .I ssize_t .br .BI papplDeviceWrite "(pappl_device_t *device, const void *buffer, size_t bytes);" .SH DESCRIPTION The .B PAPPL device functions provide access to output device connections and to list available output devices. Output devices are accessed using Uniform Resource Identifier (URI) strings such as "file:///path/to/file-or-directory", "socket://11.22.33.44", and "usb://make/model?serial=number". .PP The .B papplDeviceList function lists available output devices, providing each available output device to the supplied callback function. The list only contains devices whose URI scheme supports discovery, at present USB printers and network printers that advertise themselves using DNS-SD/mDNS and/or SNMPv1. .PP The .B papplDeviceOpen function opens a connection to an output device using its URI. The .B papplDeviceClose function closes the connection. .PP The .B papplDevicePrintf, papplDevicePuts, and .B papplDeviceWrite functions send data to the device, while the .B papplDeviceRead function reads data from the device. .PP The .B papplDeviceGetMetrics function gets statistical information about all communications with the device while it has been open, while the .B papplDeviceGetStatus function gets the hardware status of a device and maps it to the .B pappl_preason_t bitfield. .SH ENUMERATIONS .SS pappl_devtype_e Device type bit values .TP 5 PAPPL_DEVTYPE_ALL .br All printers .TP 5 PAPPL_DEVTYPE_CUSTOM_LOCAL .br Local printer using a custom interface or protocol .TP 5 PAPPL_DEVTYPE_CUSTOM_NETWORK .br Network printer using a custom interface or protocol .TP 5 PAPPL_DEVTYPE_DNS_SD .br Network printers discovered via DNS-SD/mDNS .TP 5 PAPPL_DEVTYPE_FILE .br Local file/directory .TP 5 PAPPL_DEVTYPE_LOCAL .br All local printers .TP 5 PAPPL_DEVTYPE_NETWORK .br All network printers .TP 5 PAPPL_DEVTYPE_SNMP .br Network printers discovered via SNMP .TP 5 PAPPL_DEVTYPE_SOCKET .br Network printers using raw socket .TP 5 PAPPL_DEVTYPE_USB .br USB printers .SH FUNCTIONS .SS papplDeviceAddScheme Add a device URI scheme. .PP .nf void papplDeviceAddScheme ( const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devid_cb_t id_cb ); .fi .PP This function registers a device URI scheme with PAPPL, so that devices using the named scheme can receive print data, report status information, and so forth. PAPPL includes support for the following URI schemes: .PP .IP \(bu 5 \fBdnssd\fR: Network printers discovered using DNS-SD. .IP \(bu 5 \fBfile\fR: Character device files, plain files, and directories. .IP \(bu 5 \fBsnmp\fR: Network printers discovered using SNMPv1. .IP \(bu 5 \fBsocket\fR: Network printers using a hostname or numeric IP address. .IP \(bu 5 \fBusb\fR: Class 1 (unidirectional) or 2 (bidirectional) USB printers. .PP The "scheme" parameter specifies the URI scheme and must consist of lowercase letters, digits, "-", "_", and/or ".", for example "x-foo" or "com.example.bar". .PP The "dtype" parameter specifies the device type and should be \fBPAPPL_DTYPE_CUSTOM_LOCAL\fR for locally connected printers and \fBPAPPL_DTYPE_CUSTOM_NETWORK\fR for network printers. .PP Each of the callbacks corresponds to one of the \fBpapplDevice\fR functions: .PP .IP \(bu 5 "list_cb": Implements discovery of devices (optional) .IP \(bu 5 "open_cb": Opens communication with a device and allocates any device- specific data as needed .IP \(bu 5 "close_cb": Closes communication with a device and frees any device- specific data as needed .IP \(bu 5 "read_cb": Reads data from a device .IP \(bu 5 "write_cb": Write data to a device .IP \(bu 5 "status_cb": Gets basic printer state information from a device (optional) .IP \(bu 5 "id_cb": Gets the current IEEE-1284 device ID from a device (optional) .PP The "open_cb" callback typically calls \fIpapplDeviceSetData\fR to store a pointer to contextual information for the connection while the "close_cb", "id_cb", "read_cb", "write_cb", and "status_cb" callbacks typically call \fIpapplDeviceGetData\fR to retrieve it. .SS papplDeviceAddScheme2 Add a device URI scheme with supply-level queries. .PP .nf void papplDeviceAddScheme2 ( const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devsupplies_cb_t supplies_cb, pappl_devid_cb_t id_cb ); .fi .PP This function registers a device URI scheme with PAPPL, so that devices using the named scheme can receive print data, report status information, and so forth. PAPPL includes support for the following URI schemes: .PP .IP \(bu 5 \fBdnssd\fR: Network printers discovered using DNS-SD. .IP \(bu 5 \fBfile\fR: Character device files, plain files, and directories. .IP \(bu 5 \fBsnmp\fR: Network printers discovered using SNMPv1. .IP \(bu 5 \fBsocket\fR: Network printers using a hostname or numeric IP address. .IP \(bu 5 \fBusb\fR: Class 1 (unidirectional) or 2 (bidirectional) USB printers. .PP The "scheme" parameter specifies the URI scheme and must consist of lowercase letters, digits, "-", "_", and/or ".", for example "x-foo" or "com.example.bar". .PP The "dtype" parameter specifies the device type and should be \fBPAPPL_DTYPE_CUSTOM_LOCAL\fR for locally connected printers and \fBPAPPL_DTYPE_CUSTOM_NETWORK\fR for network printers. .PP Each of the callbacks corresponds to one of the \fBpapplDevice\fR functions: .PP .IP \(bu 5 "list_cb": Implements discovery of devices (optional) .IP \(bu 5 "open_cb": Opens communication with a device and allocates any device- specific data as needed .IP \(bu 5 "close_cb": Closes communication with a device and frees any device- specific data as needed .IP \(bu 5 "read_cb": Reads data from a device .IP \(bu 5 "write_cb": Write data to a device .IP \(bu 5 "status_cb": Gets basic printer state information from a device (optional) .IP \(bu 5 "supplies_cb": Gets supply level information from a device (optional) .IP \(bu 5 "id_cb": Gets the current IEEE-1284 device ID from a device (optional) .PP The "open_cb" callback typically calls \fIpapplDeviceSetData\fR to store a pointer to contextual information for the connection while the "close_cb", "id_cb", "read_cb", "write_cb", "status_cb", and "supplies_cb" callbacks typically call \fIpapplDeviceGetData\fR to retrieve it. .SS papplDeviceClose Close a device connection. .PP .nf void papplDeviceClose ( pappl_device_t *device ); .fi .PP This function flushes any pending write data and closes the connection to a device. .SS papplDeviceError Report an error on a device. .PP .nf void papplDeviceError ( pappl_device_t *device, const char *message, ... ); .fi .PP This function reports an error on a device using the client-supplied callback function. It is normally called from any custom device URI scheme callbacks you implement. .SS papplDeviceFlush Flush any buffered data to the device. .PP .nf void papplDeviceFlush ( pappl_device_t *device ); .fi .PP This function flushes any pending write data sent using the \fIpapplDevicePrintf\fR, \fIpapplDevicePuts\fR, or \fIpapplDeviceWrite\fR functions to the device. .SS papplDeviceGetData Get device-specific data. .PP .nf void * papplDeviceGetData ( pappl_device_t *device ); .fi .PP This function returns any device-specific data that has been set by the device open callback. It is normally only called from any custom device URI scheme callbacks you implement. .SS papplDeviceGetID Get the IEEE-1284 device ID. .PP .nf char * papplDeviceGetID ( pappl_device_t *device, char *buffer, size_t bufsize ); .fi .PP This function queries the IEEE-1284 device ID from the device and copies it to the provided buffer. The buffer must be at least 64 bytes and should be at least 1024 bytes in length. .PP .IP 5 \fINote:\fR This function can block for up to several seconds depending on .IP 5 the type of connection. .SS papplDeviceGetMetrics Get the device metrics. .PP .nf pappl_devmetrics_t * papplDeviceGetMetrics ( pappl_device_t *device, pappl_devmetrics_t *metrics ); .fi .PP This function returns a copy of the device metrics data, which includes the number, length (in bytes), and duration (in milliseconds) of read, status, and write requests for the current session. This information is normally used for performance measurement and optimization during development of a printer application. It can also be useful diagnostic information. .SS papplDeviceGetStatus Get the printer status bits. .PP .nf pappl_preason_t papplDeviceGetStatus ( pappl_device_t *device ); .fi .PP This function returns the current printer status bits, as applicable to the current device. .PP The status bits for USB devices come from the original Centronics parallel printer "standard" which was later formally standardized in IEEE 1284-1984 and the USB Device Class Definition for Printing Devices. Some vendor extensions are also supported. .PP The status bits for network devices come from the hrPrinterDetectedErrorState property that is defined in the SNMP Printer MIB v2 (RFC 3805). .PP This function returns a \fIpappl_preason_t\fR bitfield which can be passed to the \fIpapplPrinterSetReasons\fR function. Use the \fIPAPPL_PREASON_DEVICE_STATUS\fR value as the value of the "remove" argument. .PP .IP 5 Note: This function can block for several seconds while getting the status .IP 5 information. .SS papplDeviceGetSupplies Get the current printer supplies. .PP .nf int papplDeviceGetSupplies ( pappl_device_t *device, int max_supplies, pappl_supply_t *supplies ); .fi .PP This function returns the number, type, and level of current printer supply levels, as applicable to the current device. .PP The supply levels for network devices come from the prtSupplyTable and prtMarkerColorantTable properties that are defined in the SNMP Printer MIB v2 (RFC 3805). .PP The supply levels for other devices are not standardized and must be queried using other methods. .PP .IP 5 Note: This function can block for several seconds while getting the supply .IP 5 information. .SS papplDeviceIsSupported Determine whether a given URI is supported. .PP .nf bool papplDeviceIsSupported ( const char *uri ); .fi .PP This function determines whether a given URI or URI scheme is supported as a device. .SS papplDeviceList List available devices. .PP .nf bool papplDeviceList ( pappl_devtype_t types, pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data ); .fi .PP This function lists the available devices, calling the "cb" function once per device that is discovered/listed. The callback function receives the device URI, IEEE-1284 device ID (if any), and "data" pointer, and returns \fBtrue\fR to stop listing devices and \fBfalse\fR to continue. .PP The "types" argument determines which devices are listed, for example \fBPAPPL_DEVTYPE_ALL\fR will list all types of devices while \fBPAPPL_DEVTYPE_USB\fR only lists USB printers. .PP Any errors are reported using the supplied "err_cb" function. If you specify \fBNULL\fR for this argument, errors are sent to \fBstderr\fR. .PP .IP 5 Note: This function will block (not return) until each of the device URI .IP 5 schemes has reported all of the devices \fIor\fR the supplied callback function .IP 5 returns \fBtrue\fR. .SS papplDeviceOpen Open a connection to a device. .PP .nf pappl_device_t * papplDeviceOpen ( const char *device_uri, const char *name, pappl_deverror_cb_t err_cb, void *err_data ); .fi .PP This function opens a connection to the specified device URI. The "name" argument provides textual context for the connection and is usually the name (title) of the print job. .PP Any errors are reported using the supplied "err_cb" function. If you specify \fBNULL\fR for this argument, errors are sent to \fBstderr\fR. .SS papplDeviceParseID Parse an IEEE-1284 device ID string. .PP .nf int papplDeviceParseID ( const char *device_id, cups_option_t **pairs ); .fi .PP This function parses an IEEE-1284 device ID string and returns an array of key/value pairs as a \fBcups_option_t\fR array. The returned array must be freed using the \fBcupsFreeOptions\fR function. .SS papplDevicePrintf Write a formatted string. .PP .nf ssize_t papplDevicePrintf ( pappl_device_t *device, const char *format, ... ); .fi .PP This function buffers a formatted string that will be sent to the device. The "format" argument accepts all \fBprintf\fR format specifiers and behaves identically to that function. .PP Call the \fIpapplDeviceFlush\fR function to ensure that the formatted string is immediately sent to the device. .SS papplDevicePuts Write a literal string. .PP .nf ssize_t papplDevicePuts ( pappl_device_t *device, const char *s ); .fi .PP This function buffers a literal string that will be sent to the device. Call the \fIpapplDeviceFlush\fR function to ensure that the literal string is immediately sent to the device. .SS papplDeviceRead Read from a device. .PP .nf ssize_t papplDeviceRead ( pappl_device_t *device, void *buffer, size_t bytes ); .fi .PP This function reads data from the device. Depending on the device, this function may block indefinitely. .SS papplDeviceRemoveScheme Remove the named device URI scheme. .PP .nf void papplDeviceRemoveScheme ( const char *scheme ); .fi .PP This function removes support for the named device URI scheme. Use only when you want to disable a URI scheme for security or functional reasons, for example to disable the "file" URI scheme. .SS papplDeviceRemoveTypes Remove device URI schemes of the specified types. .PP .nf void papplDeviceRemoveTypes ( pappl_devtype_t types ); .fi .PP This function removes device URI schemes of the specified types. Use only when you want to disable URI schemes for security or functional reasons, for example to disable all network URI schemes. .SS papplDeviceSetData Set device-specific data. .PP .nf void papplDeviceSetData ( pappl_device_t *device, void *data ); .fi .PP This function sets any device-specific data needed to communicate with the device. It is normally only called from the open callback that was registered for the device URI scheme. .SS papplDeviceWrite Write to a device. .PP .nf ssize_t papplDeviceWrite ( pappl_device_t *device, const void *buffer, size_t bytes ); .fi .PP This function buffers data that will be sent to the device. Call the \fIpapplDeviceFlush\fR function to ensure that the data is immediately sent to the device. .SH STRUCTURES .SS pappl_devmetrics_s Device metrics .PP .nf struct pappl_devmetrics_s { size_t read_bytes; size_t read_msecs; size_t read_requests; size_t status_msecs; size_t status_requests; size_t write_bytes; size_t write_msecs; size_t write_requests; }; .fi .SH TYPES .SS pappl_devclose_cb_t Device close callback .PP .nf typedef void (*pappl_devclose_cb_t)(pappl_device_t *device); .fi .SS pappl_deverror_cb_t Device error callback .PP .nf typedef void (*pappl_deverror_cb_t)(const char *message, void *err_data); .fi .SS pappl_device_cb_t Device callback - return \fBtrue\fR to stop, \fBfalse\fR to continue .PP .nf typedef bool (*pappl_device_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data); .fi .SS pappl_devid_cb_t Device ID callback .PP .nf typedef char * (*pappl_devid_cb_t)(pappl_device_t *device, char *buffer, size_t bufsize); .fi .SS pappl_devlist_cb_t Device list callback .PP .nf typedef bool (*pappl_devlist_cb_t)(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data); .fi .SS pappl_devmetrics_t Device metrics .PP .nf typedef struct pappl_devmetrics_s pappl_devmetrics_t; .fi .SS pappl_devopen_cb_t Device open callback .PP .nf typedef bool (*pappl_devopen_cb_t)(pappl_device_t *device, const char *device_uri, const char *name); .fi .SS pappl_devread_cb_t Device read callback .PP .nf typedef ssize_t (*pappl_devread_cb_t)(pappl_device_t *device, void *buffer, size_t bytes); .fi .SS pappl_devstatus_cb_t Device status callback .PP .nf typedef pappl_preason_t (*pappl_devstatus_cb_t)(pappl_device_t *device); .fi .SS pappl_devsupplies_cb_t Device supplies callback .PP .nf typedef int (*pappl_devsupplies_cb_t)(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies); .fi .SS pappl_devtype_t Device type bitfield .PP .nf typedef unsigned pappl_devtype_t; .fi .SS pappl_devwrite_cb_t Device write callback .PP .nf typedef ssize_t (*pappl_devwrite_cb_t)(pappl_device_t *device, const void *buffer, size_t bytes); .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-footer.man000066400000000000000000000011651476704353100165360ustar00rootroot00000000000000.SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-job-body.man000066400000000000000000000062731476704353100167520ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_job_s .B pappl_job_t; .PP .I void .br .BI papplJobCancel "(pappl_job_t *job);" .PP .I bool .br .BI papplJobFilterImage "(pappl_job_t *job, pappl_device_t *device, pappl_joptions_t *options, const unsigned char *pixels, unsigned width, unsigned height, unsigned depth, bool smoothing);" .PP .I ipp_attribute_t * .br .BI papplJobGetAttribute "(pappl_job_t *job, const char *name);" .PP .I void * .br .BI papplJobGetData "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetFilename "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetFormat "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetID "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetImpressions "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetImpressionsCompleted "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetMessage "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetName "(pappl_job_t *job);" .PP .I pappl_joptions_t * .br .BI papplJobGetOptions "(pappl_job_t *job, pappl_joptions_t *options, unsigned num_pages, bool color);" .PP .I pappl_printer_t * .br .BI papplJobGetPrinter "(pappl_job_t *job);" .PP .I pappl_jreason_t .br .BI papplJobGetReasons "(pappl_job_t *job);" .PP .I ipp_jstate_t .br .BI papplJobGetState "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeCompleted "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeCreated "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeProcessed "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetUsername "(pappl_job_t *job);" .PP .I bool .br .BI papplJobIsCanceled "(pappl_job_t *job);" .PP .I int .br .BI papplJobOpenFile "(pappl_job_t *job, char *fname, size_t fnamesize, const char *directory, const char *ext, const char *mode);" .PP .I void .br .BI papplJobSetData "(pappl_job_t *job, void *data);" .PP .I void .br .BI papplJobSetImpressions "(pappl_job_t *job, int impressions);" .PP .I void .br .BI papplJobSetImpressionsCompleted "(pappl_job_t *job, int add);" .PP .I void .br .BI papplJobSetMessage "(pappl_job_t *job, const char *message, ...);" .PP .I void .br .BI papplJobSetReasons "(pappl_job_t *job, pappl_jreason_t add, pappl_jreason_t remove);" .SH DESCRIPTION The .B PAPPL job functions provide access to the job object. Jobs and the life cycle of the .B pappl_job_t objects are managed automatically by the system object for the printer application. .PP The .B papplJobGet functions get the current values associated with a job while the .B papplJobSet functions set the current values associated with a job. .PP The .B papplJobCancel function cancels processing of a job, while the .B papplJobIsCanceled function returns whether a job is in the canceled state (\fIIPP_JSTATE_CANCELED\fR) or is in the process of being canceled (\fIIPP_JSTATE_PROCESSING\fR and \fIPAPPL_JREASON_PROCESSING_TO_STOP_POINT\fR). .PP The .B papplJobOpenFile function opens a file associated with the job. The file descriptor must be closed by the caller using the .BR close (2) system call. .PP The .B papplJobFilterImage function converts raw image data to raster data suitable for the printer. pappl-1.4.9/man/pappl-job.3000066400000000000000000000421701476704353100154020ustar00rootroot00000000000000.TH pappl-job 3 "pappl job functions" "2025-03-20" "pappl job functions" .SH NAME pappl-job \- pappl job functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_job_s .B pappl_job_t; .PP .I void .br .BI papplJobCancel "(pappl_job_t *job);" .PP .I bool .br .BI papplJobFilterImage "(pappl_job_t *job, pappl_device_t *device, pappl_joptions_t *options, const unsigned char *pixels, unsigned width, unsigned height, unsigned depth, bool smoothing);" .PP .I ipp_attribute_t * .br .BI papplJobGetAttribute "(pappl_job_t *job, const char *name);" .PP .I void * .br .BI papplJobGetData "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetFilename "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetFormat "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetID "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetImpressions "(pappl_job_t *job);" .PP .I int .br .BI papplJobGetImpressionsCompleted "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetMessage "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetName "(pappl_job_t *job);" .PP .I pappl_joptions_t * .br .BI papplJobGetOptions "(pappl_job_t *job, pappl_joptions_t *options, unsigned num_pages, bool color);" .PP .I pappl_printer_t * .br .BI papplJobGetPrinter "(pappl_job_t *job);" .PP .I pappl_jreason_t .br .BI papplJobGetReasons "(pappl_job_t *job);" .PP .I ipp_jstate_t .br .BI papplJobGetState "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeCompleted "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeCreated "(pappl_job_t *job);" .PP .I time_t .br .BI papplJobGetTimeProcessed "(pappl_job_t *job);" .PP .I const char * .br .BI papplJobGetUsername "(pappl_job_t *job);" .PP .I bool .br .BI papplJobIsCanceled "(pappl_job_t *job);" .PP .I int .br .BI papplJobOpenFile "(pappl_job_t *job, char *fname, size_t fnamesize, const char *directory, const char *ext, const char *mode);" .PP .I void .br .BI papplJobSetData "(pappl_job_t *job, void *data);" .PP .I void .br .BI papplJobSetImpressions "(pappl_job_t *job, int impressions);" .PP .I void .br .BI papplJobSetImpressionsCompleted "(pappl_job_t *job, int add);" .PP .I void .br .BI papplJobSetMessage "(pappl_job_t *job, const char *message, ...);" .PP .I void .br .BI papplJobSetReasons "(pappl_job_t *job, pappl_jreason_t add, pappl_jreason_t remove);" .SH DESCRIPTION The .B PAPPL job functions provide access to the job object. Jobs and the life cycle of the .B pappl_job_t objects are managed automatically by the system object for the printer application. .PP The .B papplJobGet functions get the current values associated with a job while the .B papplJobSet functions set the current values associated with a job. .PP The .B papplJobCancel function cancels processing of a job, while the .B papplJobIsCanceled function returns whether a job is in the canceled state (\fIIPP_JSTATE_CANCELED\fR) or is in the process of being canceled (\fIIPP_JSTATE_PROCESSING\fR and \fIPAPPL_JREASON_PROCESSING_TO_STOP_POINT\fR). .PP The .B papplJobOpenFile function opens a file associated with the job. The file descriptor must be closed by the caller using the .BR close (2) system call. .PP The .B papplJobFilterImage function converts raw image data to raster data suitable for the printer. .SH ENUMERATIONS .SS pappl_jreason_e IPP "job-state-reasons" bit values .TP 5 PAPPL_JREASON_ABORTED_BY_SYSTEM .br \'aborted-by-system' .TP 5 PAPPL_JREASON_COMPRESSION_ERROR .br \'compression-error' .TP 5 PAPPL_JREASON_DOCUMENT_FORMAT_ERROR .br \'document-format-error' .TP 5 PAPPL_JREASON_DOCUMENT_PASSWORD_ERROR .br \'document-password-error' .TP 5 PAPPL_JREASON_DOCUMENT_PERMISSION_ERROR .br \'document-permission-error' .TP 5 PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR .br \'document-unprintable-error' .TP 5 PAPPL_JREASON_ERRORS_DETECTED .br \'errors-detected' .TP 5 PAPPL_JREASON_JOB_CANCELED_AFTER_TIMEOUT .br \'job-canceled-after-timeout' .TP 5 PAPPL_JREASON_JOB_CANCELED_AT_DEVICE .br \'job-canceled-at-device' .TP 5 PAPPL_JREASON_JOB_CANCELED_BY_USER .br \'job-canceled-by-user' .TP 5 PAPPL_JREASON_JOB_COMPLETED_SUCCESSFULLY .br \'job-completed-successfully' .TP 5 PAPPL_JREASON_JOB_COMPLETED_WITH_ERRORS .br \'job-completed-with-errors' .TP 5 PAPPL_JREASON_JOB_COMPLETED_WITH_WARNINGS .br \'job-completed-with-warnings' .TP 5 PAPPL_JREASON_JOB_DATA_INSUFFICIENT .br \'job-data-insufficient' .TP 5 PAPPL_JREASON_JOB_FETCHABLE .br \'job-fetchable' .TP 5 PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED .br \'job-hold-until-specified' .TP 5 PAPPL_JREASON_JOB_INCOMING .br \'job-incoming' .TP 5 PAPPL_JREASON_JOB_PRINTING .br \'job-printing' .TP 5 PAPPL_JREASON_JOB_QUEUED .br \'job-queued' .TP 5 PAPPL_JREASON_JOB_SPOOLING .br \'job-spooling' .TP 5 PAPPL_JREASON_JOB_SUSPENDED_FOR_APPROVAL .br \'job-suspended-for-approval' .TP 5 PAPPL_JREASON_NONE .br \'none' .TP 5 PAPPL_JREASON_PRINTER_STOPPED .br \'printer-stopped' .TP 5 PAPPL_JREASON_PRINTER_STOPPED_PARTLY .br \'printer-stopped-partly' .TP 5 PAPPL_JREASON_PROCESSING_TO_STOP_POINT .br \'processing-to-stop-point' .TP 5 PAPPL_JREASON_QUEUED_IN_DEVICE .br \'queued-in-device' .TP 5 PAPPL_JREASON_WARNINGS_DETECTED .br \'warnings-detected' .SH FUNCTIONS .SS papplJobCancel Cancel a job. .PP .nf void papplJobCancel ( pappl_job_t *job ); .fi .PP This function cancels the specified job. If the job is currently being printed, it will be stopped at a convenient time (usually the end of a page) so that the printer will be left in a known state. .SS papplJobCreatePrintOptions Create the printer options for a job. .PP .nf pappl_pr_options_t * papplJobCreatePrintOptions ( pappl_job_t *job, unsigned num_pages, bool color ); .fi .PP This function allocates a printer options structure and computes the print options for a job based upon the Job Template attributes submitted in the print request and the default values set in the printer driver data. .PP The "num_pages" and "color" arguments specify the number of pages and whether the document contains non-grayscale colors - this information typically comes from parsing the job file. .SS papplJobCreateWithFile Create a job with a local file. .PP .nf pappl_job_t * papplJobCreateWithFile ( pappl_printer_t *printer, const char *username, const char *format, const char *job_name, int num_options, cups_option_t *options, const char *filename ); .fi .PP This function creates a new print job with a local file. The "num_options" and "options" parameters specify additional print options, as needed. The file specified by "filename" is removed automatically if it resides in the spool directory. .SS papplJobDeletePrintOptions Delete a job options structure. .PP .nf void papplJobDeletePrintOptions ( pappl_pr_options_t *options ); .fi .PP This function frees the memory used for a job options structure. .SS papplJobFilterImage Filter an image in memory. .PP .nf bool papplJobFilterImage ( pappl_job_t *job, pappl_device_t *device, pappl_pr_options_t *options, const unsigned char *pixels, int width, int height, int depth, int ppi, bool smoothing ); .fi .PP This function will print a grayscale or sRGB image using the printer's raster driver interface, scaling and positioning the image as necessary based on the job options, and printing as many copies as requested. .PP The image data is an array of grayscale ("depth" = \fB1\fR) or sRGB ("depth" = \fB3\fR) pixels starting at the top-left corner of the image. .PP The image resolution ("ppi") is expressed in pixels per inch and is used for some "print-scaling" modes. Pass \fB0\fR if the image has no explicit resolution information. .SS papplJobGetAttribute Get an attribute from a job. .PP .nf ipp_attribute_t * papplJobGetAttribute ( pappl_job_t *job, const char *name ); .fi .PP This function gets the named IPP attribute from a job. The returned attribute can be examined using the \fBippGetXxx\fR functions. .SS papplJobGetCopies Get the number of copies in the job. .PP .nf int papplJobGetCopies ( pappl_job_t *job ); .fi .PP This function returns the number of copies to produce of the job's document data. .SS papplJobGetCopiesCompleted Get the number of completed copies. .PP .nf int papplJobGetCopiesCompleted ( pappl_job_t *job ); .fi .PP This function returns the number of copies that have been completed. .SS papplJobGetData Get per-job driver data. .PP .nf void * papplJobGetData ( pappl_job_t *job ); .fi .PP This function returns the driver data associated with the job. It is normally only called from drivers to maintain state for the processing of the job, for example to store bitmap compression information. .SS papplJobGetFilename Get the job's filename. .PP .nf const char * papplJobGetFilename ( pappl_job_t *job ); .fi .PP This function returns the filename for the job's document data. .SS papplJobGetFormat Get the MIME media type for the job's file. .PP .nf const char * papplJobGetFormat ( pappl_job_t *job ); .fi .PP This function returns the MIME media type for the job's document data. .SS papplJobGetID Get the job ID value. .PP .nf int papplJobGetID ( pappl_job_t *job ); .fi .PP This function returns the job's unique integer identifier. .SS papplJobGetImpressions Get the number of impressions (sides) in the job. .PP .nf int papplJobGetImpressions ( pappl_job_t *job ); .fi .PP This function returns the number of impressions in the job's document data. An impression is one side of an output page. .SS papplJobGetImpressionsCompleted Get the number of completed impressions (sides) in the job. .PP .nf int papplJobGetImpressionsCompleted ( pappl_job_t *job ); .fi .PP This function returns the number of impressions that have been printed. An impression is one side of an output page. .SS papplJobGetMessage Get the current job message string, if any. .PP .nf const char * papplJobGetMessage ( pappl_job_t *job ); .fi .PP This function returns the current job message string, if any. .SS papplJobGetName Get the job name/title. .PP .nf const char * papplJobGetName ( pappl_job_t *job ); .fi .PP This function returns the name or title of the job. .SS papplJobGetPrinter Get the printer for the job. .PP .nf pappl_printer_t * papplJobGetPrinter ( pappl_job_t *job ); .fi .PP This function returns the printer containing the job. .SS papplJobGetReasons Get the current job state reasons. .PP .nf pappl_jreason_t papplJobGetReasons ( pappl_job_t *job ); .fi .PP This function returns the current job state reasons bitfield. .SS papplJobGetState Get the current job state. .PP .nf ipp_jstate_t papplJobGetState ( pappl_job_t *job ); .fi .PP This function returns the current job processing state, which is represented as an enumeration: .PP .IP \(bu 5 \fBIPP_JSTATE_ABORTED\fR: Job has been aborted by the system due to an error. .IP \(bu 5 \fBIPP_JSTATE_CANCELED\fR: Job has been canceled by a user. .IP \(bu 5 \fBIPP_JSTATE_COMPLETED\fR: Job has finished printing. .IP \(bu 5 \fBIPP_JSTATE_HELD\fR: Job is being held for some reason, typically because the document data is being received. .IP \(bu 5 \fBIPP_JSTATE_PENDING\fR: Job is queued and waiting to be printed. .IP \(bu 5 \fBIPP_JSTATE_PROCESSING\fR: Job is being printed. .IP \(bu 5 \fBIPP_JSTATE_STOPPED\fR: Job is paused, typically when the printer is not ready. .SS papplJobGetTimeCompleted Get the job completion time, if any. .PP .nf time_t papplJobGetTimeCompleted ( pappl_job_t *job ); .fi .PP This function returns the date and time when the job reached the completed, canceled, or aborted states. \fB0\fR is returned if the job is not yet in one of those states. .SS papplJobGetTimeCreated Get the job creation time. .PP .nf time_t papplJobGetTimeCreated ( pappl_job_t *job ); .fi .PP This function returns the date and time when the job was created. .SS papplJobGetTimeProcessed Get the job processing time. .PP .nf time_t papplJobGetTimeProcessed ( pappl_job_t *job ); .fi .PP This function returns the date and time when the job started processing (printing). .SS papplJobGetUsername Get the name of the user that submitted the job. .PP .nf const char * papplJobGetUsername ( pappl_job_t *job ); .fi .PP This function returns the name of the user that submitted the job. .SS papplJobHold Hold a job for printing. .PP .nf bool papplJobHold ( pappl_job_t *job, const char *username, const char *until, time_t until_time ); .fi .PP This function holds a pending job for printing at a later time. .SS papplJobIsCanceled Return whether the job is canceled. .PP .nf bool papplJobIsCanceled ( pappl_job_t *job ); .fi .PP This function returns \fBtrue\fR if the job has been canceled or aborted. .SS papplJobOpenFile Create or open a file for the document in a job. .PP .nf int papplJobOpenFile ( pappl_job_t *job, char *fname, size_t fnamesize, const char *directory, const char *ext, const char *mode ); .fi .PP This function creates or opens a file for a job. The "fname" and "fnamesize" arguments specify the location and size of a buffer to store the job filename, which incorporates the "directory", printer ID, job ID, job name (title), and "ext" values. The job name is "sanitized" to only contain alphanumeric characters. .PP The "mode" argument is "r" to read an existing job file or "w" to write a new job file. New files are created with restricted permissions for security purposes. .SS papplJobRelease Release a job for printing. .PP .nf bool papplJobRelease ( pappl_job_t *job, const char *username ); .fi .PP This function releases a held job for printing. .SS papplJobResume Resume processing of a job. .PP .nf void papplJobResume ( pappl_job_t *job, pappl_jreason_t remove ); .fi .SS papplJobRetain Retain a completed job until the specified time. .PP .nf bool papplJobRetain ( pappl_job_t *job, const char *username, const char *until, int until_interval, time_t until_time ); .fi .SS papplJobSetCopiesCompleted Add completed copies to the job. .PP .nf void papplJobSetCopiesCompleted ( pappl_job_t *job, int add ); .fi .PP This function updates the number of completed impressions in a job. An impression is one side of an output page. .SS papplJobSetData Set the per-job driver data pointer. .PP .nf void papplJobSetData ( pappl_job_t *job, void *data ); .fi .PP This function sets the driver data for the specified job. It is normally only called from drivers to maintain state for the processing of the job, for example to store bitmap compression information. .SS papplJobSetImpressions Set the number of impressions (sides) in a job. .PP .nf void papplJobSetImpressions ( pappl_job_t *job, int impressions ); .fi .PP This function sets the number of impressions in a job. An impression is one side of an output page. .SS papplJobSetImpressionsCompleted Add completed impressions (sides) to the job. .PP .nf void papplJobSetImpressionsCompleted ( pappl_job_t *job, int add ); .fi .PP This function updates the number of completed impressions in a job. An impression is one side of an output page. .SS papplJobSetMessage Set the job message string. .PP .nf void papplJobSetMessage ( pappl_job_t *job, const char *message, ... ); .fi .PP This function sets the job message string using a \fBprintf\fR-style format string. .PP .IP 5 Note: The maximum length of the job message string is 1023 bytes. .SS papplJobSetReasons Set the job state reasons bit values. .PP .nf void papplJobSetReasons ( pappl_job_t *job, pappl_jreason_t add, pappl_jreason_t remove ); .fi .PP This function updates the job state reasons bitfield. The "remove" bits are cleared first, then the "add" bits are set. .SS papplJobSuspend Temporarily stop processing of a job. .PP .nf void papplJobSuspend ( pappl_job_t *job, pappl_jreason_t add ); .fi .SS papplPrinterFindJob Find a job. .PP .nf pappl_job_t * papplPrinterFindJob ( pappl_printer_t *printer, int job_id ); .fi .PP This function finds a job submitted to a printer using its integer ID value. .SS papplSystemCleanJobs Clean out old (completed) jobs. .PP .nf void papplSystemCleanJobs ( pappl_system_t *system ); .fi .PP This function deletes all old (completed) jobs above the limit set by the \fIpapplPrinterSetMaxCompletedJobs\fR function. The level may temporarily exceed this limit if the jobs were completed within the last 60 seconds. .PP .IP 5 Note: This function is normally called automatically from the .IP 5 \fIpapplSystemRun\fR function. .SH TYPES .SS pappl_jreason_t Bitfield for IPP "job-state-reasons" values .PP .nf typedef unsigned int pappl_jreason_t; .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-log-body.man000066400000000000000000000022131476704353100167470ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I void .br .BI papplLog "(pappl_system_t *system, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogClient "(pappl_client_t *client, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogJob "(pappl_job_t *job, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogPrinter "(pappl_printer_t *printer, pappl_loglevel_t level, const char *message, ...);" .SH DESCRIPTION The .B PAPPL logging functions record messages to the configured log file. .PP .B papplLog records messages applying to the system as a whole. .PP .B papplLogClient, .B papplLogJob, and .B papplLogPrinter record messages specific to a client connection, print job, or printer respectively. .PP The .I level argument specifies a log level from debugging (\fIPAPPL_LOGLEVEL_DEBUG\fR) to fatal (\fIPAPPL_LOGLEVEL_FATAL\fR) and is used to determine whether the message is recorded to the log. .PP The .I message argument specifies the message using a .BR printf (3) format string. pappl-1.4.9/man/pappl-log.3000066400000000000000000000130501476704353100154040ustar00rootroot00000000000000.TH pappl-log 3 "pappl logging functions" "2025-03-20" "pappl logging functions" .SH NAME pappl-log \- pappl logging functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I void .br .BI papplLog "(pappl_system_t *system, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogClient "(pappl_client_t *client, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogJob "(pappl_job_t *job, pappl_loglevel_t level, const char *message, ...);" .PP .I void .br .BI papplLogPrinter "(pappl_printer_t *printer, pappl_loglevel_t level, const char *message, ...);" .SH DESCRIPTION The .B PAPPL logging functions record messages to the configured log file. .PP .B papplLog records messages applying to the system as a whole. .PP .B papplLogClient, .B papplLogJob, and .B papplLogPrinter record messages specific to a client connection, print job, or printer respectively. .PP The .I level argument specifies a log level from debugging (\fIPAPPL_LOGLEVEL_DEBUG\fR) to fatal (\fIPAPPL_LOGLEVEL_FATAL\fR) and is used to determine whether the message is recorded to the log. .PP The .I message argument specifies the message using a .BR printf (3) format string. .SH ENUMERATIONS .SS pappl_loglevel_e Log levels .TP 5 PAPPL_LOGLEVEL_DEBUG .br Debug message .TP 5 PAPPL_LOGLEVEL_ERROR .br Error message .TP 5 PAPPL_LOGLEVEL_FATAL .br Fatal message .TP 5 PAPPL_LOGLEVEL_INFO .br Informational message .TP 5 PAPPL_LOGLEVEL_UNSPEC .br Not specified .TP 5 PAPPL_LOGLEVEL_WARN .br Warning message .SH FUNCTIONS .SS papplLog Log a message for the system. .PP .nf void papplLog ( pappl_system_t *system, pappl_loglevel_t level, const char *message, ... ); .fi .PP This function sends a message to the system's log file. The "level" argument specifies the urgency of the message: .PP .IP \(bu 5 \fBPAPPL_LOGLEVEL_DEBUG\fR: A debugging message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_ERROR\fR: An error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_FATAL\fR: A fatal error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_INFO\fR: An informational message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_WARN\fR: A warning message. .PP The "message" argument specifies a \fBprintf\fR-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters. .SS papplLogClient Log a message for a client. .PP .nf void papplLogClient ( pappl_client_t *client, pappl_loglevel_t level, const char *message, ... ); .fi .PP This function sends a client message to the system's log file. The "level" argument specifies the urgency of the message: .PP .IP \(bu 5 \fBPAPPL_LOGLEVEL_DEBUG\fR: A debugging message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_ERROR\fR: An error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_FATAL\fR: A fatal error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_INFO\fR: An informational message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_WARN\fR: A warning message. .PP The "message" argument specifies a \fBprintf\fR-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters. .SS papplLogDevice Log a device error for the system... .PP .nf void papplLogDevice ( const char *message, void *data ); .fi .PP This function sends a device error message to the system's log file. .SS papplLogJob Log a message for a job. .PP .nf void papplLogJob ( pappl_job_t *job, pappl_loglevel_t level, const char *message, ... ); .fi .PP This function sends a job message to the system's log file. The "level" argument specifies the urgency of the message: .PP .IP \(bu 5 \fBPAPPL_LOGLEVEL_DEBUG\fR: A debugging message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_ERROR\fR: An error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_FATAL\fR: A fatal error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_INFO\fR: An informational message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_WARN\fR: A warning message. .PP The "message" argument specifies a \fBprintf\fR-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters. .SS papplLogPrinter Log a message for a printer. .PP .nf void papplLogPrinter ( pappl_printer_t *printer, pappl_loglevel_t level, const char *message, ... ); .fi .PP This function sends a printer message to the system's log file. The "level" argument specifies the urgency of the message: .PP .IP \(bu 5 \fBPAPPL_LOGLEVEL_DEBUG\fR: A debugging message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_ERROR\fR: An error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_FATAL\fR: A fatal error message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_INFO\fR: An informational message. .IP \(bu 5 \fBPAPPL_LOGLEVEL_WARN\fR: A warning message. .PP The "message" argument specifies a \fBprintf\fR-style format string. Values logged using the "%c" and "%s" format specifiers are sanitized to not contain control characters. .SH TYPES .SS pappl_loglevel_t Log levels .PP .nf typedef enum pappl_loglevel_e pappl_loglevel_t; .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-mainloop-body.man000066400000000000000000000011441476704353100200060ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I int .br .BI papplMainloop "(int argc, char *argv[], const char *version, const char *footer_html, int num_drivers, pappl_driver_t *drivers, pappl_driver_cb_t driver_cb, pappl_ml_autoadd_cb_t autoadd_cb, const char *subcmd_name, pappl_ml_subcmd_cb_t subcmd_cb, pappl_ml_system_cb_t system_cb, pappl_ml_usage_cb_t usage_cb, void *data);" .SH DESCRIPTION The .PP PAPPL mainloop function starts the printer application and supports standard command-line arguments and behaviors. pappl-1.4.9/man/pappl-mainloop.3000066400000000000000000000075401476704353100164500ustar00rootroot00000000000000.TH pappl-mainloop 3 "pappl main loop functions" "2025-03-20" "pappl main loop functions" .SH NAME pappl-mainloop \- pappl main loop functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I int .br .BI papplMainloop "(int argc, char *argv[], const char *version, const char *footer_html, int num_drivers, pappl_driver_t *drivers, pappl_driver_cb_t driver_cb, pappl_ml_autoadd_cb_t autoadd_cb, const char *subcmd_name, pappl_ml_subcmd_cb_t subcmd_cb, pappl_ml_system_cb_t system_cb, pappl_ml_usage_cb_t usage_cb, void *data);" .SH DESCRIPTION The .PP PAPPL mainloop function starts the printer application and supports standard command-line arguments and behaviors. .SH FUNCTIONS .SS papplMainloop Run a standard main loop for printer applications. .PP .nf int papplMainloop ( int argc, char *argv[], const char *version, const char *footer_html, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_driver_cb_t driver_cb, const char *subcmd_name, pappl_ml_subcmd_cb_t subcmd_cb, pappl_ml_system_cb_t system_cb, pappl_ml_usage_cb_t usage_cb, void *data ); .fi .PP This function runs a standard main loop for a printer application. The "argc" and "argv" arguments are those provided to the \fBmain\fR function. .PP The "version" argument specifies a numeric version number for the printer application that conforms to semantic versioning guidelines with up to four numbers, for example "1.2.3.4". .PP The "footer_html" argument specifies HTML text to use in the footer of the web interface. If \fBNULL\fR, the footer is omitted. .PP The "num_drivers", "drivers", and "driver_cb" arguments specify a list of drivers and the driver callback for printers. Specify \fB0\fR and \fBNULL\fR if the drivers are configured in the system callback. The "autoadd_cb" argument specifies a callback for automatically adding new printers with the "autoadd" sub-command and for auto-detecting the driver when adding manually. .PP The "usage_cb" argument specifies a callback that displays a usage/help summary. If \fBNULL\fR, a generic summary is shown as needed. .PP The "subcmd_name" and "subcmd_cb" arguments specify the name and a callback for a custom sub-command. If \fBNULL\fR, no custom sub-commands will be supported. .PP The "system_cb" argument specifies a function that will create a new \fBpappl_system_t\fR object. If \fBNULL\fR, a default system object is created. .PP The "data" argument provides application-specific data for each of the callbacks. .SS papplMainloopShutdown Request a shutdown of a running system. .PP .nf void papplMainloopShutdown (void); .fi .PP This function requests that the system started by \fIpapplMainloop\fR be shutdown. .SH TYPES .SS pappl_ml_subcmd_cb_t Sub-command callback .PP .nf typedef int (*pappl_ml_subcmd_cb_t)(const char *base_name, int num_options, cups_option_t *options, int num_files, char **files, void *data); .fi .SS pappl_ml_system_cb_t System callback .PP .nf typedef pappl_system_t * (*pappl_ml_system_cb_t)(int num_options, cups_option_t *options, void *data); .fi .SS pappl_ml_usage_cb_t Program usage callback .PP .nf typedef void (*pappl_ml_usage_cb_t)(void *data); .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-makeresheader.1000066400000000000000000000025321476704353100174240ustar00rootroot00000000000000.\" .\" pappl-makeresheader man page .\" .\" Copyright © 2019-2020 by Michael R Sweet .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH pappl-makeresheader 1 "pappl-makeresheader" "2020-10-25" "Michael R Sweet" .SH NAME pappl-makeresheader \- resource header utility .SH SYNOPSIS .B pappl-makeresheader .I FILES > .I FILENAME.h .SH DESCRIPTION .B pappl-makeresheader creates a C header file suitable for inclusion in a printer application. The header file creates a C unsigned char array or string constant that can be used with the .B papplSystemAddResourceData or .B papplSystemAddResourceString functions, or as data for a printer icon in the .B pappl_icon_t structure. The C variable names used for each file are generated by replacing all spaces, dots, and dashes with the underscore. For example, a file named "my printer-icon.png" would have the C variable name "my_printer_icon_png". .SH SEE ALSO .BR pappl (1), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-printer-body.man000066400000000000000000000150451476704353100176600ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_printer_s .B pappl_printer_t; .PP .I void .br .BI papplPrinterCancelAllJobs "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterCloseDevice "(pappl_printer_t *printer);" .PP .I pappl_printer_t * .br .BI papplPrinterCreate "(pappl_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_id, const char *device_uri);" .PP .I void .br .BI papplPrinterDelete "(pappl_printer_t *printer);" .PP .I pappl_job_t * .br .BI papplPrinterFindJob "(pappl_printer_t *printer, int job_id);" .PP .I pappl_contact_t * .br .BI papplPrinterGetContact "(pappl_printer_t *printer, pappl_contact_t *contact);" .PP .I const char * .br .BI papplPrinterGetDeviceID "(pappl_printer_t *printer);" .PP .I const char * .br .BI papplPrinterGetDeviceURI "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetDNSSDName "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I ipp_t * .br .BI papplPrinterGetDriverAttributes "(pappl_printer_t *printer);" .PP .I pappl_driver_data_t * .br .BI papplPrinterGetDriverData "(pappl_printer_t *printer, pappl_driver_data_t *data);" .PP .I const char * .br .BI papplPrinterGetDriverName "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetGeoLocation "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I int .br .BI papplPrinterGetID "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetImpressionsCompleted "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetLocation "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I int .br .BI papplPrinterGetMaxActiveJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetMaxCompletedJobs "(pappl_printer_t *printer);" .PP .I const char * .br .BI papplPrinterGetName "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNextJobID "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfActiveJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfCompletedJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfJobs "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetOrganization "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplPrinterGetOrganizationalUnit "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplPrinterGetPrintGroup "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I pappl_preason_t .br .BI papplPrinterGetReasons "(pappl_printer_t *printer);" .PP .I ipp_pstate_t .br .BI papplPrinterGetState "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetSupplies "(pappl_printer_t *printer, int max_supplies, pappl_supply_t *supplies);" .PP .I pappl_system_t * .br .BI papplPrinterGetSystem "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterIterateActiveJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I void .br .BI papplPrinterIterateAllJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I void .br .BI papplPrinterIterateCompletedJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I pappl_device_t * .br .BI papplPrinterOpenDevice "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterPause "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterResume "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterSetContact "(pappl_printer_t *printer, pappl_contact_t *contact);" .PP .I void .br .BI papplPrinterSetDNSSDName "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetDriverData "(pappl_printer_t *printer, pappl_driver_data_t *data, ipp_t *attrs);" .PP .I void .br .BI papplPrinterSetDriverDefaults "(pappl_printer_t *printer, pappl_driver_data_t *data);" .PP .I void .br .BI papplPrinterSetGeoLocation "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetImpressionsCompleted "(pappl_printer_t *printer, int add);" .PP .I void .br .BI papplPrinterSetLocation "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetMaxActiveJobs "(pappl_printer_t *printer, int max_active_jobs);" .PP .I void .br .BI papplPrinterSetMaxCompletedJobs "(pappl_printer_t *printer, int max_completed_jobs);" .PP .I void .br .BI papplPrinterSetNextJobID "(pappl_printer_t *printer, int next_job_id);" .PP .I void .br .BI papplPrinterSetOrganization "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetOrganizationalUnit "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetPrintGroup "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetReadyMedia "(pappl_printer_t *printer, int num_ready, pappl_media_col_t *ready);" .PP .I void .br .BI papplPrinterSetReasons "(pappl_printer_t *printer, pappl_preason_t add, pappl_preason_t remove);" .PP .I void .br .BI papplPrinterSetSupplies "(pappl_printer_t *printer, int num_supplies, pappl_supply_t *supplies);" .PP .I void .br .BI papplPrinterSetUSB "(pappl_printer_t *printer, unsigned vendor_id, unsigned product_id, pappl_uoptions_t options);" .SH DESCRIPTION The .B PAPPL printer functions provide access to the printer object. Printers are created and deleted by the printer application while the life cycle of the .B pappl_printer_t objects are managed automatically by the system object for the printer application. .PP The .B papplPrinterCreate function creates a new printer while the .B papplPrinterDelete function deletes a printer. .PP The .B papplPrinterPause function stops a printer while the .B papplPrinterResume function starts a printer. .PP The .B papplPrinterGet functions get the current values associated with a printer while the .B papplPrinterSet functions set the current values associated with a printer. .PP The .B papplPrinterCancelAddJobs, papplPrinterFindJob, .B papplPrinterGetNumberOfActiveJobs, papplPrinterGetNumberOfCompletedJobs, .B papplPrinterGetNumberOfJobs, papplPrinterIterateActiveJobs, .B papplPrinterIterateAllJobs, and .B papplPrinterIterateCompletedJobs functions provide access to the jobs queued on a printer. .PP The .B papplPrinterOpenDevice function provides access to the device associated with a printer when it is not processing a job. The device must be later closed using the .B papplPrinterCloseDevice function so that the printer can resume job processing. pappl-1.4.9/man/pappl-printer.3000066400000000000000000001261411476704353100163140ustar00rootroot00000000000000.TH pappl-printer 3 "pappl printer functions" "2025-03-20" "pappl printer functions" .SH NAME pappl-printer \- pappl printer functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_printer_s .B pappl_printer_t; .PP .I void .br .BI papplPrinterCancelAllJobs "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterCloseDevice "(pappl_printer_t *printer);" .PP .I pappl_printer_t * .br .BI papplPrinterCreate "(pappl_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_id, const char *device_uri);" .PP .I void .br .BI papplPrinterDelete "(pappl_printer_t *printer);" .PP .I pappl_job_t * .br .BI papplPrinterFindJob "(pappl_printer_t *printer, int job_id);" .PP .I pappl_contact_t * .br .BI papplPrinterGetContact "(pappl_printer_t *printer, pappl_contact_t *contact);" .PP .I const char * .br .BI papplPrinterGetDeviceID "(pappl_printer_t *printer);" .PP .I const char * .br .BI papplPrinterGetDeviceURI "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetDNSSDName "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I ipp_t * .br .BI papplPrinterGetDriverAttributes "(pappl_printer_t *printer);" .PP .I pappl_driver_data_t * .br .BI papplPrinterGetDriverData "(pappl_printer_t *printer, pappl_driver_data_t *data);" .PP .I const char * .br .BI papplPrinterGetDriverName "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetGeoLocation "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I int .br .BI papplPrinterGetID "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetImpressionsCompleted "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetLocation "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I int .br .BI papplPrinterGetMaxActiveJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetMaxCompletedJobs "(pappl_printer_t *printer);" .PP .I const char * .br .BI papplPrinterGetName "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNextJobID "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfActiveJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfCompletedJobs "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetNumberOfJobs "(pappl_printer_t *printer);" .PP .I char * .br .BI papplPrinterGetOrganization "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplPrinterGetOrganizationalUnit "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplPrinterGetPrintGroup "(pappl_printer_t *printer, char *buffer, size_t bufsize);" .PP .I pappl_preason_t .br .BI papplPrinterGetReasons "(pappl_printer_t *printer);" .PP .I ipp_pstate_t .br .BI papplPrinterGetState "(pappl_printer_t *printer);" .PP .I int .br .BI papplPrinterGetSupplies "(pappl_printer_t *printer, int max_supplies, pappl_supply_t *supplies);" .PP .I pappl_system_t * .br .BI papplPrinterGetSystem "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterIterateActiveJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I void .br .BI papplPrinterIterateAllJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I void .br .BI papplPrinterIterateCompletedJobs "(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit);" .PP .I pappl_device_t * .br .BI papplPrinterOpenDevice "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterPause "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterResume "(pappl_printer_t *printer);" .PP .I void .br .BI papplPrinterSetContact "(pappl_printer_t *printer, pappl_contact_t *contact);" .PP .I void .br .BI papplPrinterSetDNSSDName "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetDriverData "(pappl_printer_t *printer, pappl_driver_data_t *data, ipp_t *attrs);" .PP .I void .br .BI papplPrinterSetDriverDefaults "(pappl_printer_t *printer, pappl_driver_data_t *data);" .PP .I void .br .BI papplPrinterSetGeoLocation "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetImpressionsCompleted "(pappl_printer_t *printer, int add);" .PP .I void .br .BI papplPrinterSetLocation "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetMaxActiveJobs "(pappl_printer_t *printer, int max_active_jobs);" .PP .I void .br .BI papplPrinterSetMaxCompletedJobs "(pappl_printer_t *printer, int max_completed_jobs);" .PP .I void .br .BI papplPrinterSetNextJobID "(pappl_printer_t *printer, int next_job_id);" .PP .I void .br .BI papplPrinterSetOrganization "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetOrganizationalUnit "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetPrintGroup "(pappl_printer_t *printer, const char *value);" .PP .I void .br .BI papplPrinterSetReadyMedia "(pappl_printer_t *printer, int num_ready, pappl_media_col_t *ready);" .PP .I void .br .BI papplPrinterSetReasons "(pappl_printer_t *printer, pappl_preason_t add, pappl_preason_t remove);" .PP .I void .br .BI papplPrinterSetSupplies "(pappl_printer_t *printer, int num_supplies, pappl_supply_t *supplies);" .PP .I void .br .BI papplPrinterSetUSB "(pappl_printer_t *printer, unsigned vendor_id, unsigned product_id, pappl_uoptions_t options);" .SH DESCRIPTION The .B PAPPL printer functions provide access to the printer object. Printers are created and deleted by the printer application while the life cycle of the .B pappl_printer_t objects are managed automatically by the system object for the printer application. .PP The .B papplPrinterCreate function creates a new printer while the .B papplPrinterDelete function deletes a printer. .PP The .B papplPrinterPause function stops a printer while the .B papplPrinterResume function starts a printer. .PP The .B papplPrinterGet functions get the current values associated with a printer while the .B papplPrinterSet functions set the current values associated with a printer. .PP The .B papplPrinterCancelAddJobs, papplPrinterFindJob, .B papplPrinterGetNumberOfActiveJobs, papplPrinterGetNumberOfCompletedJobs, .B papplPrinterGetNumberOfJobs, papplPrinterIterateActiveJobs, .B papplPrinterIterateAllJobs, and .B papplPrinterIterateCompletedJobs functions provide access to the jobs queued on a printer. .PP The .B papplPrinterOpenDevice function provides access to the device associated with a printer when it is not processing a job. The device must be later closed using the .B papplPrinterCloseDevice function so that the printer can resume job processing. .SH ENUMERATIONS .SS pappl_color_mode_e IPP "print-color-mode" bit values .TP 5 PAPPL_COLOR_MODE_AUTO .br \'auto' - Automatic color/monochrome print mode .TP 5 PAPPL_COLOR_MODE_AUTO_MONOCHROME .br \'auto-monochrome' - Automatic monochrome/process monochrome print mode .TP 5 PAPPL_COLOR_MODE_BI_LEVEL .br \'bi-level' - B&W (threshold) print mode .TP 5 PAPPL_COLOR_MODE_COLOR .br \'color' - Full color print mode .TP 5 PAPPL_COLOR_MODE_MONOCHROME .br \'monochrome' - Grayscale print mode using 1 color .TP 5 PAPPL_COLOR_MODE_PROCESS_MONOCHROME .br \'process-monochrome' - Grayscale print mode using multiple colors .SS pappl_content_e IPP "print-content-optimize" bit values .TP 5 PAPPL_CONTENT_AUTO .br \'auto': Automatically determine content .TP 5 PAPPL_CONTENT_GRAPHIC .br \'graphic': Optimize for vector graphics .TP 5 PAPPL_CONTENT_PHOTO .br \'photo': Optimize for photos/continuous tone images .TP 5 PAPPL_CONTENT_TEXT .br \'text': Optimize for text .TP 5 PAPPL_CONTENT_TEXT_AND_GRAPHIC .br \'text-and-graphic': Optimize for text and vector graphics .SS pappl_duplex_e Duplex printing support .TP 5 PAPPL_DUPLEX_FLIPPED .br Duplex with flipped back sides .TP 5 PAPPL_DUPLEX_MANUAL_TUMBLE .br Duplex with back side rotated 180 degrees for short-edge duplex .TP 5 PAPPL_DUPLEX_NONE .br No duplex printing support .TP 5 PAPPL_DUPLEX_NORMAL .br Duplex with normal back sides .TP 5 PAPPL_DUPLEX_ROTATED .br Duplex with back side rotated 180 degrees for long-edge duplex .SS pappl_finishings_e IPP "finishings" bit values .TP 5 PAPPL_FINISHINGS_NONE .br \'none' .TP 5 PAPPL_FINISHINGS_PUNCH .br \'punch' .TP 5 PAPPL_FINISHINGS_STAPLE .br \'staple' .TP 5 PAPPL_FINISHINGS_TRIM .br \'trim' .SS pappl_identify_actions_e IPP "identify-actions" bit values .TP 5 PAPPL_IDENTIFY_ACTIONS_DISPLAY .br \'display': Display a message .TP 5 PAPPL_IDENTIFY_ACTIONS_FLASH .br \'flash': Flash the display or a light .TP 5 PAPPL_IDENTIFY_ACTIONS_NONE .br No actions .TP 5 PAPPL_IDENTIFY_ACTIONS_SOUND .br \'sound': Make a sound .TP 5 PAPPL_IDENTIFY_ACTIONS_SPEAK .br \'speak': Speak a message .SS pappl_kind_e IPP "printer-kind" bit values .TP 5 PAPPL_KIND_DISC .br \'disc' .TP 5 PAPPL_KIND_DOCUMENT .br \'document' .TP 5 PAPPL_KIND_ENVELOPE .br \'envelope' .TP 5 PAPPL_KIND_LABEL .br \'label' .TP 5 PAPPL_KIND_LARGE_FORMAT .br \'large-format' .TP 5 PAPPL_KIND_PHOTO .br \'photo' .TP 5 PAPPL_KIND_POSTCARD .br \'postcard' .TP 5 PAPPL_KIND_RECEIPT .br \'receipt' .TP 5 PAPPL_KIND_ROLL .br \'roll' .SS pappl_label_mode_e IPP "label-mode-xxx" bit values .TP 5 PAPPL_LABEL_MODE_APPLICATOR .br \'applicator' .TP 5 PAPPL_LABEL_MODE_CUTTER .br \'cutter' .TP 5 PAPPL_LABEL_MODE_CUTTER_DELAYED .br \'cutter-delayed' .TP 5 PAPPL_LABEL_MODE_KIOSK .br \'kiosk' .TP 5 PAPPL_LABEL_MODE_PEEL_OFF .br \'peel-off' .TP 5 PAPPL_LABEL_MODE_PEEL_OFF_PREPEEL .br \'peel-off-prepeel' .TP 5 PAPPL_LABEL_MODE_REWIND .br \'rewind' .TP 5 PAPPL_LABEL_MODE_RFID .br \'rfid' .TP 5 PAPPL_LABEL_MODE_TEAR_OFF .br \'tear-off' .SS pappl_media_tracking_e IPP "media-tracking" bit values .TP 5 PAPPL_MEDIA_TRACKING_CONTINUOUS .br \'continuous' .TP 5 PAPPL_MEDIA_TRACKING_GAP .br \'gap' .TP 5 PAPPL_MEDIA_TRACKING_MARK .br \'mark' .TP 5 PAPPL_MEDIA_TRACKING_WEB .br \'web' .SS pappl_preason_e IPP "printer-state-reasons" bit values .TP 5 PAPPL_PREASON_COVER_OPEN .br \'cover-open' .TP 5 PAPPL_PREASON_DEVICE_STATUS .br Supported \fIpapplDeviceGetStatus\fR bits .TP 5 PAPPL_PREASON_DOOR_OPEN .br \'door-open' .TP 5 PAPPL_PREASON_IDENTIFY_PRINTER_REQUESTED .br \'identify-printer-requested' .TP 5 PAPPL_PREASON_INPUT_TRAY_MISSING .br \'input-tray-missing' .TP 5 PAPPL_PREASON_MARKER_SUPPLY_EMPTY .br \'marker-supply-empty' .TP 5 PAPPL_PREASON_MARKER_SUPPLY_LOW .br \'marker-supply-low' .TP 5 PAPPL_PREASON_MARKER_WASTE_ALMOST_FULL .br \'marker-waste-almost-full' .TP 5 PAPPL_PREASON_MARKER_WASTE_FULL .br \'marker-waste-full' .TP 5 PAPPL_PREASON_MEDIA_EMPTY .br \'media-empty' .TP 5 PAPPL_PREASON_MEDIA_JAM .br \'media-jam' .TP 5 PAPPL_PREASON_MEDIA_LOW .br \'media-low' .TP 5 PAPPL_PREASON_MEDIA_NEEDED .br \'media-needed' .TP 5 PAPPL_PREASON_NONE .br \'none' .TP 5 PAPPL_PREASON_OFFLINE .br \'offline' .TP 5 PAPPL_PREASON_OTHER .br \'other' .TP 5 PAPPL_PREASON_SPOOL_AREA_FULL .br \'spool-area-full' .TP 5 PAPPL_PREASON_TONER_EMPTY .br \'toner-empty' .TP 5 PAPPL_PREASON_TONER_LOW .br \'toner-low' .SS pappl_raster_type_e IPP "pwg-raster-document-type-supported" bit values .TP 5 PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_16 .br 16-bit per component AdobeRGB .TP 5 PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8 .br 8-bit per component AdobeRGB .TP 5 PAPPL_PWG_RASTER_TYPE_BLACK_1 .br 1-bit (device) black .TP 5 PAPPL_PWG_RASTER_TYPE_BLACK_16 .br 16-bit (device) black .TP 5 PAPPL_PWG_RASTER_TYPE_BLACK_8 .br 8-bit (device) black .TP 5 PAPPL_PWG_RASTER_TYPE_CMYK_16 .br 16-bit per component (device) CMYK .TP 5 PAPPL_PWG_RASTER_TYPE_CMYK_8 .br 8-bit per component (device) CMYK .TP 5 PAPPL_PWG_RASTER_TYPE_NONE .br Do not force a particular raster type .TP 5 PAPPL_PWG_RASTER_TYPE_RGB_16 .br 16-bit per component (device) RGB .TP 5 PAPPL_PWG_RASTER_TYPE_RGB_8 .br 8-bit per component (device) RGB .TP 5 PAPPL_PWG_RASTER_TYPE_SGRAY_16 .br 16-bit grayscale with 2.2 gamma .TP 5 PAPPL_PWG_RASTER_TYPE_SGRAY_8 .br 8-bit grayscale with 2.2 gamma .TP 5 PAPPL_PWG_RASTER_TYPE_SRGB_16 .br 16-bit per component sRGB .TP 5 PAPPL_PWG_RASTER_TYPE_SRGB_8 .br 8-bit per component sRGB .SS pappl_scaling_e IPP "print-scaling" bit values .TP 5 PAPPL_SCALING_AUTO .br \'auto': Scale to fit (non-borderless) or fill (borderless) if larger, otherwise center .TP 5 PAPPL_SCALING_AUTO_FIT .br \'auto-fit': Scale to fit if larger, otherwise center .TP 5 PAPPL_SCALING_FILL .br \'fill': Scale to fill the media .TP 5 PAPPL_SCALING_FIT .br \'fit': Scale to fit within margins .TP 5 PAPPL_SCALING_NONE .br \'none': No scaling (center/crop) .SS pappl_sides_e IPP "sides" bit values .TP 5 PAPPL_SIDES_ONE_SIDED .br \'one-sided' .TP 5 PAPPL_SIDES_TWO_SIDED_LONG_EDGE .br \'two-sided-long-edge' .TP 5 PAPPL_SIDES_TWO_SIDED_SHORT_EDGE .br \'two-sided-short-edge' .SS pappl_uoptions_e USB gadget options .TP 5 PAPPL_UOPTIONS_ETHERNET .br Include USB ethernet gadget .TP 5 PAPPL_UOPTIONS_NONE .br No options (just USB printer) .TP 5 PAPPL_UOPTIONS_SERIAL .br Include USB serial gadget .TP 5 PAPPL_UOPTIONS_STORAGE .br Include USB mass storage gadget .TP 5 PAPPL_UOPTIONS_STORAGE_READONLY .br USB mass storage gadget is read-only .TP 5 PAPPL_UOPTIONS_STORAGE_REMOVABLE .br USB mass storage gadget is removable .SH FUNCTIONS .SS papplPrinterCancelAllJobs Cancel all jobs on the printer. .PP .nf void papplPrinterCancelAllJobs ( pappl_printer_t *printer ); .fi .PP This function cancels all jobs on the printer. If any job is currently being printed, it will be stopped at a convenient time (usually the end of a page) so that the printer will be left in a known state. .SS papplPrinterCloseDevice Close the device associated with the printer. .PP .nf void papplPrinterCloseDevice ( pappl_printer_t *printer ); .fi .PP This function closes the device for a printer. The device must have been previously opened using the \fIpapplPrinterOpenDevice\fR function. .SS papplPrinterCreate Create a new printer. .PP .nf pappl_printer_t * papplPrinterCreate ( pappl_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_id, const char *device_uri ); .fi .PP This function creates a new printer (service) on the specified system. The "type" argument specifies the type of service to create and must currently be the value \fBPAPPL_SERVICE_TYPE_PRINT\fR. .PP The "printer_id" argument specifies a positive integer identifier that is unique to the system. If you specify a value of \fB0\fR a new identifier will be assigned. .PP The "driver_name" argument specifies a named driver for the printer, from the list of drivers registered with the \fIpapplSystemSetPrinterDrivers\fR function. .PP The "device_id" and "device_uri" arguments specify the IEEE-1284 device ID and device URI strings for the printer. .PP On error, this function sets the \fBerrno\fR variable to one of the following values: .PP .IP \(bu 5 \fBEEXIST\fR: A printer with the specified name already exists. .IP \(bu 5 \fBEINVAL\fR: Bad values for the arguments were specified. .IP \(bu 5 \fBEIO\fR: The driver callback failed. .IP \(bu 5 \fBENOENT\fR: No driver callback has been set. .IP \(bu 5 \fBENOMEM\fR: Ran out of memory. .SS papplPrinterDelete Delete a printer. .PP .nf void papplPrinterDelete ( pappl_printer_t *printer ); .fi .PP This function deletes a printer from a system, freeing all memory and canceling all jobs as needed. .SS papplPrinterDisable Stop accepting jobs on a printer. .PP .nf void papplPrinterDisable ( pappl_printer_t *printer ); .fi .PP This function stops accepting jobs on a printer. .SS papplPrinterEnable Start accepting jobs on a printer. .PP .nf void papplPrinterEnable ( pappl_printer_t *printer ); .fi .PP This function starts accepting jobs on a printer. .SS papplPrinterGetContact Get the "printer-contact" value. .PP .nf pappl_contact_t * papplPrinterGetContact ( pappl_printer_t *printer, pappl_contact_t *contact ); .fi .PP This function copies the current printer contact information to the buffer pointed to by the "contact" argument. .SS papplPrinterGetDNSSDName Get the current DNS-SD service name. .PP .nf char * papplPrinterGetDNSSDName ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the current DNS-SD service name to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetDeviceID Get the IEEE-1284 device ID of the printer. .PP .nf const char * papplPrinterGetDeviceID ( pappl_printer_t *printer ); .fi .PP This function returns the IEEE-1284 device ID of the printer. .SS papplPrinterGetDeviceURI Get the URI of the device associated with the printer. .PP .nf const char * papplPrinterGetDeviceURI ( pappl_printer_t *printer ); .fi .PP This function returns the device URI for the printer. .SS papplPrinterGetDriverAttributes Get a copy of the current driver attributes. .PP .nf ipp_t * papplPrinterGetDriverAttributes ( pappl_printer_t *printer ); .fi .PP This function returns a copy the current driver attributes. Use the \fBippDelete\fR function to free the memory used for the attributes when you are done. .SS papplPrinterGetDriverData Get the current print driver data. .PP .nf pappl_pr_driver_data_t * papplPrinterGetDriverData ( pappl_printer_t *printer, pappl_pr_driver_data_t *data ); .fi .PP This function copies the current print driver data, defaults, and ready (loaded) media information into the specified buffer. .SS papplPrinterGetDriverName Get the driver name for a printer. .PP .nf const char * papplPrinterGetDriverName ( pappl_printer_t *printer ); .fi .PP This function returns the driver name for the printer. .SS papplPrinterGetGeoLocation Get the current geo-location as a "geo:" URI. .PP .nf char * papplPrinterGetGeoLocation ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the currently configured geographic location as a "geo:" URI to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetID Get the printer ID. .PP .nf int papplPrinterGetID ( pappl_printer_t *printer ); .fi .PP This function returns the printer's unique positive integer identifier. .SS papplPrinterGetImpressionsCompleted Get the number of impressions (sides) that have been printed. .PP .nf int papplPrinterGetImpressionsCompleted ( pappl_printer_t *printer ); .fi .PP This function returns the number of impressions that have been printed. An impression is one side of an output page. .SS papplPrinterGetLocation Get the location string. .PP .nf char * papplPrinterGetLocation ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the printer's human-readable location to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetMaxActiveJobs Get the maximum number of active (queued) jobs allowed by the printer. .PP .nf int papplPrinterGetMaxActiveJobs ( pappl_printer_t *printer ); .fi .PP This function returns the maximum number of active jobs that the printer supports, as configured by the \fIpapplPrinterSetMaxActiveJobs\fR function. .SS papplPrinterGetMaxCompletedJobs Get the maximum number of jobs retained for history by the printer. .PP .nf int papplPrinterGetMaxCompletedJobs ( pappl_printer_t *printer ); .fi .PP This function returns the maximum number of jobs that are retained in the job history as configured by the \fIpapplPrinterSetMaxCompletedJobs\fR function. .SS papplPrinterGetMaxPreservedJobs Get the maximum number of jobs preserved by the printer. .PP .nf int papplPrinterGetMaxPreservedJobs ( pappl_printer_t *printer ); .fi .PP This function returns the maximum number of jobs that are retained (including document data) in the job history as configured by the \fIpapplPrinterSetMaxPreservedJobs\fR function. .SS papplPrinterGetName Get the printer name. .PP .nf const char * papplPrinterGetName ( pappl_printer_t *printer ); .fi .PP This function returns the printer's human-readable name. .SS papplPrinterGetNextJobID Get the next job ID. .PP .nf int papplPrinterGetNextJobID ( pappl_printer_t *printer ); .fi .PP This function returns the positive integer identifier that will be used for the next job that is created. .SS papplPrinterGetNumberOfActiveJobs Get the number of active print jobs. .PP .nf int papplPrinterGetNumberOfActiveJobs ( pappl_printer_t *printer ); .fi .PP This function returns the number of print jobs that are either printing or waiting to be printed. .SS papplPrinterGetNumberOfCompletedJobs Get the number of completed print jobs. .PP .nf int papplPrinterGetNumberOfCompletedJobs ( pappl_printer_t *printer ); .fi .PP This function returns the number of print jobs that have been aborted, canceled, or completed. .SS papplPrinterGetNumberOfJobs Get the total number of print jobs. .PP .nf int papplPrinterGetNumberOfJobs ( pappl_printer_t *printer ); .fi .PP This function returns the number of print jobs that are printing, waiting to be printed, have been aborted, have been canceled, or have completed. .SS papplPrinterGetOrganization Get the organization name. .PP .nf char * papplPrinterGetOrganization ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the printer's organization name to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetOrganizationalUnit Get the organizational unit name. .PP .nf char * papplPrinterGetOrganizationalUnit ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the printer's organizational unit name to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetPath Get the URL path for a printer web page. .PP .nf char * papplPrinterGetPath ( pappl_printer_t *printer, const char *subpath, char *buffer, size_t bufsize ); .fi .PP This function generates and returns the URL path for the printer's web page. The "subpath" argument specifies an optional sub-path for a specific printer web page. .SS papplPrinterGetPrintGroup Get the print authorization group, if any. .PP .nf char * papplPrinterGetPrintGroup ( pappl_printer_t *printer, char *buffer, size_t bufsize ); .fi .PP This function copies the printer's authorization group name to the buffer pointed to by the "buffer" argument. .SS papplPrinterGetReasons Get the current "printer-state-reasons" bit values. .PP .nf pappl_preason_t papplPrinterGetReasons ( pappl_printer_t *printer ); .fi .PP This function returns the current printer state reasons bitfield, which can be updated by the printer driver and/or by the \fIpapplPrinterSetReasons\fR function. .SS papplPrinterGetState Get the current "printer-state" value. .PP .nf ipp_pstate_t papplPrinterGetState ( pappl_printer_t *printer ); .fi .PP This function returns the current printer state as an enumeration: .PP .IP \(bu 5 \fBIPP_PSTATE_IDLE\fR: The printer is idle and has no jobs to process. .IP \(bu 5 \fBIPP_PSTATE_PROCESSING\fR: The printer is processing a job and/or producing output. .IP \(bu 5 \fBIPP_PSTATE_STOPPED\fR: The printer is stopped for maintenance. .SS papplPrinterGetSupplies Get the current "printer-supplies" values. .PP .nf int papplPrinterGetSupplies ( pappl_printer_t *printer, int max_supplies, pappl_supply_t *supplies ); .fi .PP This function copies the current printer supply values to the specified array. The "max_supplies" and "supplies" arguments can be \fB0\fR and \fBNULL\fR to query the number of supplies used. .PP The return value is the actual number of supplies used by the printer, regardless of the size of the array. .SS papplPrinterGetSystem Get the system associated with the printer. .PP .nf pappl_system_t * papplPrinterGetSystem ( pappl_printer_t *printer ); .fi .PP This function returns a pointer to the system object that contains the printer. .SS papplPrinterHoldNewJobs Hold new jobs for printing. .PP .nf bool papplPrinterHoldNewJobs ( pappl_printer_t *printer ); .fi .PP This function holds any new jobs for printing and is typically used prior to performing printer maintenance. Existing jobs will finish printing but new jobs will be held until you call \fIpapplPrinterReleaseHeldNewJobs\fR. .SS papplPrinterIsAcceptingJobs Return whether the printer is accepting jobs. .PP .nf bool papplPrinterIsAcceptingJobs ( pappl_printer_t *printer ); .fi .PP This function returns a boolean value indicating whether a printer is accepting jobs. .SS papplPrinterIsDeleted Return whether a printer is in the process of being deleted. .PP .nf bool papplPrinterIsDeleted ( pappl_printer_t *printer ); .fi .PP This function returns a boolean value indicating whether a printer is being deleted. .SS papplPrinterIsHoldingNewJobs Return whether the printer is holding new jobs. .PP .nf bool papplPrinterIsHoldingNewJobs ( pappl_printer_t *printer ); .fi .PP This function returns a boolean value indicating whether a printer is holding new jobs. .SS papplPrinterIterateActiveJobs Iterate over the active jobs. .PP .nf void papplPrinterIterateActiveJobs ( pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit ); .fi .PP This function iterates over jobs that are either printing or waiting to be printed. The specified callback "cb" will be called once per job with the data pointer "data". .PP The "job_index" argument specifies the first job in the list to iterate, where \fB1\fR is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use \fB0\fR to iterate an unlimited number of jobs. .SS papplPrinterIterateAllJobs Iterate over all the jobs. .PP .nf void papplPrinterIterateAllJobs ( pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit ); .fi .PP This function iterates over all jobs. The specified callback "cb" will be called once per job with the data pointer "data". .PP The "job_index" argument specifies the first job in the list to iterate, where \fB1\fR is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use \fB0\fR to iterate an unlimited number of jobs. .SS papplPrinterIterateCompletedJobs Iterate over the completed jobs. .PP .nf void papplPrinterIterateCompletedJobs ( pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int job_index, int limit ); .fi .PP This function iterates over jobs that are aborted, canceled, or completed. The specified callback "cb" will be called once per job with the data pointer "data". .PP The "job_index" argument specifies the first job in the list to iterate, where \fB1\fR is the first job, etc. The "limit" argument specifies the maximum number of jobs to iterate - use \fB0\fR to iterate an unlimited number of jobs. .SS papplPrinterOpenDevice Open the device associated with a printer. .PP .nf pappl_device_t * papplPrinterOpenDevice ( pappl_printer_t *printer ); .fi .PP This function opens the printer's device. \fBNULL\fR is returned if the device is already in use, for example while a job is being printed. .PP The returned device must be closed using the \fIpapplPrinterCloseDevice\fR function. .SS papplPrinterOpenFile Create or open a file for a printer. .PP .nf int papplPrinterOpenFile ( pappl_printer_t *printer, char *fname, size_t fnamesize, const char *directory, const char *resname, const char *ext, const char *mode ); .fi .PP This function creates, opens, or removes a file for a printer. The "fname" and "fnamesize" arguments specify the location and size of a buffer to store the printer filename, which incorporates the "directory", printer ID, resource name, and "ext" values. The resource name is "sanitized" to only contain alphanumeric characters. .PP The "mode" argument is "r" to read an existing printer file, "w" to write a new printer file, or "x" to remove an existing printer file. New files are created with restricted permissions for security purposes. .PP For the "r" and "w" modes, the return value is the file descriptor number on success or \fB-1\fR on error. For the "x" mode, the return value is \fB0\fR on success and \fB-1\fR on error. The \fBerrno\fR variable is set appropriately on error. .SS papplPrinterPause Pause (stop) a printer. .PP .nf void papplPrinterPause ( pappl_printer_t *printer ); .fi .PP This function pauses a printer. If the printer is currently processing (printing) a job, it will be completed before the printer is stopped. .SS papplPrinterReleaseHeldNewJobs Release any previously held jobs for printing. .PP .nf bool papplPrinterReleaseHeldNewJobs ( pappl_printer_t *printer, const char *username ); .fi .PP This function releases all jobs that were previously held due to a prior call to \fIpapplPrinterHoldNewJobs\fR. .SS papplPrinterResume Resume (start) a printer. .PP .nf void papplPrinterResume ( pappl_printer_t *printer ); .fi .PP This function resumes a printer and starts processing any pending jobs. .SS papplPrinterSetContact Set the "printer-contact" value. .PP .nf void papplPrinterSetContact ( pappl_printer_t *printer, pappl_contact_t *contact ); .fi .PP This function sets the printer's contact information. .SS papplPrinterSetDNSSDName Set the DNS-SD service name. .PP .nf void papplPrinterSetDNSSDName ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's DNS-SD service name. If \fBNULL\fR, the printer will stop advertising the printer. .SS papplPrinterSetDriverData Set the driver data. .PP .nf bool papplPrinterSetDriverData ( pappl_printer_t *printer, pappl_pr_driver_data_t *data, ipp_t *attrs ); .fi .PP This function validates and sets the driver data, including all defaults and ready (loaded) media. .PP .IP 5 Note: This function regenerates all of the driver-specific capability .IP 5 attributes like "media-col-database", "sides-supported", and so forth. .IP 5 Use the \fIpapplPrinterSetDriverDefaults\fR or .IP 5 \fIpapplPrinterSetReadyMedia\fR functions to efficiently change the .IP 5 "xxx-default" or "xxx-ready" values, respectively. .SS papplPrinterSetDriverDefaults Set the default print option values. .PP .nf bool papplPrinterSetDriverDefaults ( pappl_printer_t *printer, pappl_pr_driver_data_t *data, int num_vendor, cups_option_t *vendor ); .fi .PP This function validates and sets the printer's default print options. .PP .IP 5 Note: Unlike \fIpapplPrinterSetPrintDriverData\fR, this function only .IP 5 changes the "xxx_default" members of the driver data and is considered .IP 5 lightweight. .SS papplPrinterSetGeoLocation Set the geo-location value as a "geo:" URI. .PP .nf void papplPrinterSetGeoLocation ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's geographic location as a "geo:" URI. If \fBNULL\fR, the location is cleared to the 'unknown' value. .SS papplPrinterSetImpressionsCompleted Add impressions (sides) to the total count of printed impressions. .PP .nf void papplPrinterSetImpressionsCompleted ( pappl_printer_t *printer, int add ); .fi .PP This function adds to the printer's impressions counter. An impression is one side of an output page. .SS papplPrinterSetLocation Set the location string. .PP .nf void papplPrinterSetLocation ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's human-readable location string. If \fBNULL\fR, the location is cleared. .SS papplPrinterSetMaxActiveJobs Set the maximum number of active jobs for the printer. .PP .nf void papplPrinterSetMaxActiveJobs ( pappl_printer_t *printer, int max_active_jobs ); .fi .PP This function sets the maximum number of jobs that can be spooled on the printer at one time. .PP .IP 5 Note: This limit does not apply to streaming raster formats such as PWG .IP 5 Raster since they are not spooled. .SS papplPrinterSetMaxCompletedJobs Set the maximum number of completed jobs for the printer. .PP .nf void papplPrinterSetMaxCompletedJobs ( pappl_printer_t *printer, int max_completed_jobs ); .fi .PP This function sets the maximum number of aborted, canceled, or completed jobs that are retained in the job history. .SS papplPrinterSetMaxPreservedJobs Set the maximum number of preserved jobs for the printer. .PP .nf void papplPrinterSetMaxPreservedJobs ( pappl_printer_t *printer, int max_preserved_jobs ); .fi .PP This function sets the maximum number of aborted, canceled, or completed jobs that are preserved (with document data) in the job history. .SS papplPrinterSetNextJobID Set the next "job-id" value. .PP .nf void papplPrinterSetNextJobID ( pappl_printer_t *printer, int next_job_id ); .fi .PP This function sets the next unique positive integer identifier that will be used for a job. .PP .IP 5 Note: This function is normally only called once to restore the previous .IP 5 state of the printer. .SS papplPrinterSetOrganization Set the organization name. .PP .nf void papplPrinterSetOrganization ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's organization name. If \fBNULL\fR the value is cleared. .SS papplPrinterSetOrganizationalUnit Set the organizational unit name. .PP .nf void papplPrinterSetOrganizationalUnit ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's organizational unit name. If \fBNULL\fR the value is cleared. .SS papplPrinterSetPrintGroup Set the print authorization group, if any. .PP .nf void papplPrinterSetPrintGroup ( pappl_printer_t *printer, const char *value ); .fi .PP This function sets the printer's authorization group. If \fBNULL\fR, the group is cleared. .PP .IP 5 Note: The authorization group is only used if the system is created with a .IP 5 named authorization service. .SS papplPrinterSetReadyMedia Set the ready (loaded) media. .PP .nf bool papplPrinterSetReadyMedia ( pappl_printer_t *printer, int num_ready, pappl_media_col_t *ready ); .fi .PP This function validates and sets the printer's ready (loaded) media. .SS papplPrinterSetReasons Add or remove values from "printer-state-reasons". .PP .nf void papplPrinterSetReasons ( pappl_printer_t *printer, pappl_preason_t add, pappl_preason_t remove ); .fi .PP This function updates the printer state reasons bitfield by clearing any bit values in the "remove" argument and setting any bit values in the "add" argument. .SS papplPrinterSetSupplies Set/update the supplies for a printer. .PP .nf void papplPrinterSetSupplies ( pappl_printer_t *printer, int num_supplies, pappl_supply_t *supplies ); .fi .PP This function updates the supply information for the printer. .SS papplPrinterSetUSB Set the USB vendor and product IDs for a printer. .PP .nf void papplPrinterSetUSB ( pappl_printer_t *printer, unsigned vendor_id, unsigned product_id, pappl_uoptions_t options, const char *storagefile, pappl_pr_usb_cb_t usb_cb, void *usb_cbdata ); .fi .PP This function sets the USB vendor and product IDs for a printer as well as specifying USB gadget options when the printer is registered with the USB device controller. .PP The \fBusb_cb\fR argument specifies a processing callback that is called for every byte of data sent from the USB host and which is responsible for interpreting the data, writing data to the device, and handling back-channel data. .PP .IP 5 Note: USB gadget functionality is currently only available when running .IP 5 on Linux with compatible hardware such as the Raspberry Pi Zero and 4B. .SH STRUCTURES .SS pappl_icon_s Printer PNG icon structure .PP .nf struct pappl_icon_s { const void *data; size_t datalen; char filename[256]; }; .fi .SS pappl_media_col_s Media details structure .PP .nf struct pappl_media_col_s { int bottom_margin; int left_margin; int left_offset; int right_margin; int size_length; char size_name[64]; int size_width; char source[64]; int top_margin; int top_offset; pappl_media_tracking_t tracking; char type[64]; }; .fi .SS pappl_pr_driver_data_s Printer driver data .PP .nf struct pappl_pr_driver_data_s { const char *bin[PAPPL_MAX_BIN]; int bin_default; bool borderless; int bottom_top; pappl_color_mode_t color_default; pappl_color_mode_t color_supported; pappl_content_t content_default; int darkness_configured; int darkness_default; int darkness_supported; pappl_pr_delete_cb_t delete_cb; pappl_duplex_t duplex; void *extension; const char *features[PAPPL_MAX_VENDOR]; pappl_finishings_t finishings; pappl_raster_type_t force_raster_type; const char *format; pappl_dither_t gdither; bool has_supplies; pappl_icon_t icons[3]; pappl_pr_identify_cb_t identify_cb; pappl_identify_actions_t identify_default; pappl_identify_actions_t identify_supported; bool input_face_up; pappl_kind_t kind; int left_offset_supported[2]; int left_right; char make_and_model[128]; const char *media[PAPPL_MAX_MEDIA]; pappl_media_col_t media_default; pappl_media_col_t media_ready[PAPPL_MAX_SOURCE]; pappl_label_mode_t mode_configured; pappl_label_mode_t mode_supported; int num_bin; int num_features; int num_media; int num_resolution; int num_source; int num_type; int num_vendor; ipp_orient_t orient_default; bool output_face_up; pappl_dither_t pdither; int ppm; int ppm_color; pappl_pr_printfile_cb_t printfile_cb; ipp_quality_t quality_default; pappl_raster_type_t raster_types; pappl_pr_rendjob_cb_t rendjob_cb; pappl_pr_rendpage_cb_t rendpage_cb; pappl_pr_rstartjob_cb_t rstartjob_cb; pappl_pr_rstartpage_cb_t rstartpage_cb; pappl_pr_rwriteline_cb_t rwriteline_cb; pappl_scaling_t scaling_default; pappl_sides_t sides_default; pappl_sides_t sides_supported; const char *source[PAPPL_MAX_SOURCE]; int speed_default; int speed_supported[2]; pappl_pr_status_cb_t status_cb; int tear_offset_configured; int tear_offset_supported[2]; pappl_pr_testpage_cb_t testpage_cb; int top_offset_supported[2]; pappl_media_tracking_t tracking_supported; const char *type[PAPPL_MAX_TYPE]; const char *vendor[PAPPL_MAX_VENDOR]; int x_default; int x_resolution[PAPPL_MAX_RESOLUTION]; int y_default; int y_resolution[PAPPL_MAX_RESOLUTION]; }; .fi .SS pappl_pr_options_s Combined print job options .PP .nf struct pappl_pr_options_s { int copies; int darkness_configured; pappl_dither_t dither; pappl_finishings_t finishings; unsigned first_page; cups_page_header_t header; unsigned last_page; pappl_media_col_t media; unsigned num_pages; int num_vendor; ipp_orient_t orientation_requested; char output_bin[64]; pappl_color_mode_t print_color_mode; pappl_content_t print_content_optimize; int print_darkness; ipp_quality_t print_quality; pappl_scaling_t print_scaling; int print_speed; int printer_resolution[2]; pappl_sides_t sides; cups_option_t *vendor; }; .fi .SH TYPES .SS pappl_color_mode_t Bitfield for IPP "print-color-mode" values .PP .nf typedef unsigned pappl_color_mode_t; .fi .SS pappl_content_t Bitfield for IPP "print-content-optimize" values .PP .nf typedef unsigned pappl_content_t; .fi .SS pappl_default_cb_t papplIterateDefaults callback .PP .nf typedef void (*pappl_default_cb_t)(ipp_attribute_t *attr, void *data); .fi .SS pappl_duplex_t Duplex printing support .PP .nf typedef enum pappl_duplex_e pappl_duplex_t; .fi .SS pappl_finishings_t Bitfield for IPP "finishings" values .PP .nf typedef unsigned pappl_finishings_t; .fi .SS pappl_icon_t Printer PNG icon structure .PP .nf typedef struct pappl_icon_s pappl_icon_t; .fi .SS pappl_identify_actions_t Bitfield for IPP "identify-actions" values .PP .nf typedef unsigned pappl_identify_actions_t; .fi .SS pappl_job_cb_t papplIterateXxxJobs callback function .PP .nf typedef void (*pappl_job_cb_t)(pappl_job_t *job, void *data); .fi .SS pappl_kind_t Bitfield for IPP "printer-kind" values .PP .nf typedef unsigned pappl_kind_t; .fi .SS pappl_label_mode_t Bitfield for IPP "label-mode-xxx" values .PP .nf typedef unsigned short pappl_label_mode_t; .fi .SS pappl_media_col_t Media details structure .PP .nf typedef struct pappl_media_col_s pappl_media_col_t; .fi .SS pappl_media_tracking_t Bitfield for IPP "media-tracking" values .PP .nf typedef unsigned short pappl_media_tracking_t; .fi .SS pappl_pr_delete_cb_t Printer deletion callback .PP .nf typedef void (*pappl_pr_delete_cb_t)(pappl_printer_t *printer, pappl_pr_driver_data_t *data); .fi .SS pappl_pr_identify_cb_t Identify-Printer callback .PP .nf typedef void (*pappl_pr_identify_cb_t)(pappl_printer_t *printer, pappl_identify_actions_t actions, const char *message); .fi .SS pappl_pr_printfile_cb_t Print a "raw" job callback .PP .nf typedef bool (*pappl_pr_printfile_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); .fi .SS pappl_pr_rendjob_cb_t End a raster job callback .PP .nf typedef bool (*pappl_pr_rendjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); .fi .SS pappl_pr_rendpage_cb_t End a raster page callback .PP .nf typedef bool (*pappl_pr_rendpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); .fi .SS pappl_pr_rstartjob_cb_t Start a raster job callback .PP .nf typedef bool (*pappl_pr_rstartjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); .fi .SS pappl_pr_rstartpage_cb_t Start a raster page callback .PP .nf typedef bool (*pappl_pr_rstartpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); .fi .SS pappl_pr_rwriteline_cb_t Write a line of raster graphics callback .PP .nf typedef bool (*pappl_pr_rwriteline_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned y, const unsigned char *line); .fi .SS pappl_pr_status_cb_t Update printer status callback .PP .nf typedef bool (*pappl_pr_status_cb_t)(pappl_printer_t *printer); .fi .SS pappl_pr_testpage_cb_t Print a test page callback .PP .nf typedef const char * (*pappl_pr_testpage_cb_t)(pappl_printer_t *printer, char *buffer, size_t bufsize); .fi .SS pappl_pr_usb_cb_t Raw USB IO callback .PP .nf typedef ssize_t (*pappl_pr_usb_cb_t)(pappl_printer_t *printer, pappl_device_t *device, void *buffer, size_t bufsize, size_t bytes, void *data); .fi .SS pappl_raster_type_t Bitfield for IPP "pwg-raster-document-type-supported" values .PP .nf typedef unsigned pappl_raster_type_t; .fi .SS pappl_scaling_t Bitfield for IPP "print-scaling" values .PP .nf typedef unsigned pappl_scaling_t; .fi .SS pappl_sides_t Bitfield for IPP "sides" values .PP .nf typedef unsigned pappl_sides_t; .fi .SS pappl_uoptions_t USB gadget options bitfield .PP .nf typedef unsigned pappl_uoptions_t; .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-resource-body.man000066400000000000000000000032071476704353100200210ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_printer_s .B pappl_printer_t; .PP .I typedef struct _pappl_system_s .B pappl_system_t; .PP .I void .br .BI papplPrinterAddLink "(pappl_printer_t *printer, const char *label, const char *path_or_url, bool secure);" .PP .I void .br .BI papplSystemAddLink "(pappl_system_t *system, const char *label, const char *path_or_url, bool secure);" .PP .I void .br .BI papplSystemAddResourceCallback "(pappl_system_t *system, const char *path, const char *format, pappl_resource_cb_t cb, void *data);" .PP .I void .br .BI papplSystemAddResourceData "(pappl_system_t *system, const char *path, const char *format, const void *data, size_t datalen);" .PP .I void .br .BI papplSystemAddResourceDirectory "(pappl_system_t *system, const char *basepath, const char *directory);" .PP .I void .br .BI papplSystemAddResourceFile "(pappl_system_t *system, const char *path, const char *format, const char *filename);" .PP .I void .br .BI papplSystemAddResourceString "(pappl_system_t *system, const char *path, const char *format, const char *data);" .PP .I void .br .BI papplSystemAddStringsData "(pappl_system_t *system, const char *path, const char *language, const char *data);" .PP .I void .br .BI papplSystemAddStringsFile "(pappl_system_t *system, const char *path, const char *language, const char *filename);" .PP .I void .br .BI papplSystemRemoveResource "(pappl_system_t *system, const char *path);" .SH DESCRIPTION The .B PAPPL resource functions manage resource files, callbacks, and links in the printer application. pappl-1.4.9/man/pappl-resource.3000066400000000000000000000212621476704353100164560ustar00rootroot00000000000000.TH pappl-resource 3 "pappl resource functions" "2025-03-20" "pappl resource functions" .SH NAME pappl-resource \- pappl resource functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_printer_s .B pappl_printer_t; .PP .I typedef struct _pappl_system_s .B pappl_system_t; .PP .I void .br .BI papplPrinterAddLink "(pappl_printer_t *printer, const char *label, const char *path_or_url, bool secure);" .PP .I void .br .BI papplSystemAddLink "(pappl_system_t *system, const char *label, const char *path_or_url, bool secure);" .PP .I void .br .BI papplSystemAddResourceCallback "(pappl_system_t *system, const char *path, const char *format, pappl_resource_cb_t cb, void *data);" .PP .I void .br .BI papplSystemAddResourceData "(pappl_system_t *system, const char *path, const char *format, const void *data, size_t datalen);" .PP .I void .br .BI papplSystemAddResourceDirectory "(pappl_system_t *system, const char *basepath, const char *directory);" .PP .I void .br .BI papplSystemAddResourceFile "(pappl_system_t *system, const char *path, const char *format, const char *filename);" .PP .I void .br .BI papplSystemAddResourceString "(pappl_system_t *system, const char *path, const char *format, const char *data);" .PP .I void .br .BI papplSystemAddStringsData "(pappl_system_t *system, const char *path, const char *language, const char *data);" .PP .I void .br .BI papplSystemAddStringsFile "(pappl_system_t *system, const char *path, const char *language, const char *filename);" .PP .I void .br .BI papplSystemRemoveResource "(pappl_system_t *system, const char *path);" .SH DESCRIPTION The .B PAPPL resource functions manage resource files, callbacks, and links in the printer application. .SH FUNCTIONS .SS papplPrinterAddLink Add a printer link to the navigation header. .PP .nf void papplPrinterAddLink ( pappl_printer_t *printer, const char *label, const char *path_or_url, pappl_loptions_t options ); .fi .PP This function adds a navigation link for a printer. The "path_or_url" argument specifies a absolute path such as "/ipp/print/example/page" or an absolute URL such as "https://www.example.com/". The "options" argument specifies where the link is shown and whether the link should redirect an absolute path to the secure ("https://.../path") web interface. .SS papplPrinterRemoveLink Remove a printer link from the navigation header. .PP .nf void papplPrinterRemoveLink ( pappl_printer_t *printer, const char *label ); .fi .PP This function removes the named link for the printer. .SS papplSystemAddLink Add a link to the navigation header. .PP .nf void papplSystemAddLink ( pappl_system_t *system, const char *label, const char *path_or_url, pappl_loptions_t options ); .fi .PP This function adds a navigation link for the system. The "path_or_url" argument specifies a absolute path such as "/page" or an absolute URL such as "https://www.example.com/". The "options" argument specifies where the link is shown and whether the link should redirect an absolute path to the secure ("https://.../path") web interface. .SS papplSystemAddResourceCallback Add a dynamic resource that uses a callback function. .PP .nf void papplSystemAddResourceCallback ( pappl_system_t *system, const char *path, const char *format, pappl_resource_cb_t cb, void *data ); .fi .PP This function adds a dynamic resource at the specified path. When a client GET or POST request is received at the specified path, the "cb" function will be called with the client pointer and "data" pointer to respond to it. .PP Resource callbacks are most often used to implement custom web pages. .PP .IP 5 Note: Any custom web page that is added prior to calling the .IP 5 \fIpapplSystemRun\fR function will replace the corresponding standard web .IP 5 page at the same path. .SS papplSystemAddResourceData Add a static data resource. .PP .nf void papplSystemAddResourceData ( pappl_system_t *system, const char *path, const char *format, const void *data, size_t datalen ); .fi .PP This function adds a static resource at the specified path. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemAddResourceDirectory Add external files in a directory as resources. .PP .nf void papplSystemAddResourceDirectory ( pappl_system_t *system, const char *basepath, const char *directory ); .fi .PP This function adds static resources from the specified directory under the specified path. The directory is scanned and only those files present at the time of the call are available, and those files must remain stable for as long as the resources are added to the system.. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemAddResourceFile Add an external file as a resource. .PP .nf void papplSystemAddResourceFile ( pappl_system_t *system, const char *path, const char *format, const char *filename ); .fi .PP This function adds a static resource at the specified path. The provided file is not copied to the resource and must remain stable for as long as the resource is added to the system. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemAddResourceString Add a static data resource as a C string. .PP .nf void papplSystemAddResourceString ( pappl_system_t *system, const char *path, const char *format, const char *data ); .fi .PP This function adds a static resource at the specified path. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemAddStringsData Add a static localization file resource. .PP .nf void papplSystemAddStringsData ( pappl_system_t *system, const char *path, const char *language, const char *data ); .fi .PP This function adds a static localization resource at the specified path. Localization files use the NeXTStep strings ("text/strings") format defined in PWG Candidate Standard 5100.13-2013. The provided data is not copied to the resource and must remain stable for as long as the resource is added to the system. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemAddStringsFile Add an external localization file resource. .PP .nf void papplSystemAddStringsFile ( pappl_system_t *system, const char *path, const char *language, const char *filename ); .fi .PP This function adds a static localization resource at the specified path. Localization files use the NeXTStep strings ("text/strings") format defined in PWG Candidate Standard 5100.13-2013. The provided file is not copied to the resource and must remain stable for as long as the resource is added to the system. .PP .IP 5 Note: Any resource that is added prior to calling the \fIpapplSystemRun\fR .IP 5 function will replace the corresponding standard resource at the same path. .SS papplSystemRemoveLink Remove a link from the navigation header. .PP .nf void papplSystemRemoveLink ( pappl_system_t *system, const char *label ); .fi .PP This function removes the named link for the system. .SS papplSystemRemoveResource Remove a resource at the specified path. .PP .nf void papplSystemRemoveResource ( pappl_system_t *system, const char *path ); .fi .PP This function removes a resource at the specified path. .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl-system-body.man000066400000000000000000000152671476704353100175270ustar00rootroot00000000000000.SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_system_s .B pappl_system_t; .PP .I bool .br .BI papplSystemAddListeners "(pappl_system_t *system, const char *name);" .PP .I void .br .BI papplSystemAddMIMEFilter "(pappl_system_t *system, const char *srctype, const char *dsttype, pappl_mime_filter_cb_t cb, void *data);" .PP .I void .br .BI papplSystemCleanJobs "(pappl_system_t *system);" .PP .I pappl_system_t * .br .BI papplSystemCreate "(pappl_soptions_t options, const char *name, int port, const char *subtypes, const char *spooldir, const char *logfile, pappl_loglevel_t loglevel, const char *auth_service, bool tls_only);" .PP .I void .br .BI papplSystemDelete "(pappl_system_t *system);" .PP .I pappl_printer_t * .br .BI papplSystemFindPrinter "(pappl_system_t *system, const char *resource, int printer_id, const char *device_uri);" .PP .I char * .br .BI papplSystemGetAdminGroup "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I const char * .br .BI papplSystemGetAuthService "(pappl_system_t *system);" .PP .I pappl_contact_t * .br .BI papplSystemGetContact "(pappl_system_t *system, pappl_contact_t *contact);" .PP .I int .br .BI papplSystemGetDefaultPrinterID "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetDefaultPrintGroup "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetDNSSDName "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I const char * .br .BI papplSystemGetFooterHTML "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetGeoLocation "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetHostname "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetLocation "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I pappl_loglevel_t .br .BI papplSystemGetLogLevel "(pappl_system_t *system);" .PP .I size_t .br .BI papplSystemGetMaxLogSize "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetName "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I int .br .BI papplSystemGetNextPrinterID "(pappl_system_t *system);" .PP .I pappl_soptions_t .br .BI papplSystemGetOptions "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetOrganization "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetOrganizationalUnit "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetPassword "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I int .br .BI papplSystemGetPort "(pappl_system_t *system);" .PP .I const char * .br .BI papplSystemGetServerHeader "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetSessionKey "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I bool .br .BI papplSystemGetTLSOnly "(pappl_system_t *system);" .PP .I const char * .br .BI papplSystemGetUUID "(pappl_system_t *system);" .PP .I int .br .BI papplSystemGetVersions "(pappl_system_t *system, int max_versions, pappl_version_t *versions);" .PP .I char * .br .BI papplSystemHashPassword "(pappl_system_t *system, const char *salt, const char *password, char *buffer, size_t bufsize);" .PP .I bool .br .BI papplSystemIsRunning "(pappl_system_t *system);" .PP .I bool .br .BI papplSystemIsShutdown "(pappl_system_t *system);" .PP .I void .br .BI papplSystemIteratePrinters "(pappl_system_t *system, pappl_printer_cb_t cb, void *data);" .PP .I bool .br .BI papplSystemLoadState "(pappl_system_t *system, const char *filename);" .PP .I const char * .br .BI papplSystemMatchDriver "(pappl_system_t *system, const char *device_id);" .PP .I void .br .BI papplSystemRemoveResource "(pappl_system_t *system, const char *path);" .PP .I void .br .BI papplSystemRun "(pappl_system_t *system);" .PP .I bool .br .BI papplSystemSaveState "(pappl_system_t *system, const char *filename);" .PP .I void .br .BI papplSystemSetAdminGroup "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetContact "(pappl_system_t *system, pappl_contact_t *contact);" .PP .I void .br .BI papplSystemSetDefaultPrinterID "(pappl_system_t *system, int default_printer_id);" .PP .I void .br .BI papplSystemSetDefaultPrintGroup "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetDrivers "(pappl_system_t *system, int num_drivers, pappl_driver_t *drivers, pappl_driver_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetDNSSDName "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetFooterHTML "(pappl_system_t *system, const char *html);" .PP .I void .br .BI papplSystemSetGeoLocation "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetHostname "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetLocation "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetLogLevel "(pappl_system_t *system, pappl_loglevel_t loglevel);" .PP .I void .br .BI papplSystemSetMaxLogSize "(pappl_system_t *system, size_t maxSize);" .PP .I void .br .BI papplSystemSetMIMECallback "(pappl_system_t *system, pappl_mime_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetNextPrinterID "(pappl_system_t *system, int next_printer_id);" .PP .I void .br .BI papplSystemSetOperationCallback "(pappl_system_t *system, pappl_ipp_op_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetOrganization "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetOrganizationalUnit "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetPassword "(pappl_system_t *system, const char *hash);" .PP .I void .br .BI papplSystemSetSaveCallback "(pappl_system_t *system, pappl_save_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetUUID "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetVersions "(pappl_system_t *system, int num_versions, pappl_version_t *versions);" .PP .I void .br .BI papplSystemShutdown "(pappl_system_t *system);" .SH DESCRIPTION The .B PAPPL system functions provide access to the system object. System are created and deleted by the printer application while the life cycle of the .B pappl_system_t object is managed automatically for the printer application. The .B papplSystemCreate function creates a new system while the .B papplSystemDelete function deletes a system. .PP The .B papplSystemRun function starts a system while the .B papplSystemShutdown function stops a running system. .PP The .B papplSystemGet functions get the current values associated with a system while the .B papplSystemSet functions set the current values associated with a system. pappl-1.4.9/man/pappl-system.3000066400000000000000000001256261476704353100161640ustar00rootroot00000000000000.TH pappl-system 3 "pappl system functions" "2025-03-20" "pappl system functions" .SH NAME pappl-system \- pappl system functions .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .PP .I typedef struct _pappl_system_s .B pappl_system_t; .PP .I bool .br .BI papplSystemAddListeners "(pappl_system_t *system, const char *name);" .PP .I void .br .BI papplSystemAddMIMEFilter "(pappl_system_t *system, const char *srctype, const char *dsttype, pappl_mime_filter_cb_t cb, void *data);" .PP .I void .br .BI papplSystemCleanJobs "(pappl_system_t *system);" .PP .I pappl_system_t * .br .BI papplSystemCreate "(pappl_soptions_t options, const char *name, int port, const char *subtypes, const char *spooldir, const char *logfile, pappl_loglevel_t loglevel, const char *auth_service, bool tls_only);" .PP .I void .br .BI papplSystemDelete "(pappl_system_t *system);" .PP .I pappl_printer_t * .br .BI papplSystemFindPrinter "(pappl_system_t *system, const char *resource, int printer_id, const char *device_uri);" .PP .I char * .br .BI papplSystemGetAdminGroup "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I const char * .br .BI papplSystemGetAuthService "(pappl_system_t *system);" .PP .I pappl_contact_t * .br .BI papplSystemGetContact "(pappl_system_t *system, pappl_contact_t *contact);" .PP .I int .br .BI papplSystemGetDefaultPrinterID "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetDefaultPrintGroup "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetDNSSDName "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I const char * .br .BI papplSystemGetFooterHTML "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetGeoLocation "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetHostname "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetLocation "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I pappl_loglevel_t .br .BI papplSystemGetLogLevel "(pappl_system_t *system);" .PP .I size_t .br .BI papplSystemGetMaxLogSize "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetName "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I int .br .BI papplSystemGetNextPrinterID "(pappl_system_t *system);" .PP .I pappl_soptions_t .br .BI papplSystemGetOptions "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetOrganization "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetOrganizationalUnit "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I char * .br .BI papplSystemGetPassword "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I int .br .BI papplSystemGetPort "(pappl_system_t *system);" .PP .I const char * .br .BI papplSystemGetServerHeader "(pappl_system_t *system);" .PP .I char * .br .BI papplSystemGetSessionKey "(pappl_system_t *system, char *buffer, size_t bufsize);" .PP .I bool .br .BI papplSystemGetTLSOnly "(pappl_system_t *system);" .PP .I const char * .br .BI papplSystemGetUUID "(pappl_system_t *system);" .PP .I int .br .BI papplSystemGetVersions "(pappl_system_t *system, int max_versions, pappl_version_t *versions);" .PP .I char * .br .BI papplSystemHashPassword "(pappl_system_t *system, const char *salt, const char *password, char *buffer, size_t bufsize);" .PP .I bool .br .BI papplSystemIsRunning "(pappl_system_t *system);" .PP .I bool .br .BI papplSystemIsShutdown "(pappl_system_t *system);" .PP .I void .br .BI papplSystemIteratePrinters "(pappl_system_t *system, pappl_printer_cb_t cb, void *data);" .PP .I bool .br .BI papplSystemLoadState "(pappl_system_t *system, const char *filename);" .PP .I const char * .br .BI papplSystemMatchDriver "(pappl_system_t *system, const char *device_id);" .PP .I void .br .BI papplSystemRemoveResource "(pappl_system_t *system, const char *path);" .PP .I void .br .BI papplSystemRun "(pappl_system_t *system);" .PP .I bool .br .BI papplSystemSaveState "(pappl_system_t *system, const char *filename);" .PP .I void .br .BI papplSystemSetAdminGroup "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetContact "(pappl_system_t *system, pappl_contact_t *contact);" .PP .I void .br .BI papplSystemSetDefaultPrinterID "(pappl_system_t *system, int default_printer_id);" .PP .I void .br .BI papplSystemSetDefaultPrintGroup "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetDrivers "(pappl_system_t *system, int num_drivers, pappl_driver_t *drivers, pappl_driver_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetDNSSDName "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetFooterHTML "(pappl_system_t *system, const char *html);" .PP .I void .br .BI papplSystemSetGeoLocation "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetHostname "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetLocation "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetLogLevel "(pappl_system_t *system, pappl_loglevel_t loglevel);" .PP .I void .br .BI papplSystemSetMaxLogSize "(pappl_system_t *system, size_t maxSize);" .PP .I void .br .BI papplSystemSetMIMECallback "(pappl_system_t *system, pappl_mime_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetNextPrinterID "(pappl_system_t *system, int next_printer_id);" .PP .I void .br .BI papplSystemSetOperationCallback "(pappl_system_t *system, pappl_ipp_op_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetOrganization "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetOrganizationalUnit "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetPassword "(pappl_system_t *system, const char *hash);" .PP .I void .br .BI papplSystemSetSaveCallback "(pappl_system_t *system, pappl_save_cb_t cb, void *data);" .PP .I void .br .BI papplSystemSetUUID "(pappl_system_t *system, const char *value);" .PP .I void .br .BI papplSystemSetVersions "(pappl_system_t *system, int num_versions, pappl_version_t *versions);" .PP .I void .br .BI papplSystemShutdown "(pappl_system_t *system);" .SH DESCRIPTION The .B PAPPL system functions provide access to the system object. System are created and deleted by the printer application while the life cycle of the .B pappl_system_t object is managed automatically for the printer application. The .B papplSystemCreate function creates a new system while the .B papplSystemDelete function deletes a system. .PP The .B papplSystemRun function starts a system while the .B papplSystemShutdown function stops a running system. .PP The .B papplSystemGet functions get the current values associated with a system while the .B papplSystemSet functions set the current values associated with a system. .SH ENUMERATIONS .SS pappl_netconf_e Network configuration mode .TP 5 PAPPL_NETCONF_DHCP .br Full DHCP .TP 5 PAPPL_NETCONF_DHCP_MANUAL .br DHCP with manual IP address .TP 5 PAPPL_NETCONF_MANUAL .br Manual IP, netmask, and router .TP 5 PAPPL_NETCONF_OFF .br Turn network interface off .SS pappl_soptions_e System option bits .TP 5 PAPPL_SOPTIONS_DNSSD_HOST .br Use hostname in DNS-SD service names instead of serial number/UUID .TP 5 PAPPL_SOPTIONS_MULTI_QUEUE .br Support multiple printers .TP 5 PAPPL_SOPTIONS_NONE .br No options .TP 5 PAPPL_SOPTIONS_NO_TLS .br Disable TLS support .TP 5 PAPPL_SOPTIONS_RAW_SOCKET .br Accept jobs via raw sockets .TP 5 PAPPL_SOPTIONS_USB_PRINTER .br Accept jobs via USB for default printer (embedded Linux only) .TP 5 PAPPL_SOPTIONS_WEB_INTERFACE .br Enable the standard web pages .TP 5 PAPPL_SOPTIONS_WEB_LOG .br Enable the log file page .TP 5 PAPPL_SOPTIONS_WEB_NETWORK .br Enable the network settings page .TP 5 PAPPL_SOPTIONS_WEB_REMOTE .br Allow remote queue management (vs. localhost only) .TP 5 PAPPL_SOPTIONS_WEB_SECURITY .br Enable the user/password settings page .TP 5 PAPPL_SOPTIONS_WEB_TLS .br Enable the TLS settings page .SS pappl_wifi_state_e "printer-wifi-state" values .TP 5 PAPPL_WIFI_STATE_CANNOT_JOIN .br \'cannot-join' .TP 5 PAPPL_WIFI_STATE_JOINING .br \'joining' .TP 5 PAPPL_WIFI_STATE_NOT_CONFIGURED .br \'not-configured' .TP 5 PAPPL_WIFI_STATE_NOT_VISIBLE .br \'not-visible' .TP 5 PAPPL_WIFI_STATE_OFF .br \'off' .TP 5 PAPPL_WIFI_STATE_ON .br \'on' .SH FUNCTIONS .SS papplSystemAddEvent Add a notification event. .PP .nf void papplSystemAddEvent ( pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, const char *message, ... ); .fi .SS papplSystemAddListeners Add network or domain socket listeners. .PP .nf bool papplSystemAddListeners ( pappl_system_t *system, const char *name ); .fi .PP This function adds socket listeners. The "name" parameter specifies the listener address. Names starting with a slash (/) specify a UNIX domain socket path, otherwise the name is treated as a fully-qualified domain name or numeric IPv4 or IPv6 address. If name is \fBNULL\fR, the "any" addresses are used ("0.0.0.0" and "[::]"). .PP Listeners cannot be added after \fIpapplSystemRun\fR is called. .SS papplSystemAddMIMEFilter Add a file filter to the system. .PP .nf void papplSystemAddMIMEFilter ( pappl_system_t *system, const char *srctype, const char *dsttype, pappl_mime_filter_cb_t cb, void *data ); .fi .PP This function adds a file filter to the system to be used for processing different kinds of document data in print jobs. The "srctype" and "dsttype" arguments specify the source and destination MIME media types as constant strings. A destination MIME media type of "image/pwg-raster" specifies a filter that uses the driver's raster interface. Other destination types imply direct submission to the output device using the \fBpapplDeviceXxx\fR functions. .PP .IP 5 Note: This function may not be called while the system is running. .SS papplSystemAddTimerCallback Add a timer callback to a system. .PP .nf bool papplSystemAddTimerCallback ( pappl_system_t *system, time_t start, int interval, pappl_timer_cb_t cb, void *cb_data ); .fi .PP This function schedules a function that will be called on the main run loop thread at the specified time and optionally every "interval" seconds thereafter. The timing accuracy is typically within a few milliseconds but is not guaranteed. Since the callback is run on the main run loop thread, functions should create a new thread for any long-running operations. .PP The callback function receives the "system" and "cb_data" pointers and returns \fBtrue\fR to repeat the timer or \fBfalse\fR to remove it: .PP .nf bool my_timer_cb(pappl_system_t *system, void *cb_data) { ... do periodic task ... return (true); // repeat the timer } .fi .SS papplSystemCreate Create a system object. .PP .nf pappl_system_t * papplSystemCreate ( pappl_soptions_t options, const char *name, int port, const char *subtypes, const char *spooldir, const char *logfile, pappl_loglevel_t loglevel, const char *auth_service, bool tls_only ); .fi .PP This function creates a new system object, which is responsible for managing all the printers, jobs, and resources used by the printer application. .PP The "options" argument specifies which options are enabled for the server: .PP .IP \(bu 5 \fBPAPPL_SOPTIONS_NONE\fR: No options. .IP \(bu 5 \fBPAPPL_SOPTIONS_DNSSD_HOST\fR: When resolving DNS-SD service name collisions, use the DNS-SD hostname instead of a serial number or UUID. .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_LOG\fR: Include the log file web page. .IP \(bu 5 \fBPAPPL_SOPTIONS_MULTI_QUEUE\fR: Support multiple printers. .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_NETWORK\fR: Include the network settings web page. .IP \(bu 5 \fBPAPPL_SOPTIONS_RAW_SOCKET\fR: Accept jobs via raw sockets starting on port 9100 (all but Windows). .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_REMOTE\fR: Allow remote queue management. .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_SECURITY\fR: Include the security settings web page. .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_INTERFACE\fR: Include the standard printer and job monitoring web pages. .IP \(bu 5 \fBPAPPL_SOPTIONS_WEB_TLS\fR: Include the TLS settings page. .IP \(bu 5 \fBPAPPL_SOPTIONS_USB_PRINTER\fR: Accept jobs via USB for the default printer (embedded Linux only). .PP The "name" argument specifies a human-readable name for the system. .PP The "port" argument specifies the port number to bind to. A value of \fB0\fR will cause an available port number to be assigned when the first listener is added with the \fIpapplSystemAddListeners\fR function. .PP The "subtypes" argument specifies one or more comma-delimited DNS-SD service sub-types such as "_print" and "_universal". .PP The "spooldir" argument specifies the location of job files. If \fBNULL\fR, a temporary directory is created. .PP The "logfile" argument specifies where to send log messages. If \fBNULL\fR, the log messages are written to a temporary file. .PP The "loglevel" argument specifies the initial logging level. .PP The "auth_service" argument specifies a PAM authentication service name. If \fBNULL\fR, no user authentication will be provided. .PP The "tls_only" argument controls whether the printer application will accept unencrypted connections. In general, this argument should always be \fBfalse\fR (allow unencrypted connections) since not all clients support encrypted printing. .SS papplSystemCreatePrinters Create newly discovered printers. .PP .nf bool papplSystemCreatePrinters ( pappl_system_t *system, pappl_devtype_t types, pappl_pr_create_cb_t cb, void *cb_data ); .fi .PP This function lists all devices specified by "types" and attempts to add any new printers that are found. The callback function "cb" is invoked for each printer that is added. .SS papplSystemDelete Delete a system object. .PP .nf void papplSystemDelete ( pappl_system_t *system ); .fi .PP .IP 5 Note: A system object cannot be deleted while the system is running. .SS papplSystemFindLoc Find a localization for the given printer and language. .PP .nf pappl_loc_t * papplSystemFindLoc ( pappl_system_t *system, const char *language ); .fi .SS papplSystemFindPrinter Find a printer by resource, ID, or device URI. .PP .nf pappl_printer_t * papplSystemFindPrinter ( pappl_system_t *system, const char *resource, int printer_id, const char *device_uri ); .fi .PP This function finds a printer contained in the system using its resource path, unique integer identifier, or device URI. If none of these is specified, the current default printer is returned. .SS papplSystemFindSubscription Find a subscription. .PP .nf pappl_subscription_t * papplSystemFindSubscription ( pappl_system_t *system, int sub_id ); .fi .PP This function finds the numbered event notification subscription on a system. .SS papplSystemGetAdminGroup Get the current administrative group, if any. .PP .nf char * papplSystemGetAdminGroup ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current administrative group, if any, to the specified buffer. .SS papplSystemGetAuthService Get the PAM authorization service, if any. .PP .nf const char * papplSystemGetAuthService ( pappl_system_t *system ); .fi .PP This function returns the PAM authorization service being used by the system for authentication, if any. .SS papplSystemGetContact Get the "system-contact" value. .PP .nf pappl_contact_t * papplSystemGetContact ( pappl_system_t *system, pappl_contact_t *contact ); .fi .PP This function copies the current system contact information to the specified buffer. .SS papplSystemGetDNSSDName Get the current DNS-SD service name. .PP .nf char * papplSystemGetDNSSDName ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current DNS-SD service name of the system, if any, to the specified buffer. .SS papplSystemGetDefaultPrintGroup Get the default print group, if any. .PP .nf char * papplSystemGetDefaultPrintGroup ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current default print group, if any, to the specified buffer. .SS papplSystemGetDefaultPrinterID Get the current "default-printer-id" value. .PP .nf int papplSystemGetDefaultPrinterID ( pappl_system_t *system ); .fi .PP This function returns the positive integer identifier for the current default printer or \fB0\fR if there is no default printer. .SS papplSystemGetFooterHTML Get the footer HTML for the web interface, if any. .PP .nf const char * papplSystemGetFooterHTML ( pappl_system_t *system ); .fi .PP This function returns the HTML for the web page footer, if any. The footer HTML can be set using the \fIpapplSystemSetFooterHTML\fR function. .SS papplSystemGetGeoLocation Get the system geo-location string, if any. .PP .nf char * papplSystemGetGeoLocation ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current system geographic location as a "geo:" URI to the specified buffer. .SS papplSystemGetHostName Get the system hostname. .PP .nf char * papplSystemGetHostName ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current system hostname to the specified buffer. .SS papplSystemGetHostPort Get the port number for network connections to the system. .PP .nf int papplSystemGetHostPort ( pappl_system_t *system ); .fi .PP This function returns the port number that is used for network connections to the system. .SS papplSystemGetLocation Get the system location string, if any. .PP .nf char * papplSystemGetLocation ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current human-readable location, if any, to the specified buffer. .SS papplSystemGetLogLevel Get the system log level. .PP .nf pappl_loglevel_t papplSystemGetLogLevel ( pappl_system_t *system ); .fi .PP This function returns the current system log level as an enumeration. .SS papplSystemGetMaxClients Get the maximum number of clients. .PP .nf int papplSystemGetMaxClients ( pappl_system_t *system ); .fi .PP This function gets the maximum number of simultaneous clients that are allowed by the system. .SS papplSystemGetMaxImageSize Get the maximum supported size for images. .PP .nf size_t papplSystemGetMaxImageSize ( pappl_system_t *system, int *max_width, int *max_height ); .fi .PP This function retrieves the image size limits in bytes (uncompressed), columns, and lines. .SS papplSystemGetMaxLogSize Get the maximum log file size. .PP .nf size_t papplSystemGetMaxLogSize ( pappl_system_t *system ); .fi .PP This function gets the maximum log file size, which is only used when logging directly to a file. When the limit is reached, the current log file is renamed to "filename.O" and a new log file is created. Set the maximum size to \fB0\fR to disable log file rotation. .PP The default maximum log file size is 1MiB or \fB1048576\fR bytes. .SS papplSystemGetMaxSubscriptions Get the maximum number of event subscriptions. .PP .nf size_t papplSystemGetMaxSubscriptions ( pappl_system_t *system ); .fi .PP This function gets the maximum number of event subscriptions that are allowed. A maximum of \fB0\fR means there is no limit. .PP The default maximum number of event subscriptions is 100. .SS papplSystemGetName Get the system name. .PP .nf char * papplSystemGetName ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current system name to the specified buffer. .SS papplSystemGetNextPrinterID Get the next "printer-id" value. .PP .nf int papplSystemGetNextPrinterID ( pappl_system_t *system ); .fi .PP This function returns the positive integer identifier that will be used for the next printer that is created. .SS papplSystemGetOptions Get the system options. .PP .nf pappl_soptions_t papplSystemGetOptions ( pappl_system_t *system ); .fi .PP This function returns the system options as a bitfield. .SS papplSystemGetOrganization Get the system organization string, if any. .PP .nf char * papplSystemGetOrganization ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current organization name, if any, to the specified buffer. .SS papplSystemGetOrganizationalUnit Get the system organizational unit string, if any. .PP .nf char * papplSystemGetOrganizationalUnit ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current organizational unit name, if any, to the specified buffer. .SS papplSystemGetPassword Get the current web site access password. .PP .nf char * papplSystemGetPassword ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current web site password hash, if any, to the specified buffer. .PP Note: The access password is only used when the PAM authentication service is not set. .SS papplSystemGetServerHeader Get the Server: header for HTTP responses. .PP .nf const char * papplSystemGetServerHeader ( pappl_system_t *system ); .fi .PP This function returns the value of the HTTP "Server:" header that is used by the system. .SS papplSystemGetSessionKey Get the current session key. .PP .nf char * papplSystemGetSessionKey ( pappl_system_t *system, char *buffer, size_t bufsize ); .fi .PP This function copies the current session key to the specified buffer. The session key is used for web interface forms to provide CSRF protection and is refreshed periodically. .SS papplSystemGetTLSOnly Get the TLS-only state of the system. .PP .nf bool papplSystemGetTLSOnly ( pappl_system_t *system ); .fi .PP This function returns whether the system will only accept encrypted connections. .SS papplSystemGetUUID Get the "system-uuid" value. .PP .nf const char * papplSystemGetUUID ( pappl_system_t *system ); .fi .PP This function returns the system's UUID value. .SS papplSystemGetVersions Get the firmware names and versions. .PP .nf int papplSystemGetVersions ( pappl_system_t *system, int max_versions, pappl_version_t *versions ); .fi .PP This function copies the system firmware information to the specified buffer. The return value is always the number of firmware versions that have been set using the \fIpapplSystemSetVersions\fR function, regardless of the value of the "max_versions" argument. .SS papplSystemHashPassword Generate a password hash using salt and password strings. .PP .nf char * papplSystemHashPassword ( pappl_system_t *system, const char *salt, const char *password, char *buffer, size_t bufsize ); .fi .PP This function generates a password hash using the "salt" and "password" strings. The "salt" string should be \fBNULL\fR to generate a new password hash or the value of an existing password hash to verify that a given plaintext "password" string matches the password hash. .PP .IP 5 Note: Hashed access passwords are only used when the PAM authentication .IP 5 service is not set. .SS papplSystemIsRunning Return whether the system is running. .PP .nf bool papplSystemIsRunning ( pappl_system_t *system ); .fi .PP This function returns whether the system is running. .SS papplSystemIsShutdown Return whether the system has been shutdown. .PP .nf bool papplSystemIsShutdown ( pappl_system_t *system ); .fi .PP This function returns whether the system is shutdown or scheduled to shutdown. .SS papplSystemIteratePrinters Iterate all of the printers. .PP .nf void papplSystemIteratePrinters ( pappl_system_t *system, pappl_printer_cb_t cb, void *data ); .fi .PP This function iterates each of the printers managed by the system. The "cb" function is called once per printer with the "system" and "data" values. .SS papplSystemLoadState Load the previous system state. .PP .nf bool papplSystemLoadState ( pappl_system_t *system, const char *filename ); .fi .PP This function loads the previous system state from a file created by the \fIpapplSystemSaveState\fR function. The system state contains all of the system object values, the list of printers, and the jobs for each printer. .PP When loading a printer definition, if the printer cannot be created (e.g., because the driver name is no longer valid) then that printer and all of its job history will be lost. In the case of a bad driver name, a printer application's driver callback can perform any necessary mapping of the driver name, including the use its auto-add callback to find a compatible new driver. .PP .IP 5 Note: This function must be called prior to \fIpapplSystemRun\fR. .SS papplSystemMatchDriver .PP .nf const char * papplSystemMatchDriver ( pappl_system_t *system, const char *device_id ); .fi .SS papplSystemRemoveTimerCallback Remove a timer callback. .PP .nf void papplSystemRemoveTimerCallback ( pappl_system_t *system, pappl_timer_cb_t cb, void *cb_data ); .fi .PP This function removes all matching timer callbacks from the specified system. Both the callback function and data must match to remove a timer. .SS papplSystemRun Run the printer application. .PP .nf void papplSystemRun ( pappl_system_t *system ); .fi .PP This function runs the printer application, accepting new connections, handling requests, and processing jobs as needed. It returns once the system is shutdown, either through an IPP request or \fBSIGTERM\fR. .SS papplSystemSaveState Save the current system state. .PP .nf bool papplSystemSaveState ( pappl_system_t *system, const char *filename ); .fi .PP This function saves the current system state to a file. It is typically used with the \fIpapplSystemSetSaveCallback\fR function to periodically save the state: .PP .nf papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, (void *)filename); .fi .SS papplSystemSetAdminGroup Set the administrative group. .PP .nf void papplSystemSetAdminGroup ( pappl_system_t *system, const char *value ); .fi .PP This function sets the group name used for administrative requests such as adding or deleting a printer. .PP .IP 5 Note: The administrative group is only used when the PAM authorization .IP 5 service is also set when the system is created. .SS papplSystemSetAuthCallback Set an authentication callback for the specified scheme. .PP .nf void papplSystemSetAuthCallback ( pappl_system_t *system, const char *auth_scheme, pappl_auth_cb_t auth_cb, void *auth_cbdata ); .fi .PP This function sets the authentication callback that is used for Client requests. The authentication callback is used for every Client request containing the WWW-Authenticate header (\fBHTTP_FIELD_WWW_AUTHENTICATE\fR). The callback returns one of the following status codes: .PP .IP \(bu 5 \fBHTTP_STATUS_CONTINUE\fR if the authentication succeeded, .IP \(bu 5 \fBHTTP_STATUS_UNAUTHORIZED\fR if the authentication failed, or .IP \(bu 5 \fBHTTP_STATUS_FORBIDDEN\fR if the authentication succeeded but the user is not part of the specified group. .PP .IP 5 Note: The authentication callback can only be set prior to calling .IP 5 \fIpapplSystemRun\fR. .SS papplSystemSetContact Set the "system-contact" value. .PP .nf void papplSystemSetContact ( pappl_system_t *system, pappl_contact_t *contact ); .fi .PP This function sets the system contact value. .SS papplSystemSetDNSSDName Set the DNS-SD service name. .PP .nf void papplSystemSetDNSSDName ( pappl_system_t *system, const char *value ); .fi .PP This function sets the DNS-SD service name of the system. If \fBNULL\fR, the DNS-SD registration is removed. .SS papplSystemSetDefaultPrintGroup Set the default print group. .PP .nf void papplSystemSetDefaultPrintGroup ( pappl_system_t *system, const char *value ); .fi .PP This function sets the default group name used for print requests. .PP .IP 5 Note: The default print group is only used when the PAM authorization .IP 5 service is also set when the system is created. .SS papplSystemSetDefaultPrinterID Set the "default-printer-id" value. .PP .nf void papplSystemSetDefaultPrinterID ( pappl_system_t *system, int default_printer_id ); .fi .PP This function sets the default printer using its unique positive integer identifier. .SS papplSystemSetEventCallback Set a callback for monitoring system events. .PP .nf void papplSystemSetEventCallback ( pappl_system_t *system, pappl_event_cb_t event_cb, void *event_data ); .fi .PP This function sets a callback function to receive event notifications from the system. .SS papplSystemSetFooterHTML Set the footer HTML for the web interface. .PP .nf void papplSystemSetFooterHTML ( pappl_system_t *system, const char *html ); .fi .PP This function sets the footer HTML for the web interface. .PP .IP 5 Note: The footer HTML can only be set prior to calling .IP 5 \fIpapplSystemRun\fR. .SS papplSystemSetGeoLocation Set the geographic location string. .PP .nf void papplSystemSetGeoLocation ( pappl_system_t *system, const char *value ); .fi .PP This function sets the geographic location of the system as a "geo:" URI. If \fBNULL\fR, the location is cleared. .SS papplSystemSetHostName Set the system hostname. .PP .nf void papplSystemSetHostName ( pappl_system_t *system, const char *value ); .fi .PP This function sets the system hostname. If \fBNULL\fR, the default hostname is used. .SS papplSystemSetLocation Set the system location string, if any. .PP .nf void papplSystemSetLocation ( pappl_system_t *system, const char *value ); .fi .PP This function sets the human-readable location of the system. If \fBNULL\fR, the location is cleared. .SS papplSystemSetLogLevel Set the system log level .PP .nf void papplSystemSetLogLevel ( pappl_system_t *system, pappl_loglevel_t loglevel ); .fi .PP This function sets the log level as an enumeration. .SS papplSystemSetMIMECallback Set the MIME typing callback for the system. .PP .nf void papplSystemSetMIMECallback ( pappl_system_t *system, pappl_mime_cb_t cb, void *data ); .fi .PP This function sets a custom MIME typing callback for the system. The MIME typing callback extends the built-in MIME typing support for other media types that are supported by the application, typically vendor print formats. .PP The callback function receives a buffer containing the initial bytes of the document data, the length of the buffer, and the callback data. It can then return \fBNULL\fR if the content is not recognized or a constant string containing the MIME media type, for example "application/vnd.hp-pcl" for HP PCL print data. .SS papplSystemSetMaxClients Set the maximum number of clients. .PP .nf void papplSystemSetMaxClients ( pappl_system_t *system, int max_clients ); .fi .PP This function sets the maximum number of simultaneous clients that are allowed by the system from 0 (auto) to 32768 (half of the available TCP port numbers). .PP The default maximum number of clients is based on available system resources. .SS papplSystemSetMaxImageSize Set the maximum allowed JPEG/PNG image sizes. .PP .nf void papplSystemSetMaxImageSize ( pappl_system_t *system, size_t max_size, int max_width, int max_height ); .fi .PP This function sets the maximum size allowed for JPEG and PNG images. The default limits are 16384x16384 and 1/10th the maximum memory the current process can use or 1GiB, whichever is less. .SS papplSystemSetMaxLogSize Set the maximum log file size in bytes. .PP .nf void papplSystemSetMaxLogSize ( pappl_system_t *system, size_t maxsize ); .fi .PP This function sets the maximum log file size in bytes, which is only used when logging directly to a file. When the limit is reached, the current log file is renamed to "filename.O" and a new log file is created. Set the maximum size to \fB0\fR to disable log file rotation. .PP The default maximum log file size is 1MiB or \fB1048576\fR bytes. .SS papplSystemSetMaxSubscriptions Set the maximum number of event subscriptions. .PP .nf void papplSystemSetMaxSubscriptions ( pappl_system_t *system, size_t max_subscriptions ); .fi .PP This function Sets the maximum number of event subscriptions that are allowed. A maximum of \fB0\fR means there is no limit. .PP The default maximum number of event subscriptions is \fB100\fR. .SS papplSystemSetNetworkCallbacks Set the network configuration callbacks. .PP .nf void papplSystemSetNetworkCallbacks ( pappl_system_t *system, pappl_network_get_cb_t get_cb, pappl_network_set_cb_t set_cb, void *cb_data ); .fi .PP This function sets the network configuration callbacks for a system. The "get" callback reads the configuration of all network interfaces and stores them in an array of \fIpappl_network_t\fR structures that is passed to the callback. The "set" callback writes the configuration of all network interfaces and returns a boolean value indicating whether the configuration has been written successfully. .SS papplSystemSetNextPrinterID Set the next "printer-id" value. .PP .nf void papplSystemSetNextPrinterID ( pappl_system_t *system, int next_printer_id ); .fi .PP This function sets the unique positive integer identifier that will be used for the next printer that is created. It is typically only called as part of restoring the state of a system. .PP .IP 5 Note: The next printer ID can only be set prior to calling .IP 5 \fIpapplSystemRun\fR. .SS papplSystemSetOperationCallback Set the IPP operation callback. .PP .nf void papplSystemSetOperationCallback ( pappl_system_t *system, pappl_ipp_op_cb_t cb, void *data ); .fi .PP This function sets a custom IPP operation handler for the system that is called for any IPP operations that are not handled by the built-in IPP services. .PP .IP 5 Note: The operation callback can only be set prior to calling .IP 5 \fIpapplSystemRun\fR. .SS papplSystemSetOrganization Set the system organization string, if any. .PP .nf void papplSystemSetOrganization ( pappl_system_t *system, const char *value ); .fi .PP This function sets the organization name for the system. If \fBNULL\fR, the name is cleared. .SS papplSystemSetOrganizationalUnit Set the system organizational unit string, if any. .PP .nf void papplSystemSetOrganizationalUnit ( pappl_system_t *system, const char *value ); .fi .PP This function sets the organizational unit name for the system. If \fBNULL\fR, the name is cleared. .SS papplSystemSetPassword Set the access password hash string. .PP .nf void papplSystemSetPassword ( pappl_system_t *system, const char *hash ); .fi .PP This function sets the hash for the web access password. The hash string is generated using the \fIpapplSystemHashPassword\fR function. .PP .IP 5 Note: The access password is only used when the PAM authentication service .IP 5 is not set. .SS papplSystemSetPrinterDrivers Set the list of drivers and the driver callbacks. .PP .nf void papplSystemSetPrinterDrivers ( pappl_system_t *system, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_create_cb_t create_cb, pappl_pr_driver_cb_t driver_cb, void *data ); .fi .PP This function sets the lists of printer drivers, the optional auto-add callback function, the optional creation callback, and the required driver initialization callback function. .PP The auto-add callback ("autoadd_cb") finds a compatible driver name for the specified printer. It is used when the client or user specifies the "auto" driver name, and for the "autoadd" sub-command for the \fBpapplMainloop\fR API. .PP The creation callback ("create_cb") is called at the end of printer creation to make any common changes or additions to a new printer. It is typically used to add extra web pages, add per-printer static resources, and/or initialize the contact and location information. .PP The driver initialization callback ("driver_cb") is called to initialize the \fBpappl_pr_driver_data_t\fR structure, which provides all of the printer capabilities and callbacks for printing. .SS papplSystemSetSaveCallback Set the save callback. .PP .nf void papplSystemSetSaveCallback ( pappl_system_t *system, pappl_save_cb_t cb, void *data ); .fi .PP This function sets a callback that is used to periodically save the current system state. Typically the callback function ("cb") is \fIpapplSystemSaveState\fR and the callback data ("data") is the name of the state file: .PP .nf papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, (void *)filename); .fi .IP 5 Note: The save callback can only be set prior to calling .IP 5 \fIpapplSystemRun\fR. .SS papplSystemSetUUID Set the system UUID. .PP .nf void papplSystemSetUUID ( pappl_system_t *system, const char *value ); .fi .PP This function sets the system UUID value, overriding the default (generated) value. It is typically used when restoring the state of a previous incarnation of the system. .PP .IP 5 Note: The UUID can only be set prior to calling \fIpapplSystemRun\fR. .SS papplSystemSetVersions Set the firmware names and versions. .PP .nf void papplSystemSetVersions ( pappl_system_t *system, int num_versions, pappl_version_t *versions ); .fi .PP This function sets the names and versions of each firmware/software component of the printer application. .SS papplSystemSetWiFiCallbacks Set Wi-Fi callbacks. .PP .nf void papplSystemSetWiFiCallbacks ( pappl_system_t *system, pappl_wifi_join_cb_t join_cb, pappl_wifi_list_cb_t list_cb, pappl_wifi_status_cb_t status_cb, void *data ); .fi .PP This function sets the 802.11 Wi-Fi interface callbacks for the system. The "join_cb" is used to join a Wi-Fi network, the "list_cb" is used to list available networks, and the "status_cb" is used to query the current Wi-Fi network connection status and Secure Set Identifier (SSID). The "join_cb" and "status_cb" functions are used to support getting and setting the IPP "printer-wifi-state", "printer-wifi-ssid", and "printer-wifi-password" attributes, while the "list_cb" function enables changing the Wi-Fi network from the network web interface, if enabled. .PP Note: The Wi-Fi callbacks can only be set prior to calling \fIpapplSystemRun\fR. .SS papplSystemShutdown Shutdown the system. .PP .nf void papplSystemShutdown ( pappl_system_t *system ); .fi .PP This function tells the system to perform an orderly shutdown of all printers and to terminate the main loop. .SH STRUCTURES .SS pappl_network_s Network interface information .PP .nf struct pappl_network_s { http_addr_t addr4; http_addr_t addr6; pappl_netconf_t config4; pappl_netconf_t config6; http_addr_t dns[2]; char domain[64]; http_addr_t gateway4; http_addr_t gateway6; char ident[256]; http_addr_t linkaddr6; http_addr_t mask4; char name[64]; unsigned prefix6; bool up; }; .fi .SS pappl_pr_driver_s Printer driver information .PP .nf struct pappl_pr_driver_s { const char *description; const char *device_id; void *extension; const char *name; }; .fi .SS pappl_version_s Firmware version information .PP .nf struct pappl_version_s { char name[64]; char patches[64]; char sversion[64]; unsigned short version[4]; }; .fi .SS pappl_wifi_s Wi-Fi status/configuration information .PP .nf struct pappl_wifi_s { char ssid[128]; pappl_wifi_state_t state; }; .fi .SH TYPES .SS pappl_auth_cb_t Authentication callback .PP .nf typedef http_status_t (*pappl_auth_cb_t)(pappl_client_t *client, const char *group, gid_t groupid, void *cb_data); .fi .SS pappl_ipp_op_cb_t IPP operation callback function .PP .nf typedef bool (*pappl_ipp_op_cb_t)(pappl_client_t *client, void *data); .fi .SS pappl_mime_cb_t MIME typing callback function .PP .nf typedef const char * (*pappl_mime_cb_t)(const unsigned char *header, size_t headersize, void *data); .fi .SS pappl_mime_filter_cb_t Filter callback function .PP .nf typedef bool (*pappl_mime_filter_cb_t)(pappl_job_t *job, pappl_device_t *device, void *data); .fi .SS pappl_netconf_t Network configuration mode .PP .nf typedef enum pappl_netconf_e pappl_netconf_t; .fi .SS pappl_network_get_cb_t Get networks callback .PP .nf typedef size_t (*pappl_network_get_cb_t)(pappl_system_t *system, void *cb_data, size_t max_networks, pappl_network_t *networks); .fi .SS pappl_network_set_cb_t Set networks callback .PP .nf typedef bool (*pappl_network_set_cb_t)(pappl_system_t *system, void *cb_data, size_t num_networks, pappl_network_t *networks); .fi .SS pappl_network_t Network interface information .PP .nf typedef struct pappl_network_s pappl_network_t; .fi .SS pappl_pr_autoadd_cb_t Auto-add callback .PP .nf typedef const char * (*pappl_pr_autoadd_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data); .fi .SS pappl_pr_create_cb_t Printer creation callback .PP .nf typedef void (*pappl_pr_create_cb_t)(pappl_printer_t *printer, void *data); .fi .SS pappl_pr_driver_cb_t Driver callback function .PP .nf typedef bool (*pappl_pr_driver_cb_t)(pappl_system_t *system, const char *driver_name, const char *device_uri, const char *device_id, pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data); .fi .SS pappl_pr_driver_t Printer driver information .PP .nf typedef struct pappl_pr_driver_s pappl_pr_driver_t; .fi .SS pappl_printer_cb_t Printer iterator callback function .PP .nf typedef void (*pappl_printer_cb_t)(pappl_printer_t *printer, void *data); .fi .SS pappl_resource_cb_t Dynamic resource callback function .PP .nf typedef bool (*pappl_resource_cb_t)(pappl_client_t *client, void *data); .fi .SS pappl_save_cb_t Save callback function .PP .nf typedef bool (*pappl_save_cb_t)(pappl_system_t *system, void *data); .fi .SS pappl_soptions_t Bitfield for system options .PP .nf typedef unsigned pappl_soptions_t; .fi .SS pappl_timer_cb_t Timer callback function .PP .nf typedef bool (*pappl_timer_cb_t)(pappl_system_t *system, void *cb_data); .fi .SS pappl_version_t Firmware version information .PP .nf typedef struct pappl_version_s pappl_version_t; .fi .SS pappl_wifi_join_cb_t Wi-Fi join callback .PP .nf typedef bool (*pappl_wifi_join_cb_t)(pappl_system_t *system, void *data, const char *ssid, const char *psk); .fi .SS pappl_wifi_list_cb_t Wi-Fi list callback .PP .nf typedef int (*pappl_wifi_list_cb_t)(pappl_system_t *system, void *data, cups_dest_t **ssids); .fi .SS pappl_wifi_state_t "printer-wifi-state" values .PP .nf typedef enum pappl_wifi_state_e pappl_wifi_state_t; .fi .SS pappl_wifi_status_cb_t Wi-Fi status callback .PP .nf typedef pappl_wifi_t * (*pappl_wifi_status_cb_t)(pappl_system_t *system, void *data, pappl_wifi_t *wifi_data); .fi .SS pappl_wifi_t Wi-Fi status/configuration information .PP .nf typedef struct pappl_wifi_s pappl_wifi_t; .fi .SH SEE ALSO .BR pappl (1), .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2022 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/man/pappl.1000066400000000000000000000044361476704353100146330ustar00rootroot00000000000000.\" .\" pappl man page .\" .\" Copyright © 2019-2020 by Michael R Sweet .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH pappl 1 "pappl" "2020-10-25" "Michael R Sweet" .SH NAME pappl \- printer application framework .SH LIBRARY Printer Application Framework (libpappl, "pkg-config --cflags --libs pappl") .SH SYNOPSIS .B #include .SH DESCRIPTION .B PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. It is sufficiently general purpose to support any kind of printer or driver that can be used on desktops, servers, and in embedded environments. .PP .B PAPPL embeds a multi-threaded HTTP / IPP Everywhere\[tm] server and provides callbacks for a variety of events that allows a GUI or command-line application to interact with both the local user that is running the Printer Application and any network clients that are submitting print jobs, querying printer status and capabilities, and so forth. .PP .B PAPPL provides a simple driver interface for raster graphics printing, and developers of CUPS Raster drivers will readily adapt to it. .B PAPPL can also be used with printers that support vector graphics printing although you'll have to develop more code to support them. Drivers provide configuration and capability information to .B PAPPL, and .B PAPPL then calls the driver to print things as needed. .B PAPPL automatically supports printing of JPEG, PNG, PWG Raster, Apple Raster, and "raw" files to printers connected via USB and network (AppSocket/JetDirect) connections. Other formats can be supported through "filter" callbacks you register. .SH SEE ALSO .BR pappl-client (3), .BR pappl-device (3), .BR pappl-job (3), .BR pappl-log (3), .BR pappl-mainline (3), .BR pappl-makeresheader (1), .BR pappl-printer (3), .BR pappl-resource (3), .BR pappl-system (3), https://www.msweet.org/pappl .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. .PP .B PAPPL is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used .I freely in any project you'd like. See the files "LICENSE" and "NOTICE" in the source distribution for more information. pappl-1.4.9/pappl.spec000066400000000000000000000047231476704353100146510ustar00rootroot00000000000000# # RPM spec file for the Printer Application Framework # # Copyright © 2020-2025 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # Summary: Printer Application Framework (PAPPL) Name: pappl Version: 1.4.9 Release: 1 License: Apache 2.0 Group: Development/Libraries Source: https://github.com/michaelrsweet/pappl/releases/download/release-%{version}/pappl-%{version}.tar.gz Url: https://www.msweet.org/pappl Packager: John Doe Vendor: Michael R Sweet BuildRequires: avahi-devel, cups-devel, gnutls-devel, libjpeg-turbo-devel, libpng-devel, libusbx-devel, pam-devel, zlib-devel Requires: cups-devel # Use buildroot so as not to disturb the version already installed BuildRoot: /var/tmp/%{name}-root %description PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. PAPPL supports JPEG, PNG, PWG Raster, Apple Raster, and "raw" printing to printers connected via USB and network (AppSocket/JetDirect) connections. PAPPL provides access to the printer via its embedded IPP Everywhere™ service, either local to the computer or on your whole network, which can then be discovered and used by any application. PAPPL is licensed under the Apache License Version 2.0 with an exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS), so it can be used freely in any project you'd like. %package devel Summary: PAPPL - development environment Requires: %{name} = %{version} %description devel This package provides the PAPPL headers and development environment. %prep %setup %build CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --enable-shared --prefix=/usr # If we got this far, all prerequisite libraries must be here. make %install # Make sure the RPM_BUILD_ROOT directory exists. rm -rf $RPM_BUILD_ROOT make BUILDROOT=$RPM_BUILD_ROOT install %clean rm -rf $RPM_BUILD_ROOT %post /sbin/ldconfig %postun /sbin/ldconfig %files %defattr(-,root,root) %dir /usr/lib /usr/lib/libpappl.so* %files devel %defattr(-,root,root) %dir /usr/bin /usr/bin/* %dir /usr/include/pappl /usr/include/pappl/*.h %dir /usr/lib /usr/lib/libpappl.a %dir /usr/lib/pkgconfig /usr/lib/pkgconfig/pappl.pc %dir /usr/share/doc/pappl /usr/share/doc/pappl/* %dir /usr/share/man/man1 /usr/share/man/man1/* %dir /usr/share/man/man3 /usr/share/man/man3/* %dir /usr/share/pappl /usr/share/pappl/* pappl-1.4.9/pappl/000077500000000000000000000000001476704353100137675ustar00rootroot00000000000000pappl-1.4.9/pappl/Dependencies000066400000000000000000000352031476704353100163030ustar00rootroot00000000000000client.o: client.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h client-accessors.o: client-accessors.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h client-auth.o: client-auth.c client-private.h base-private.h ../config.h \ base.h \ \ \ \ \ \ \ \ \ client.h log.h \ system-private.h dnssd-private.h subscription-private.h subscription.h \ system.h device.h client-loc.o: client-loc.c client-private.h base-private.h ../config.h \ base.h \ \ \ \ \ \ \ \ \ client.h log.h loc-private.h \ system-private.h dnssd-private.h subscription-private.h subscription.h \ system.h device.h printer-private.h printer.h loc.h client-ipp.o: client-ipp.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h client-webif.o: client-webif.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h contact.o: contact.c base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ device.o: device.c device-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ device.h printer.h device-file.o: device-file.c device-private.h base-private.h ../config.h \ base.h \ \ \ \ \ \ \ \ \ device.h device-network.o: device-network.c device-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ device.h dnssd-private.h \ snmp-private.h printer-private.h printer.h log.h device-usb.o: device-usb.c device-private.h base-private.h ../config.h \ base.h \ \ \ \ \ \ \ \ \ device.h printer.h \ dnssd.o: dnssd.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h httpmon.o: httpmon.c httpmon-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ job-accessors.o: job-accessors.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h job-filter.o: job-filter.c pappl.h device.h base.h \ \ \ \ \ \ \ \ \ \ system.h subscription.h \ log.h client.h printer.h job.h loc.h mainloop.h job-private.h \ base-private.h ../config.h system-private.h dnssd-private.h \ subscription-private.h \ \ \ job-ipp.o: job-ipp.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h job-process.o: job-process.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h job.o: job.c pappl-private.h client-private.h base-private.h ../config.h \ base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h link.o: link.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h loc.o: loc.c loc-private.h system-private.h dnssd-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ subscription-private.h \ subscription.h system.h device.h log.h printer-private.h printer.h \ loc.h strings/de_strings.h strings/en_strings.h strings/es_strings.h \ strings/fr_strings.h strings/it_strings.h strings/ja_strings.h \ strings/nb-NO_strings.h strings/pl_strings.h strings/tr_strings.h log.o: log.c client-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h job-private.h \ job.h log-private.h printer-private.h dnssd-private.h printer.h \ device.h system-private.h subscription-private.h subscription.h \ system.h lookup.o: lookup.c base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ mainloop.o: mainloop.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h mainloop-subcommands.o: mainloop-subcommands.c pappl-private.h \ client-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h mainloop-support.o: mainloop-support.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer.o: printer.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer-accessors.o: printer-accessors.c printer-private.h \ dnssd-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ printer.h log.h device.h \ job-private.h job.h system-private.h subscription-private.h \ subscription.h system.h printer-driver.o: printer-driver.c printer-private.h dnssd-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ printer.h log.h device.h \ system-private.h subscription-private.h subscription.h system.h printer-ipp.o: printer-ipp.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer-raw.o: printer-raw.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer-support.o: printer-support.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer-usb.o: printer-usb.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h printer-webif.o: printer-webif.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h resource.o: resource.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h snmp.o: snmp.c snmp-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ subscription.o: subscription.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h subscription-ipp.o: subscription-ipp.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h system.o: system.c pappl-private.h client-private.h base-private.h \ ../config.h base.h \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h resource-private.h system-accessors.o: system-accessors.c system-private.h dnssd-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ subscription-private.h \ subscription.h system.h device.h log.h \ \ \ system-ipp.o: system-ipp.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h system-loadsave.o: system-loadsave.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h system-loc.o: system-loc.c system-private.h dnssd-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ subscription-private.h \ subscription.h system.h device.h log.h loc-private.h printer-private.h \ printer.h loc.h system-printer.o: system-printer.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h system-subscription.o: system-subscription.c pappl-private.h \ client-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h system-webif.o: system-webif.c pappl-private.h client-private.h \ base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ util.o: util.c base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ system-status-macos.o: system-status-macos.m pappl-private.h \ client-private.h base-private.h ../config.h base.h \ \ \ \ \ \ \ \ \ \ client.h log.h \ device-private.h device.h dnssd-private.h job-private.h job.h \ loc-private.h system-private.h subscription-private.h subscription.h \ system.h printer-private.h printer.h loc.h log-private.h \ mainloop-private.h mainloop.h pappl-1.4.9/pappl/Info.plist000066400000000000000000000016101476704353100157350ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable pappl CFBundleIdentifier org.msweet.pappl CFBundleInfoDictionaryVersion 6.0 CFBundleName pappl CFBundlePackageType FMWK CFBundleShortVersionString 0.1 CFBundleSupportedPlatforms MacOSX CFBundleVersion 0.1 LSMinimumSystemVersion 10.14 NSHumanReadableCopyright Copyright © 2019-2020 Michael Sweet. All rights reserved. pappl-1.4.9/pappl/Makefile000066400000000000000000000211431476704353100154300ustar00rootroot00000000000000# # Library makefile for the Printer Application Framework # # Copyright © 2020-2025 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # include ../Makedefs BASEOBJS = \ client.o \ client-accessors.o \ client-auth.o \ client-loc.o \ client-ipp.o \ client-webif.o \ contact.o \ device.o \ device-file.o \ device-network.o \ device-usb.o \ dnssd.o \ httpmon.o \ job-accessors.o \ job-filter.o \ job-ipp.o \ job-process.o \ job.o \ link.o \ loc.o \ log.o \ lookup.o \ mainloop.o \ mainloop-subcommands.o \ mainloop-support.o \ printer.o \ printer-accessors.o \ printer-driver.o \ printer-ipp.o \ printer-raw.o \ printer-support.o \ printer-usb.o \ printer-webif.o \ resource.o \ snmp.o \ subscription.o \ subscription-ipp.o \ system.o \ system-accessors.o \ system-ipp.o \ system-loadsave.o \ system-loc.o \ system-printer.o \ system-subscription.o \ system-webif.o \ util.o OBJS = \ $(BASEOBJS) \ $(SYSTEM_STATUS) HEADERS = \ base.h \ client.h \ device.h \ job.h \ loc.h \ log.h \ mainloop.h \ pappl.h \ printer.h \ subscription.h \ system.h RESOURCES = \ icon-sm.png \ icon-md.png \ icon-lg.png \ style.css STRINGS = \ strings/de.strings \ strings/en.strings \ strings/es.strings \ strings/fr.strings \ strings/it.strings \ strings/ja.strings \ strings/nb-NO.strings \ strings/pl.strings \ strings/tr.strings DOCFLAGS = \ --author "Michael R Sweet" \ --copyright "Copyright (c) 2020-2025 by Michael R Sweet" \ --docversion $(PAPPL_VERSION) .SUFFIXES: md DOCFILES = \ device.md \ hello-world.md \ introduction.md \ job.md \ mainloop.md \ printer.md \ resource.md \ system.md TARGETS = $(LIBPAPPL) libpappl.a # Make everything all: $(TARGETS) # Clean everything clean: $(RM) $(OBJS) $(RM) $(TARGETS) $(RM) libpappl.dylib libpappl.so parse-lock-log # Clean all non-distribution files distclean: clean # Update dependencies depend: $(CC) -MM $(CFLAGS) `echo $(OBJS:.o=.c) | sed -e '1,$$s/-macos\.c/-macos.m/g'` | sed -e '1,$$s/ \/usr\/include\/[^ ]*//g' -e '1,$$s/ \/usr\/local\/include\/[^ ]*//g' >Dependencies # Generate documentation using codedoc (https://www.msweet.org/codedoc) doc: echo Generating pappl.html... codedoc $(DOCFLAGS) --title "PAPPL v$(PAPPL_VERSION_MAJOR).$(PAPPL_VERSION_MINOR) Programmers Manual" --coverimage ../doc/pappl-512.png --body ../doc/pappl-body.md pappl.xml $(HEADERS) $(BASEOBJS:.o=.c) >../doc/pappl.html echo Generating pappl.epub... codedoc $(DOCFLAGS) --title "PAPPL v$(PAPPL_VERSION_MAJOR).$(PAPPL_VERSION_MINOR) Programmers Manual" --coverimage epub.png --body ../doc/pappl-body.md pappl.xml --epub ../doc/pappl.epub $(RM) pappl.xml echo Generating pappl-client.3... codedoc $(DOCFLAGS) --title "pappl client functions" --man pappl-client --section 3 --body ../man/pappl-client-body.man --footer ../man/pappl-footer.man client.h client*.c >../man/pappl-client.3 echo Generating pappl-device.3... codedoc $(DOCFLAGS) --title "pappl device functions" --man pappl-device --section 3 --body ../man/pappl-device-body.man --footer ../man/pappl-footer.man device.h device.c >../man/pappl-device.3 echo Generating pappl-job.3... codedoc $(DOCFLAGS) --title "pappl job functions" --man pappl-job --section 3 --body ../man/pappl-job-body.man --footer ../man/pappl-footer.man job.h job*.c >../man/pappl-job.3 echo Generating pappl-log.3... codedoc $(DOCFLAGS) --title "pappl logging functions" --man pappl-log --section 3 --body ../man/pappl-log-body.man --footer ../man/pappl-footer.man log.h log.c >../man/pappl-log.3 echo Generating pappl-mainloop.3... codedoc $(DOCFLAGS) --title "pappl main loop functions" --man pappl-mainloop --section 3 --body ../man/pappl-mainloop-body.man --footer ../man/pappl-footer.man mainloop.h mainloop*.c >../man/pappl-mainloop.3 echo Generating pappl-printer.3... codedoc $(DOCFLAGS) --title "pappl printer functions" --man pappl-printer --section 3 --body ../man/pappl-printer-body.man --footer ../man/pappl-footer.man printer.h printer*.c >../man/pappl-printer.3 echo Generating pappl-resource.3... codedoc $(DOCFLAGS) --title "pappl resource functions" --man pappl-resource --section 3 --body ../man/pappl-resource-body.man --footer ../man/pappl-footer.man link.c resource.c >../man/pappl-resource.3 echo Generating pappl-system.3... codedoc $(DOCFLAGS) --title "pappl system functions" --man pappl-system --section 3 --body ../man/pappl-system-body.man --footer ../man/pappl-footer.man system.h system*.c >../man/pappl-system.3 # Install everything install: $(TARGETS) echo Installing pappl-makeresheader in $(BUILDROOT)$(bindir)... $(INSTALL) -d -m 755 $(BUILDROOT)$(bindir) $(INSTALL) -c -m 755 makeresheader.sh $(BUILDROOT)$(bindir)/pappl-makeresheader echo Installing libpappl in $(BUILDROOT)$(libdir)... $(INSTALL) -d -m 755 $(BUILDROOT)$(libdir) $(INSTALL) -c -m 755 $(LIBPAPPL) $(BUILDROOT)$(libdir) if test "$(LIBPAPPL)" = libpappl.so.1; then \ $(RM) $(BUILDROOT)$(libdir)/libpappl.so; \ $(LN) -s libpappl.so.1 $(BUILDROOT)$(libdir)/libpappl.so; \ elif test "$(LIBPAPPL)" = libpappl.1.dylib; then \ $(RM) $(BUILDROOT)$(libdir)/libpappl.dylib; \ $(LN) -s libpappl.1.dylib $(BUILDROOT)$(libdir)/libpappl.dylib; \ fi if test "$(LIBPAPPL_STATIC)" = libpappl.a; then \ $(INSTALL) -c -m 644 libpappl.a $(BUILDROOT)$(libdir); \ fi echo Installing pkg-config files in $(BUILDROOT)$(libdir)/pkgconfig... $(INSTALL) -d -m 755 $(BUILDROOT)$(libdir)/pkgconfig $(INSTALL) -c -m 644 pappl.pc $(BUILDROOT)$(libdir)/pkgconfig echo Installing data files in $(BUILDROOT)$(datadir)/pappl... $(INSTALL) -d -m 755 $(BUILDROOT)$(datadir)/pappl for file in $(RESOURCES); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)$(datadir)/pappl; \ done echo Installing header files in $(BUILDROOT)$(includedir)/pappl... $(INSTALL) -d -m 755 $(BUILDROOT)$(includedir)/pappl for file in $(HEADERS); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)$(includedir)/pappl; \ done # Test everything test: # pappl exports file libpappl1.def: $(OBJS) Makefile echo Generating $@... echo "LIBRARY libpappl1" >libpappl1.def echo "VERSION 1.2" >>libpappl1.def echo "EXPORTS" >>libpappl1.def (nm $(OBJS) 2>/dev/null | grep "T _" | awk '{print $$3}') | \ grep -v '^__' | sed -e '1,$$s/^_//' | sort >>libpappl1.def # pappl static library libpappl.a: $(OBJS) echo Archiving $@... $(RM) $@ $(AR) $(ARFLAGS) $@ $(OBJS) $(RANLIB) $@ # pappl shared library libpappl.so.1: $(OBJS) echo Linking $@... $(CC) $(DSOFLAGS) -shared -o $@ -Wl,-soname,$@ $(OBJS) $(LIBS) $(RM) `basename $@ .1` $(LN) $@ `basename $@ .1` # pappl shared library (macOS) libpappl.1.dylib: $(OBJS) echo Linking $@... $(CC) $(DSOFLAGS) -dynamiclib -o $@ \ -install_name $(libdir)/$@ \ -current_version $(PAPPL_VERSION_MAJOR).$(PAPPL_VERSION_MINOR) -compatibility_version 1.0 \ $(OBJS) $(LIBS) $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.`basename $@ .1.dylib` $@ $(RM) `basename $@ .1.dylib`.dylib $(LN) $@ `basename $@ .1.dylib`.dylib # parse-lock-log parse-lock-log: parse-lock-log.c echo Compiling and linking $@... $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< # Static resource header... resheader: $(RESOURCES) echo Generating $@... ./makeresheader.sh $(RESOURCES) >resource-private.h # Update localization strings using StringUtils () .PHONY: strings strings: echo Updating base.strings... cp ipp.strings base.strings stringsutil -f base.strings -n _PAPPL_LOC scan *.[cm] for file in $(STRINGS); do \ stringsutil -f $$file -c merge base.strings; \ done stringsh: echo Generating localization headers... for file in $(STRINGS); do \ stringsutil -f $$file export strings/`basename $$file .strings`_strings.h; \ done # Analyze code with the Clang static analyzer clang: echo "clang $(CPPFLAGS) --analyze ..." clang $(CPPFLAGS) --analyze `echo $(OBJS:.o=.c) | sed -e '1,$$s/-macos\.c/-macos.m/g'` 2>clang.log rm -rf $(OBJS:.o=.plist) test -s clang.log && (echo "$(GHA_ERROR)Clang detected issues."; echo ""; cat clang.log; exit 1) || exit 0 # Analyze code using Cppcheck cppcheck: echo Analyzing code with Cppcheck... echo 'cppcheck $(CPPFLAGS) --template=gcc --suppressions-list=cppcheck.suppressions ...' cppcheck $(CPPFLAGS) --template=gcc --suppressions-list=cppcheck.suppressions `echo $(OBJS:.o=.c) | sed -e '1,$$s/-macos\.c/-macos.m/g'` 2>cppcheck.log test -s cppcheck.log && (echo "$(GHA_ERROR)Cppcheck detected issues."; echo ""; cat cppcheck.log; exit 1) || exit 0 # Dependencies include Dependencies pappl-1.4.9/pappl/base-private.h000066400000000000000000000143761476704353100165350ustar00rootroot00000000000000// // Private base definitions for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_BASE_PRIVATE_H_ # define _PAPPL_BASE_PRIVATE_H_ # include # include "base.h" # include # include # if _WIN32 # include # include "win32-gettimeofday.h" # include "win32-pthread.h" # include "win32-socket.h" # define getuid() 0 # else // !_WIN32 # include # include # include # include # include # include # include extern char **environ; # define O_BINARY 0 // I hate Windows... # endif // _WIN32 // // The CUPS API is changed in CUPS v3... // # if CUPS_VERSION_MAJOR < 3 # define CUPS_ENCODING_ISO8859_1 CUPS_ISO8859_1 # define CUPS_ENCODING_JIS_X0213 CUPS_JIS_X0213 # define cups_len_t int # define cups_page_header_t cups_page_header2_t # define cupsArrayNew cupsArrayNew3 # define cupsLangGetName(lang) lang->language # define cupsRasterReadHeader cupsRasterReadHeader2 # define cupsRasterWriteHeader cupsRasterWriteHeader2 # define httpAddrConnect httpAddrConnect2 # define httpConnect httpConnect2 # define httpGetDateString httpGetDateString2 # define httpRead httpRead2 # define httpWrite httpWrite2 # define httpWriteResponse(http,code) (httpWriteResponse(http,code) == 0) # define IPP_NUM_CAST (int) # if CUPS_VERSION_MINOR < 3 # define HTTP_STATUS_FOUND (http_status_t)302 # endif // CUPS_VERSION_MINOR < 3 # if CUPS_VERSION_MINOR < 5 # define cups_b64len_t int # define cupsArrayGetCount cupsArrayCount # define cupsArrayGetElement(a,n) cupsArrayIndex(a,(int)n) # define cupsArrayGetFirst cupsArrayFirst # define cupsArrayGetLast cupsArrayLast # define cupsArrayGetNext cupsArrayNext # define cupsArrayGetPrev cupsArrayPrev # define cupsCreateTempFd(prefix,suffix,buffer,bufsize) cupsTempFd(buffer,bufsize) # define cupsGetError cupsLastError # define cupsGetErrorString cupsLastErrorString # define cupsGetUser cupsUser static inline int cupsParseOptions2(const char *s, const char **end, int num_options, cups_option_t **options) { (void)end; return (cupsParseOptions(s, num_options, options)); } # define cupsParseOptions cupsParseOptions2 # define cupsRasterGetErrorString cupsRasterErrorString # define httpAddrGetFamily httpAddrFamily # define httpAddrGetLength httpAddrLength # define httpAddrGetString httpAddrString # define httpAddrIsLocalhost httpAddrLocalhost # define httpConnectAgain httpReconnect2 # define httpDecode64(out,outlen,in,end) httpDecode64_2(out,outlen,in) # define httpEncode64(out,outlen,in,inlen,url) httpEncode64_2(out,outlen,in,inlen) # define httpGetError httpError # define httpSetEncryption(http,e) (httpEncryption(http,e)>=0) # define httpStatusString httpStatus # define ippGetFirstAttribute ippFirstAttribute # define ippGetLength ippLength # define ippGetNextAttribute ippNextAttribute typedef cups_array_func_t cups_array_cb_t; typedef cups_acopy_func_t cups_acopy_cb_t; typedef cups_afree_func_t cups_afree_cb_t; typedef cups_raster_iocb_t cups_raster_cb_t; typedef ipp_copycb_t ipp_copy_cb_t; # else # define cups_b64len_t size_t # define cupsParseOptions cupsParseOptions2 # define httpDecode64 httpDecode64_3 # define httpEncode64 httpEncode64_3 # endif // CUPS_VERSION_MINOR < 5 # else # define cups_b64len_t size_t # define cups_len_t size_t # define cups_utf8_t char # define IPP_NUM_CAST (size_t) # endif // CUPS_VERSION_MAJOR < 3 // // Macros... // # ifdef DEBUG # define _PAPPL_DEBUG(...) fprintf(stderr, __VA_ARGS__) # define _papplRWLockRead(obj) fprintf(stderr, "%p/%s: rdlock %p(%s)\n", (void *)pthread_self(), __func__, (void *)obj, obj->name), pthread_rwlock_rdlock(&obj->rwlock) # define _papplRWLockWrite(obj) fprintf(stderr, "%p/%s: wrlock %p(%s)\n", (void *)pthread_self(), __func__, (void *)obj, obj->name), pthread_rwlock_wrlock(&obj->rwlock) # define _papplRWUnlock(obj) fprintf(stderr, "%p/%s: unlock %p(%s)\n", (void *)pthread_self(), __func__, (void *)obj, obj->name), pthread_rwlock_unlock(&obj->rwlock) # else # define _PAPPL_DEBUG(...) # define _papplRWLockRead(obj) pthread_rwlock_rdlock(&obj->rwlock) # define _papplRWLockWrite(obj) pthread_rwlock_wrlock(&obj->rwlock) # define _papplRWUnlock(obj) pthread_rwlock_unlock(&obj->rwlock) # endif // DEBUG # define _PAPPL_LOC(s) s # define _PAPPL_LOOKUP_STRING(bit,strings) _papplLookupString(bit, sizeof(strings) / sizeof(strings[0]), strings) # define _PAPPL_LOOKUP_VALUE(keyword,strings) _papplLookupValue(keyword, sizeof(strings) / sizeof(strings[0]), strings) // // Macros to implement a simple Fibonacci sequence for variable back-off... // # define _PAPPL_FIB_NEXT(v) (((((v >> 8) + (v & 255) - 1) % 60) + 1) | ((v & 255) << 8)) # define _PAPPL_FIB_VALUE(v) (v & 255) // // Types and structures... // typedef struct _pappl_ipp_filter_s // Attribute filter { cups_array_t *ra; // Requested attributes ipp_tag_t group_tag; // Group to copy } _pappl_ipp_filter_t; typedef struct _pappl_link_s // Web interface navigation link { char *label, // Label *path_or_url; // Path or URL pappl_loptions_t options; // Link options } _pappl_link_t; // // Utility functions... // extern ipp_t *_papplContactExport(pappl_contact_t *contact) _PAPPL_PRIVATE; extern void _papplContactImport(ipp_t *col, pappl_contact_t *contact) _PAPPL_PRIVATE; extern void _papplCopyAttributes(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group_tag, int quickcopy) _PAPPL_PRIVATE; extern bool _papplIsEqual(const char *a, const char *b) _PAPPL_PRIVATE; extern const char *_papplLookupString(unsigned bit, size_t num_strings, const char * const *strings) _PAPPL_PRIVATE; extern size_t _papplLookupStrings(unsigned value, size_t max_keywords, char *keywords[], size_t num_strings, const char * const *strings) _PAPPL_PRIVATE; extern unsigned _papplLookupValue(const char *keyword, size_t num_strings, const char * const *strings) _PAPPL_PRIVATE; #endif // !_PAPPL_BASE_PRIVATE_H_ pappl-1.4.9/pappl/base.h000066400000000000000000000204411476704353100150530ustar00rootroot00000000000000// // Base definitions for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_BASE_H_ # define _PAPPL_BASE_H_ # include # include # include # include # include # include # include # include # include # include # if _WIN32 # include # include typedef int gid_t; typedef int uid_t; # else # include # endif // _WIN32 # ifdef __cplusplus extern "C" { # endif // __cplusplus // // IPP operations/tags... // # if CUPS_VERSION_MAJOR == 2 && CUPS_VERSION_MINOR < 3 # define IPP_OP_CREATE_PRINTER (ipp_op_t)0x004C # define IPP_OP_DELETE_PRINTER (ipp_op_t)0x004E # define IPP_OP_GET_PRINTERS (ipp_op_t)0x004F # define IPP_OP_CREATE_SYSTEM_SUBSCRIPTIONS (ipp_op_t)0x0058 # define IPP_OP_DISABLE_ALL_PRINTERS (ipp_op_t)0x0059 # define IPP_OP_ENABLE_ALL_PRINTERS (ipp_op_t)0x005A # define IPP_OP_GET_SYSTEM_ATTRIBUTES (ipp_op_t)0x005B # define IPP_OP_GET_SYSTEM_SUPPORTED_VALUES (ipp_op_t)0x005C # define IPP_OP_PAUSE_ALL_PRINTERS (ipp_op_t)0x005D # define IPP_OP_PAUSE_ALL_PRINTERS_AFTER_CURRENT_JOB (ipp_op_t)0x005E # define IPP_OP_RESUME_ALL_PRINTERS (ipp_op_t)0x0061 # define IPP_OP_SET_SYSTEM_ATTRIBUTES (ipp_op_t)0x0062 # define IPP_OP_SHUTDOWN_ALL_PRINTERS (ipp_op_t)0x0063 # define IPP_TAG_SYSTEM (ipp_tag_t)0x000A # endif // CUPS_VERSION_MAJOR == 2 && CUPS_VERSION_MINOR < 3 # define IPP_OP_PAPPL_FIND_DEVICES (ipp_op_t)0x402b # define IPP_OP_PAPPL_FIND_DRIVERS (ipp_op_t)0x402c # define IPP_OP_PAPPL_CREATE_PRINTERS (ipp_op_t)0x402d // // Visibility and other annotations... // # if _WIN32 # define _PAPPL_DEPRECATED(m) # define _PAPPL_INTERNAL # define _PAPPL_PRIVATE # define _PAPPL_PUBLIC # define _PAPPL_FORMAT(a,b) # define _PAPPL_NONNULL(...) # define _PAPPL_NORETURN # elif defined(__has_extension) || defined(__GNUC__) # define _PAPPL_DEPRECATED(m) __attribute__ ((deprecated(m))) __attribute__ ((visibility("default"))) # define _PAPPL_INTERNAL __attribute__ ((visibility("hidden"))) # define _PAPPL_PRIVATE __attribute__ ((visibility("default"))) # define _PAPPL_PUBLIC __attribute__ ((visibility("default"))) # define _PAPPL_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b))) # define _PAPPL_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__))) # define _PAPPL_NORETURN __attribute__ ((noreturn)) # else # define _PAPPL_DEPRECATED(m) # define _PAPPL_INTERNAL # define _PAPPL_PRIVATE # define _PAPPL_PUBLIC # define _PAPPL_FORMAT(a,b) # define _PAPPL_NONNULL(...) # define _PAPPL_NORETURN # endif // __has_extension || __GNUC__ // // Common types... // typedef struct _pappl_client_s pappl_client_t; // Client connection object typedef struct _pappl_device_s pappl_device_t; // Device connection object typedef unsigned char pappl_dither_t[16][16]; // 16x16 dither array typedef struct pappl_pr_driver_data_s pappl_pr_driver_data_t; // Print driver data typedef struct _pappl_job_s pappl_job_t;// Job object typedef struct _pappl_loc_s pappl_loc_t;// Localization data typedef struct pappl_pr_options_s pappl_pr_options_t; // Combined print job options typedef unsigned int pappl_preason_t; // Bitfield for IPP "printer-state-reasons" values typedef struct _pappl_printer_s pappl_printer_t; // Printer object typedef struct _pappl_subscription_s pappl_subscription_t; // Subscription object typedef struct _pappl_system_s pappl_system_t; // System object typedef struct pappl_contact_s // Contact information { char name[256]; // Contact name char email[256]; // Contact email address char telephone[256]; // Contact phone number } pappl_contact_t; enum pappl_loptions_e // Link option bits { PAPPL_LOPTIONS_NAVIGATION = 0x0001, // Link shown in navigation bar PAPPL_LOPTIONS_CONFIGURATION = 0x0002, // Link shown in configuration section PAPPL_LOPTIONS_JOB = 0x0004, // Link shown in job(s) section PAPPL_LOPTIONS_LOGGING = 0x0008, // Link shown in logging section PAPPL_LOPTIONS_NETWORK = 0x0010, // Link shown in network section PAPPL_LOPTIONS_PRINTER = 0x0020, // Link shown in printer(s) section PAPPL_LOPTIONS_SECURITY = 0x0040, // Link shown in security section PAPPL_LOPTIONS_STATUS = 0x0080, // Link shown in status section PAPPL_LOPTIONS_TLS = 0x0100, // Link shown in TLS section PAPPL_LOPTIONS_OTHER = 0x0200, // Link shown in other section PAPPL_LOPTIONS_HTTPS_REQUIRED = 0x8000 // Link requires HTTPS }; typedef unsigned short pappl_loptions_t;// Bitfield for link options typedef enum pappl_supply_color_e // "printer-supply" color values { PAPPL_SUPPLY_COLOR_NO_COLOR, // No color (waste tank, etc.) PAPPL_SUPPLY_COLOR_BLACK, // Black ink/toner (photo or matte) PAPPL_SUPPLY_COLOR_CYAN, // Cyan ink/toner PAPPL_SUPPLY_COLOR_GRAY, // Gray ink (sometimes marketed as light gray) PAPPL_SUPPLY_COLOR_GREEN, // Green ink PAPPL_SUPPLY_COLOR_LIGHT_CYAN, // Light cyan ink PAPPL_SUPPLY_COLOR_LIGHT_GRAY, // Light gray ink (sometimes marketed as light light gray) PAPPL_SUPPLY_COLOR_LIGHT_MAGENTA, // Light magenta ink PAPPL_SUPPLY_COLOR_MAGENTA, // Magenta ink/toner PAPPL_SUPPLY_COLOR_ORANGE, // Orange ink PAPPL_SUPPLY_COLOR_VIOLET, // Violet ink PAPPL_SUPPLY_COLOR_YELLOW, // Yellow ink/toner PAPPL_SUPPLY_COLOR_MULTIPLE // Multiple-color ink } pappl_supply_color_t; typedef enum pappl_supply_type_e // IPP "printer-supply" type values { PAPPL_SUPPLY_TYPE_BANDING_SUPPLY, // Banding finisher supplies PAPPL_SUPPLY_TYPE_BINDING_SUPPLY, // Binding finisher supplies PAPPL_SUPPLY_TYPE_CLEANER_UNIT, // Cleaning unit PAPPL_SUPPLY_TYPE_CORONA_WIRE, // Corona wire (laser printers) PAPPL_SUPPLY_TYPE_COVERS, // Cover finisher supplies PAPPL_SUPPLY_TYPE_DEVELOPER, // Developer supply PAPPL_SUPPLY_TYPE_FUSER_CLEANING_PAD, // Fuser cleaning pad (laser printers) PAPPL_SUPPLY_TYPE_FUSER_OIL_WICK, // Fuser oil wick (laser printers) PAPPL_SUPPLY_TYPE_FUSER_OIL, // Fuser oil supply (laser printers) PAPPL_SUPPLY_TYPE_FUSER_OILER, // Fuser oiler (laser printers) PAPPL_SUPPLY_TYPE_FUSER, // Fuser (laser printers) PAPPL_SUPPLY_TYPE_INK_CARTRIDGE, // Ink cartridge PAPPL_SUPPLY_TYPE_INK_RIBBON, // Ink ribbon supply PAPPL_SUPPLY_TYPE_INK, // Ink supply PAPPL_SUPPLY_TYPE_INSERTS, // Insert finisher supplies PAPPL_SUPPLY_TYPE_OPC, // Optical photoconductor (laser printers) PAPPL_SUPPLY_TYPE_PAPER_WRAP, // Wrap finisher supplies PAPPL_SUPPLY_TYPE_RIBBON_WAX, // Wax ribbon supply PAPPL_SUPPLY_TYPE_SOLID_WAX, // Solid wax supply PAPPL_SUPPLY_TYPE_STAPLES, // Staple finisher supplies PAPPL_SUPPLY_TYPE_STITCHING_WIRE, // Staple/stitch finisher supplies PAPPL_SUPPLY_TYPE_TONER_CARTRIDGE, // Toner cartridge PAPPL_SUPPLY_TYPE_TONER, // Toner supply PAPPL_SUPPLY_TYPE_TRANSFER_UNIT, // Transfer unit (laser printers) PAPPL_SUPPLY_TYPE_WASTE_INK, // Waste ink PAPPL_SUPPLY_TYPE_WASTE_TONER, // Waste toner PAPPL_SUPPLY_TYPE_WASTE_WATER, // Waste water PAPPL_SUPPLY_TYPE_WASTE_WAX, // Waste wax PAPPL_SUPPLY_TYPE_WATER, // Water supply PAPPL_SUPPLY_TYPE_GLUE_WATER_ADDITIVE, // Glue water additive PAPPL_SUPPLY_TYPE_WASTE_PAPER, // Waste paper PAPPL_SUPPLY_TYPE_SHRINK_WRAP, // Shrink wrap PAPPL_SUPPLY_TYPE_OTHER, // Other supply PAPPL_SUPPLY_TYPE_UNKNOWN // Unknown supply } pappl_supply_type_t; typedef struct pappl_supply_s // Supply data { pappl_supply_color_t color; // Color, if any char description[256]; // Description bool is_consumed; // Is this a supply that is consumed? int level; // Level (0-100, -1 = unknown) pappl_supply_type_t type; // Type } pappl_supply_t; // // Utility functions... // extern size_t papplCopyString(char *dst, const char *src, size_t dstsize) _PAPPL_PUBLIC; extern int papplCreateTempFile(char *fname, size_t fnamesize, const char *prefix, const char *ext) _PAPPL_PUBLIC; extern unsigned papplGetRand(void) _PAPPL_PUBLIC; extern const char *papplGetTempDir(void) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_BASE_H_ pappl-1.4.9/pappl/base.strings000066400000000000000000001325201476704353100163170ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Cancel all jobs (cancel)."; " -c COPIES" = " -c COPIES"; " -d PRINTER Specify printer." = " -d PRINTER Specify printer."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Specify job ID (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Specify driver (add/modify)."; " -n COPIES Specify number of copies (submit)." = " -n COPIES Specify number of copies (submit)."; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Specify option (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 to 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 to 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE'"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZATION'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Specify ipp: or ipps: printer/server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Specify socket: or usb: device (add/modify)."; " add PRINTER Add a printer." = " add PRINTER Add a printer."; " autoadd Automatically add supported printers." = " autoadd Automatically add supported printers."; " cancel Cancel one or more jobs." = " cancel Cancel one or more jobs."; " default Set the default printer." = " default Set the default printer."; " delete Delete a printer." = " delete Delete a printer."; " devices List devices." = " devices List devices."; " drivers List drivers." = " drivers List drivers."; " jobs List jobs." = " jobs List jobs."; " modify Modify a printer." = " modify Modify a printer."; " options List printer options." = " options List printer options."; " pause Pause printing for a printer." = " pause Pause printing for a printer."; " printers List printers." = " printers List printers."; " resume Resume printing for a printer." = " resume Resume printing for a printer."; " server Run a server." = " server Run a server."; " shutdown Shutdown a running server." = " shutdown Shutdown a running server."; " status Show server/printer/job status." = " status Show server/printer/job status."; " submit Submit a file for printing." = " submit Submit a file for printing."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d inches/sec"; "%d job" = "%d job"; /* Media size in millimeters */ "%d x %dmm" = "%d x %dmm"; "%ddpi" = "%ddpi"; "%dx%ddpi" = "%dx%ddpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) from %s"; /* Source/Tray Media */ "%s Media" = "%s Media"; "%s: Bad 'server-port' value." = "%s: Bad 'server-port' value."; "%s: Bad job ID." = "%s: Bad job ID."; "%s: Bad printer URI '%s'." = "%s: Bad printer URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Cannot specify more than one sub-command."; "%s: Empty print file received on the standard input." = "%s: Empty print file received on the standard input."; "%s: Failed to create a system." = "%s: Failed to create a system."; "%s: Missing '-d PRINTER'." = "%s: Missing '-d PRINTER'."; "%s: Missing '-m DRIVER-NAME'." = "%s: Missing '-m DRIVER-NAME'."; "%s: Missing '-v DEVICE-URI'." = "%s: Missing '-v DEVICE-URI'."; "%s: Missing copy count after '-n'." = "%s: Missing copy count after '-n'."; "%s: Missing device URI after '-v'." = "%s: Missing device URI after '-v'."; "%s: Missing driver name after '-m'." = "%s: Missing driver name after '-m'."; "%s: Missing filename after '--'." = "%s: Missing filename after '--'."; "%s: Missing hostname after '-h'." = "%s: Missing hostname after '-h'."; "%s: Missing job ID after '-j'." = "%s: Missing job ID after '-j'."; "%s: Missing option(s) after '-o'." = "%s: Missing option(s) after '-o'."; "%s: Missing printer URI after '-u'." = "%s: Missing printer URI after '-u'."; "%s: Missing printer name after '-d'." = "%s: Missing printer name after '-d'."; "%s: Missing space after '-o'." = "%s: Missing space after '-o'."; "%s: Missing title after '-t'." = "%s: Missing title after '-t'."; "%s: No default printer available." = "%s: No default printer available."; "%s: No files to print." = "%s: No files to print."; "%s: Server is not running." = "%s: Server is not running."; "%s: Sub-command '%s' does not accept files." = "%s: Sub-command '%s' does not accept files."; "%s: Sub-command 'autoadd' is not supported." = "%s: Sub-command 'autoadd' is not supported."; "%s: Too many files." = "%s: Too many files."; "%s: Unable to access '%s': %s" = "%s: Unable to access '%s': %s"; "%s: Unable to add printer: %s" = "%s: Unable to add printer: %s"; "%s: Unable to cancel job: %s" = "%s: Unable to cancel job: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Unable to connect to printer at '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Unable to connect to server: %s"; "%s: Unable to create temporary file: %s" = "%s: Unable to create temporary file: %s"; "%s: Unable to delete printer: %s" = "%s: Unable to delete printer: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Unable to get information for '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Unable to get information for printer: %s"; "%s: Unable to get printer options: %s" = "%s: Unable to get printer options: %s"; "%s: Unable to modify printer: %s" = "%s: Unable to modify printer: %s"; "%s: Unable to pause printer: %s" = "%s: Unable to pause printer: %s"; "%s: Unable to print '%s': %s" = "%s: Unable to print '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Unable to resume printer: %s"; "%s: Unable to set default printer: %s" = "%s: Unable to set default printer: %s"; "%s: Unable to shutdown server: %s" = "%s: Unable to shutdown server: %s"; "%s: Unable to start server: %s" = "%s: Unable to start server: %s"; "%s: Unable to write to temporary file: %s" = "%s: Unable to write to temporary file: %s"; "%s: Unknown option '%s'." = "%s: Unknown option '%s'."; "%s: Unknown option '-%c'." = "%s: Unknown option '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Unknown sub-command '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Unsupported URI scheme '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Warning - user credentials are not supported in URIs."; ", Borderless" = ", Borderless"; "A printer with that name already exists." = "A printer with that name already exists."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Add Printer"; "Admin Group" = "Admin Group"; "Afghanistan" = "Afghanistan"; "Albania" = "Albania"; "Algeria" = "Algeria"; "American Samoa" = "American Samoa"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarctica"; "Antigua and Barbuda" = "Antigua and Barbuda"; "Argentina" = "Argentina"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Auto"; "Auto-Detect Driver" = "Auto-Detect Driver"; "Azerbaijan" = "Azerbaijan"; "Bad administration group." = "Bad administration group."; "Bad port number." = "Bad port number."; "Bad print group." = "Bad print group."; "Bad printer defaults." = "Bad printer defaults."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrain"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbados"; "Belarus" = "Belarus"; "Belgium" = "Belgium"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivia (Plurinational State of)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius and Saba"; "Borderless" = "Borderless"; "Bosnia and Herzegovina" = "Bosnia and Herzegovina"; "Botswana" = "Botswana"; "Bouvet Island" = "Bouvet Island"; "Brazil" = "Brazil"; "British Indian Ocean Territory" = "British Indian Ocean Territory"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bulgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Cambodia"; "Cameroon" = "Cameroon"; "Canada" = "Canada"; "Cancel All Jobs" = "Cancel All Jobs"; "Cancel Job" = "Cancel Job"; "Canceled %s" = "Canceled %s"; "Canceling" = "Canceling"; "Cayman Islands" = "Cayman Islands"; "Central African Republic" = "Central African Republic"; "Certificate created." = "Certificate created."; "Certificate installed." = "Certificate installed."; "Certificate request created." = "Certificate request created."; "Chad" = "Chad"; "Change Access Password" = "Change Access Password"; "Change Log Level" = "Change Log Level"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Change Wi-Fi Network"; "Changes Saved." = "Changes Saved."; "Changes saved." = "Changes saved."; "Chile" = "Chile"; "China" = "China"; "Christmas Island" = "Christmas Island"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Cocos (Keeling) Islands"; "Colombia" = "Colombia"; "Comoros" = "Comoros"; "Completed %s" = "Completed %s"; "Configuration" = "Configuration"; "Configure Media" = "Configure Media"; "Confirm Cancel All" = "Confirm Cancel All"; "Confirm Delete Printer" = "Confirm Delete Printer"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, Democratic Republic of the"; "Contact" = "Contact"; "Cook Islands" = "Cook Islands"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Create Certificate Signing Request"; "Create New Certificate" = "Create New Certificate"; "Create New TLS Certificate" = "Create New TLS Certificate"; "Create TLS Certificate Request" = "Create TLS Certificate Request"; "Croatia" = "Croatia"; "Cuba" = "Cuba"; "Curaçao" = "Curaçao"; "Current Password" = "Current Password"; "Custom Size" = "Custom Size"; "Cyprus" = "Cyprus"; "Czechia" = "Czechia"; "Côte d'Ivoire" = "Côte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SD Service Name"; "Debugging" = "Debugging"; "Default printer set." = "Default printer set."; "Delete" = "Delete"; "Delete Printer" = "Delete Printer"; "Denmark" = "Denmark"; "Djibouti" = "Djibouti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominica"; "Dominican Republic" = "Dominican Republic"; "Download Certificate Request File" = "Download Certificate Request File"; "Ecuador" = "Ecuador"; "Egypt" = "Egypt"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Equatorial Guinea"; "Eritrea" = "Eritrea"; "Errors" = "Errors"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Ethiopia"; "Falkland Islands (Malvinas)" = "Falkland Islands (Malvinas)"; "Faroe Islands" = "Faroe Islands"; "Fatal Errors/Conditions" = "Fatal Errors/Conditions"; "Fiji" = "Fiji"; "Finland" = "Finland"; "France" = "France"; "French Guiana" = "French Guiana"; "French Polynesia" = "French Polynesia"; "French Southern Territories" = "French Southern Territories"; "Gabon" = "Gabon"; "Gambia" = "Gambia"; "Georgia" = "Georgia"; "Germany" = "Germany"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Greece"; "Greenland" = "Greenland"; "Grenada" = "Grenada"; "Group changes saved." = "Group changes saved."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Island and McDonald Islands"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Holy See"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Hostname"; "Human-Readable Location" = "Human-Readable Location"; "Hungary" = "Hungary"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Iceland"; "Identify Printer" = "Identify Printer"; "India" = "India"; "Indonesia" = "Indonesia"; "Informational" = "Informational"; "Install TLS Certificate" = "Install TLS Certificate"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Invalid Job ID."; "Invalid certificate or private key." = "Invalid certificate or private key."; "Invalid form data." = "Invalid form data."; "Invalid form submission." = "Invalid form submission."; "Invalid job ID." = "Invalid job ID."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (Islamic Republic of)"; "Iraq" = "Iraq"; "Ireland" = "Ireland"; "Isle of Man" = "Isle of Man"; "Israel" = "Israel"; "Italy" = "Italy"; "Jamaica" = "Jamaica"; "Japan" = "Japan"; "Jersey" = "Jersey"; "Job #" = "Job #"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Jobs"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Jordan"; "Kazakhstan" = "Kazakhstan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Korea (Democratic People's Republic of)"; "Korea, Republic of" = "Korea, Republic of"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kyrgyzstan"; "Landscape" = "Landscape"; "Lao People's Democratic Republic" = "Lao People's Democratic Republic"; "Latvia" = "Latvia"; "Lebanon" = "Lebanon"; "Lesotho" = "Lesotho"; "Level" = "Level"; "Liberia" = "Liberia"; "Libya" = "Libya"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lithuania"; "Location" = "Location"; "Log Level" = "Log Level"; "Logging" = "Logging"; "Logs" = "Logs"; "Luxembourg" = "Luxembourg"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malaysia"; "Maldives" = "Maldives"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Marshall Islands"; "Martinique" = "Martinique"; "Mauritania" = "Mauritania"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Media"; "Mexico" = "Mexico"; "Micronesia (Federated States of)" = "Micronesia (Federated States of)"; "Missing action." = "Missing action."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "Missing private key."; "Moldova, Republic of" = "Moldova, Republic of"; "Monaco" = "Monaco"; "Mongolia" = "Mongolia"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Morocco"; "Mozambique" = "Mozambique"; "Myanmar" = "Myanmar"; "Name" = "Name"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Netherlands"; "Network" = "Network"; "Network Printer" = "Network Printer"; "Networking" = "Networking"; "New Caledonia" = "New Caledonia"; "New Zealand" = "New Zealand"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "No default printer set."; "No jobs in history." = "No jobs in history."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "North Macedonia"; "Northern Mariana Islands" = "Northern Mariana Islands"; "Norway" = "Norway"; "Not set" = "Not set"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Options:"; "Organization" = "Organization"; "Organization Name" = "Organization Name"; "Other Settings" = "Other Settings"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palestine, State of"; "Panama" = "Panama"; "Papua New Guinea" = "Papua New Guinea"; "Paraguay" = "Paraguay"; "Password" = "Password"; "Password changed." = "Password changed."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit."; "Passwords do not match." = "Passwords do not match."; "Pause Printing" = "Pause Printing"; "Peru" = "Peru"; "Philippines" = "Philippines"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Please enter a hostname or IP address for the printer."; "Please enter a printer name." = "Please enter a printer name."; "Please select a device." = "Please select a device."; "Please select a driver." = "Please select a driver."; "Please select a valid log level." = "Please select a valid log level."; "Poland" = "Poland"; "Portrait" = "Portrait"; "Portugal" = "Portugal"; "Primary DNS" = "Primary DNS"; "Print Group" = "Print Group"; "Print Test Page" = "Print Test Page"; "Print job options:" = "Print job options:"; "Printer identified." = "Printer identified."; "Printer is currently active." = "Printer is currently active."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Printer names must start with a letter or underscore and cannot contain special characters."; "Printer options:" = "Printer options:"; "Printer paused." = "Printer paused."; "Printer pausing." = "Printer pausing."; "Printer resuming." = "Printer resuming."; "Printers" = "Printers"; "Printing Defaults" = "Printing Defaults"; "Puerto Rico" = "Puerto Rico"; "Qatar" = "Qatar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Reprint Job"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Resume Printing"; "Reverse Landscape" = "Reverse Landscape"; "Reverse Portrait" = "Reverse Portrait"; "Romania" = "Romania"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Running, %s since %s%s."; "Russian Federation" = "Russian Federation"; "Rwanda" = "Rwanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Saint Helena, Ascension and Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts and Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (French part)"; "Saint Pierre and Miquelon" = "Saint Pierre and Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent and the Grenadines"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome and Principe"; "Saudi Arabia" = "Saudi Arabia"; "Save Changes" = "Save Changes"; "Secondary DNS" = "Secondary DNS"; "Security" = "Security"; "Select Driver" = "Select Driver"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "Server is not running."; "Set Access Password" = "Set Access Password"; "Set as Default" = "Set as Default"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapore"; "Sint Maarten (Dutch part)" = "Sint Maarten (Dutch part)"; "Slovakia" = "Slovakia"; "Slovenia" = "Slovenia"; "Solomon Islands" = "Solomon Islands"; "Somalia" = "Somalia"; "South Africa" = "South Africa"; "South Georgia and the South Sandwich Islands" = "South Georgia and the South Sandwich Islands"; "South Sudan" = "South Sudan"; "Spain" = "Spain"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "Status"; "Sub-commands:" = "Sub-commands:"; "Sudan" = "Sudan"; "Supplies" = "Supplies"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard and Jan Mayen"; "Sweden" = "Sweden"; "Switzerland" = "Switzerland"; "Syrian Arab Republic" = "Syrian Arab Republic"; "Taiwan, Province of China" = "Taiwan, Province of China"; "Tajikistan" = "Tajikistan"; "Tanzania, United Republic of" = "Tanzania, United Republic of"; "Test page printed." = "Test page printed."; "Thailand" = "Thailand"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad and Tobago"; "Tunisia" = "Tunisia"; "Turkey" = "Turkey"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Turks and Caicos Islands"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukraine"; "Unable to access test print file." = "Unable to access test print file."; "Unable to copy print job." = "Unable to copy print job."; "Unable to create certificate request." = "Unable to create certificate request."; "Unable to create certificate." = "Unable to create certificate."; "Unable to create test print job." = "Unable to create test print job."; "Unable to identify printer." = "Unable to identify printer."; "Unable to lookup address." = "Unable to lookup address."; "Unable to use that driver." = "Unable to use that driver."; "United Arab Emirates" = "United Arab Emirates"; "United Kingdom" = "United Kingdom"; "United Kingdom of Great Britain and Northern Ireland" = "United Kingdom of Great Britain and Northern Ireland"; "United States Minor Outlying Islands" = "United States Minor Outlying Islands"; "United States of America" = "United States of America"; "Unknown" = "Unknown"; "Unknown action." = "Unknown action."; "Unknown form action." = "Unknown form action."; "Unknown form request." = "Unknown form request."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Use My Position"; "Users" = "Users"; "Uzbekistan" = "Uzbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (Bolivarian Republic of)"; "Version %s" = "Version %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "View Logs"; "Virgin Islands (British)" = "Virgin Islands (British)"; "Virgin Islands (U.S.)" = "Virgin Islands (U.S.)"; "Wallis and Futuna" = "Wallis and Futuna"; "Warning" = "Warning"; "Western Sahara" = "Western Sahara"; "Wi-Fi Configuration" = "Wi-Fi Configuration"; "Wi-Fi Network" = "Wi-Fi Network"; "Width" = "Width"; "Wrong old password." = "Wrong old password."; "Yemen" = "Yemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Number of Copies"; "default printer" = "default printer"; "finishings" = "Finisher"; "finishings.10" = "Fold"; "finishings.100" = "Z fold"; "finishings.101" = "Engineering Z fold"; "finishings.11" = "Cut"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Staple top left"; "finishings.21" = "Staple bottom left"; "finishings.22" = "Staple top right"; "finishings.23" = "Staple bottom right"; "finishings.24" = "Edge stitch left"; "finishings.25" = "Edge stitch top"; "finishings.26" = "Edge stitch right"; "finishings.27" = "Edge stitch bottom"; "finishings.28" = "2 staples on left"; "finishings.29" = "2 staples on top"; "finishings.3" = "None"; "finishings.30" = "2 staples on right"; "finishings.31" = "2 staples on bottom"; "finishings.32" = "3 staples on left"; "finishings.33" = "3 staples on top"; "finishings.34" = "3 staples on right"; "finishings.35" = "3 staples on bottom"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind left"; "finishings.51" = "Bind top"; "finishings.52" = "Bind right"; "finishings.53" = "Bind bottom"; "finishings.6" = "Cover"; "finishings.60" = "Cut after every page"; "finishings.61" = "Cut after every document"; "finishings.62" = "Cut after every set"; "finishings.63" = "Cut after job"; "finishings.7" = "Bind"; "finishings.70" = "Punch top left"; "finishings.71" = "Punch bottom left"; "finishings.72" = "Punch top right"; "finishings.73" = "Punch bottom right"; "finishings.74" = "2-hole punch left"; "finishings.75" = "2-hole punch top"; "finishings.76" = "2-hole punch right"; "finishings.77" = "2-hole punch bottom"; "finishings.78" = "3-hole punch left"; "finishings.79" = "3-hole punch top"; "finishings.8" = "Saddle stitch"; "finishings.80" = "3-hole punch right"; "finishings.81" = "3-hole punch bottom"; "finishings.82" = "4-hole punch left"; "finishings.83" = "4-hole punch top"; "finishings.84" = "4-hole punch right"; "finishings.85" = "4-hole punch bottom"; "finishings.86" = "Multi-hole punch left"; "finishings.87" = "Multi-hole punch top"; "finishings.88" = "Multi-hole punch right"; "finishings.89" = "Multi-hole punch bottom"; "finishings.9" = "Edge stitch"; "finishings.90" = "Accordion fold"; "finishings.91" = "Double gate fold"; "finishings.92" = "Gate fold"; "finishings.93" = "Half fold"; "finishings.94" = "Half Z fold"; "finishings.95" = "Left gate fold"; "finishings.96" = "Letter fold"; "finishings.97" = "Parallel fold"; "finishings.98" = "Poster fold"; "finishings.99" = "Right gate fold"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Stopping."; "job-state-reasons.compression-error" = "Decompression error."; "job-state-reasons.document-format-error" = "Document format error."; "job-state-reasons.document-password-error" = "Document password error."; "job-state-reasons.document-permission-error" = "Document permission error."; "job-state-reasons.document-unprintable-error" = "Document unprintable error."; "job-state-reasons.errors-detected" = "Errors detected."; "job-state-reasons.job-canceled-at-device" = "Canceled at printer."; "job-state-reasons.job-canceled-by-user" = "Canceled by user."; "job-state-reasons.job-completed-successfully" = "Printed."; "job-state-reasons.job-completed-with-errors" = "Printed with errors."; "job-state-reasons.job-completed-with-warnings" = "Printed with warnings."; "job-state-reasons.job-data-insufficient" = "Insufficient data."; "job-state-reasons.job-fetchable" = "Fetchable."; "job-state-reasons.job-incoming" = "Incoming."; "job-state-reasons.job-printing" = "Printing."; "job-state-reasons.job-queued" = "Preparing to print."; "job-state-reasons.job-spooling" = "Spooling."; "job-state-reasons.none" = "Pending."; "job-state-reasons.printer-stopped" = "Printer offline."; "job-state-reasons.printer-stopped-partly" = "Printer partially stopped."; "job-state-reasons.processing-to-stop-point" = "Stopping."; "job-state-reasons.queued-in-device" = "Ready."; "job-state-reasons.warnings-detected" = "Warnings detected."; "job-state.3" = "Pending"; "job-state.4" = "Held"; "job-state.5" = "Processing"; "job-state.6" = "Stopped"; "job-state.7" = "Canceled"; "job-state.8" = "Aborted"; "job-state.9" = "Completed"; "joining" = "joining"; "media" = "Media"; "media-col" = "Media"; "media-size" = "Media Size"; "media-size-name" = "Media Size"; "media-source" = "Input Tray"; "media-source.alternate" = "Alternate"; "media-source.alternate-roll" = "Alternate roll"; "media-source.auto" = "Automatic"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Multipurpose tray"; "media-source.center" = "Center"; "media-source.disc" = "Disc"; "media-source.envelope" = "Envelope"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Large capacity"; "media-source.left" = "Left"; "media-source.main" = "Main"; "media-source.main-roll" = "Main roll"; "media-source.manual" = "Manual"; "media-source.middle" = "Middle"; "media-source.photo" = "Photo"; "media-source.rear" = "Rear"; "media-source.right" = "Right"; "media-source.roll-1" = "Roll 1"; "media-source.roll-10" = "Roll 10"; "media-source.roll-2" = "Roll 2"; "media-source.roll-3" = "Roll 3"; "media-source.roll-4" = "Roll 4"; "media-source.roll-5" = "Roll 5"; "media-source.roll-6" = "Roll 6"; "media-source.roll-7" = "Roll 7"; "media-source.roll-8" = "Roll 8"; "media-source.roll-9" = "Roll 9"; "media-source.side" = "Side"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Media Tracking"; "media-tracking.continuous" = "Continuous"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Media Type"; "media-type.aluminum" = "Aluminum"; "media-type.auto" = "Automatic"; "media-type.back-print-film" = "Back print film"; "media-type.cardboard" = "Cardboard"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuous"; "media-type.continuous-long" = "Continuous long"; "media-type.continuous-short" = "Continuous short"; "media-type.corrugated-board" = "Corrugated board"; "media-type.disc" = "Optical disc"; "media-type.disc-glossy" = "Glossy optical disc"; "media-type.disc-high-gloss" = "High gloss optical disc"; "media-type.disc-matte" = "Matte optical disc"; "media-type.disc-satin" = "Satin optical disc"; "media-type.disc-semi-gloss" = "Semi-gloss optical disc"; "media-type.double-wall" = "Double wall"; "media-type.dry-film" = "Dry film"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Embossing foil"; "media-type.end-board" = "End board"; "media-type.envelope" = "Envelope"; "media-type.envelope-archival" = "Archival envelope"; "media-type.envelope-bond" = "Bond envelope"; "media-type.envelope-coated" = "Coated envelope"; "media-type.envelope-cotton" = "Cotton envelope"; "media-type.envelope-fine" = "Fine envelope"; "media-type.envelope-heavyweight" = "Heavyweight envelope"; "media-type.envelope-inkjet" = "Inkjet envelope"; "media-type.envelope-lightweight" = "Lightweight envelope"; "media-type.envelope-plain" = "Plain envelope"; "media-type.envelope-preprinted" = "Preprinted envelope"; "media-type.envelope-window" = "Windowed envelope"; "media-type.fabric" = "Fabric"; "media-type.fabric-archival" = "Archival fabric"; "media-type.fabric-glossy" = "Glossy fabric"; "media-type.fabric-high-gloss" = "High gloss fabric"; "media-type.fabric-matte" = "Matte fabric"; "media-type.fabric-semi-gloss" = "Semi-gloss fabric"; "media-type.fabric-waterproof" = "Waterproof fabric"; "media-type.film" = "Film"; "media-type.flexo-base" = "Flexo base"; "media-type.flexo-photo-polymer" = "Flexo photo polymer"; "media-type.flute" = "Flute"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "Full cut tabs"; "media-type.glass" = "Glass"; "media-type.glass-colored" = "Glass colored"; "media-type.glass-opaque" = "Glass opaque"; "media-type.glass-surfaced" = "Glass surfaced"; "media-type.glass-textured" = "Glass textured"; "media-type.gravure-cylinder" = "Gravure cylinder"; "media-type.image-setter-paper" = "Image setter paper"; "media-type.imaging-cylinder" = "Imaging cylinder"; "media-type.labels" = "Labels"; "media-type.labels-colored" = "Colored labels"; "media-type.labels-glossy" = "Glossy labels"; "media-type.labels-high-gloss" = "High gloss labels"; "media-type.labels-inkjet" = "Inkjet labels"; "media-type.labels-matte" = "Matte labels"; "media-type.labels-permanent" = "Permanent labels"; "media-type.labels-satin" = "Satin labels"; "media-type.labels-security" = "Security labels"; "media-type.labels-semi-gloss" = "Semi-gloss labels"; "media-type.laminating-foil" = "Laminating foil"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal glossy"; "media-type.metal-high-gloss" = "Metal high gloss"; "media-type.metal-matte" = "Metal matte"; "media-type.metal-satin" = "Metal satin"; "media-type.metal-semi-gloss" = "Metal semi gloss"; "media-type.mounting-tape" = "Mounting tape"; "media-type.multi-layer" = "Multi layer"; "media-type.multi-part-form" = "Multi part form"; "media-type.other" = "Other"; "media-type.paper" = "Paper"; "media-type.photographic" = "Photo paper"; "media-type.photographic-archival" = "Photographic archival"; "media-type.photographic-film" = "Photo film"; "media-type.photographic-glossy" = "Glossy photo paper"; "media-type.photographic-high-gloss" = "High gloss photo paper"; "media-type.photographic-matte" = "Matte photo paper"; "media-type.photographic-satin" = "Satin photo paper"; "media-type.photographic-semi-gloss" = "Semi-gloss photo paper"; "media-type.plastic" = "Plastic"; "media-type.plastic-archival" = "Plastic archival"; "media-type.plastic-colored" = "Plastic colored"; "media-type.plastic-glossy" = "Plastic glossy"; "media-type.plastic-high-gloss" = "Plastic high gloss"; "media-type.plastic-matte" = "Plastic matte"; "media-type.plastic-satin" = "Plastic satin"; "media-type.plastic-semi-gloss" = "Plastic semi gloss"; "media-type.plate" = "Plate"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "Pre cut tabs"; "media-type.roll" = "Roll"; "media-type.screen" = "Screen"; "media-type.screen-paged" = "Screen paged"; "media-type.self-adhesive" = "Self adhesive"; "media-type.self-adhesive-film" = "Self adhesive film"; "media-type.shrink-foil" = "Shrink foil"; "media-type.single-face" = "Single face"; "media-type.single-wall" = "Single wall"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Stationery"; "media-type.stationery-archival" = "Stationery archival"; "media-type.stationery-coated" = "Coated paper"; "media-type.stationery-cotton" = "Stationery cotton"; "media-type.stationery-fine" = "Vellum paper"; "media-type.stationery-heavyweight" = "Heavyweight paper"; "media-type.stationery-heavyweight-coated" = "Stationery heavyweight coated"; "media-type.stationery-inkjet" = "Stationery inkjet paper"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Lightweight paper"; "media-type.stationery-preprinted" = "Preprinted paper"; "media-type.stationery-prepunched" = "Punched paper"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transfer"; "media-type.transparency" = "Transparency"; "media-type.triple-wall" = "Triple wall"; "media-type.wet-film" = "Wet film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 or US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Envelope"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Envelope"; "media.iso_c10_28x40mm" = "C10 Envelope"; "media.iso_c1_648x917mm" = "C1 Envelope"; "media.iso_c2_458x648mm" = "C2 Envelope"; "media.iso_c3_324x458mm" = "C3 Envelope"; "media.iso_c4_229x324mm" = "C4 Envelope"; "media.iso_c5_162x229mm" = "C5 Envelope"; "media.iso_c6_114x162mm" = "C6 Envelope"; "media.iso_c6c5_114x229mm" = "C6/C5 Envelope"; "media.iso_c7_81x114mm" = "C7 Envelope"; "media.iso_c7c6_81x162mm" = "C7/C6 Envelope"; "media.iso_c8_57x81mm" = "C8 Envelope"; "media.iso_c9_40x57mm" = "C9 Envelope"; "media.iso_dl_110x220mm" = "DL Envelope"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Envelope Chou 2"; "media.jpn_chou3_120x235mm" = "Envelope Chou 3"; "media.jpn_chou40_90x225mm" = "Envelope Chou 40"; "media.jpn_chou4_90x205mm" = "Envelope Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Envelope Kahu"; "media.jpn_kaku2_240x332mm" = "Envelope Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Reply Postcard"; "media.jpn_you4_105x235mm" = "Envelope You 4"; "media.na_a2_4.375x5.75in" = "Envelope A2"; "media.na_c5_6.5x9.5in" = "Envelope C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "US Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "Statement"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US Letter (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US Letter (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Envelope Monarch"; "media.na_number-10_4.125x9.5in" = "Envelope #10"; "media.na_number-11_4.5x10.375in" = "Envelope #11"; "media.na_number-12_4.75x11in" = "Envelope #12"; "media.na_number-14_5x11.5in" = "Envelope #14"; "media.na_number-9_3.875x8.875in" = "Envelope #9"; "media.na_personal_3.625x6.5in" = "Envelope Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Envelope Invitation"; "media.om_italian_110x230mm" = "Envelope Italian"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389mm"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Envelope chinese #10"; "media.prc_16k_146x215mm" = "Chinese 16k"; "media.prc_1_102x165mm" = "Envelope chinese #1"; "media.prc_2_102x176mm" = "Envelope chinese #2"; "media.prc_32k_97x151mm" = "Chinese 32k"; "media.prc_3_125x176mm" = "Envelope chinese #3"; "media.prc_4_110x208mm" = "Envelope chinese #4"; "media.prc_5_110x220mm" = "Envelope chinese #5"; "media.prc_6_120x320mm" = "Envelope chinese #6"; "media.prc_7_160x230mm" = "Envelope chinese #7"; "media.prc_8_120x309mm" = "Envelope chinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "not configured"; "not visible" = "not visible"; "off" = "off"; "on" = "on"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Landscape"; "orientation-requested.5" = "Reverse landscape"; "orientation-requested.6" = "Reverse portrait"; "orientation-requested.7" = "None"; "output-bin" = "Output Tray"; "output-bin.auto" = "Automatic"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Face down"; "output-bin.face-up" = "Face up"; "output-bin.large-capacity" = "Large capacity"; "output-bin.left" = "Left"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Middle"; "output-bin.my-mailbox" = "My mailbox"; "output-bin.rear" = "Rear"; "output-bin.right" = "Right"; "output-bin.side" = "Side"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Print Mode"; "print-color-mode.auto" = "Automatic"; "print-color-mode.auto-monochrome" = "Auto monochrome"; "print-color-mode.bi-level" = "Text"; "print-color-mode.color" = "Color"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monochrome"; "print-color-mode.process-bi-level" = "Process Text"; "print-color-mode.process-monochrome" = "Process monochrome"; "print-content-optimize" = "Optimize For"; "print-content-optimize.auto" = "Automatic"; "print-content-optimize.graphic" = "Graphics"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text and graphics"; "print-darkness" = "Print Darkness"; "print-quality" = "Print Quality"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Best"; "print-scaling" = "Scaling"; "print-scaling.auto" = "Automatic"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Fill"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "None"; "print-speed" = "Print Speed"; "printer-resolution" = "Resolution"; "printer-state-reasons.cover-open" = "Cover open."; "printer-state-reasons.door-open" = "Door open."; "printer-state-reasons.identify-printer-requested" = "Identify printer."; "printer-state-reasons.input-tray-missing" = "Paper tray missing."; "printer-state-reasons.marker-supply-empty" = "Out of ink."; "printer-state-reasons.marker-supply-low" = "Low ink."; "printer-state-reasons.marker-waste-almost-full" = "Waste bin almost full."; "printer-state-reasons.marker-waste-full" = "Waste bin full."; "printer-state-reasons.media-empty" = "Out of paper."; "printer-state-reasons.media-jam" = "Paper jam."; "printer-state-reasons.media-low" = "Replace paper soon."; "printer-state-reasons.media-needed" = "Load paper."; "printer-state-reasons.none" = "Ready."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "See printer."; "printer-state-reasons.spool-area-full" = "Printer busy."; "printer-state-reasons.toner-empty" = "Out of toner."; "printer-state-reasons.toner-low" = "Toner low."; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "sides" = "2-Sided Printing"; "sides.one-sided" = "Off"; "sides.two-sided-long-edge" = "On (portrait)"; "sides.two-sided-short-edge" = "On (landscape)"; "unable to join" = "unable to join"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Åland Islands"; pappl-1.4.9/pappl/client-accessors.c000066400000000000000000000214321476704353100173760ustar00rootroot00000000000000// // Client accessor functions for the Printer Application Framework // // Copyright © 2020-2021 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // 'papplClientGetCSRFToken()' - Get a unique Cross-Site Request Forgery token // string. // // This function generates and returns a unique Cross-Site Request Forgery // token string to be used as the value of a hidden variable in all HTML forms // sent in the response and then compared when validating the form data in the // subsequent request. // // The value is based on the current system session key and client address in // order to make replay attacks infeasible. // // > Note: The @link papplClientHTMLStartForm@ function automatically adds the // > hidden CSRF variable, and the @link papplClientIsValidForm@ function // > validates the value. // char * // O - Token string papplClientGetCSRFToken( pappl_client_t *client, // I - Client char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char session_key[65], // Current session key csrf_data[1024]; // CSRF data to hash unsigned char csrf_sum[32]; // SHA2-256 sum of data if (!client || !buffer || bufsize < 65) { if (buffer) *buffer = '\0'; return (NULL); } snprintf(csrf_data, sizeof(csrf_data), "%s:%s", papplSystemGetSessionKey(client->system, session_key, sizeof(session_key)), client->hostname); cupsHashData("sha2-256", csrf_data, strlen(csrf_data), csrf_sum, sizeof(csrf_sum)); cupsHashString(csrf_sum, sizeof(csrf_sum), buffer, bufsize); return (buffer); } // // 'papplClientGetHostName()' - Get the hostname from the client-supplied Host: // field. // // This function returns the hostname that was used in the request and should // be used in any URLs or URIs that you generate. // const char * // O - Hostname or `NULL` for none papplClientGetHostName( pappl_client_t *client) // I - Client { return (client ? client->host_field : NULL); } // // 'papplClientGetHostPort()' - Get the port from the client-supplied Host: // field. // // This function returns the port number that was used in the request and should // be used in any URLs or URIs that you generate. // int // O - Port number or `0` for none papplClientGetHostPort( pappl_client_t *client) // I - Client { return (client ? client->host_port : 0); } // // 'papplClientGetHTTP()' - Get the HTTP connection associated with a client // object. // // This function returns the HTTP connection associated with the client and is // used when sending response data directly to the client using the CUPS // `httpXxx` functions. // http_t * // O - HTTP connection papplClientGetHTTP( pappl_client_t *client) // I - Client { return (client ? client->http : NULL); } // // 'papplClientGetJob()' - Get the target job for an IPP request. // // This function returns the job associated with the current IPP request. // `NULL` is returned if the request does not target a job. // pappl_job_t * // O - Target job or `NULL` if none papplClientGetJob( pappl_client_t *client) // I - Client { return (client ? client->job : NULL); } // // 'papplClientGetMethod()' - Get the HTTP request method. // // This function returns the HTTP request method that was used, for example // `HTTP_STATE_GET` for a GET request or `HTTP_STATE_POST` for a POST request. // http_state_t // O - HTTP method papplClientGetMethod( pappl_client_t *client) // I - Client { return (client ? client->operation : HTTP_STATE_ERROR); } // // 'papplClientGetOperation()' - Get the IPP operation code. // // This function returns the IPP operation code associated with the current IPP // request. // ipp_op_t // O - IPP operation code papplClientGetOperation( pappl_client_t *client) // I - Client { return (client ? client->operation_id : IPP_OP_CUPS_NONE); } // // 'papplClientGetOptions()' - Get the options from the request URI. // // This function returns any options that were passed in the HTTP request URI. // The options are the characters after the "?" character, for example a // request URI of "/mypage?name=value" will have an options string of // "name=value". // // `NULL` is returned if the request URI did not contain any options. // // > Note: HTTP GET form variables are normally accessed using the // > @link papplClientGetForm@ function. This function should only be used when // > getting non-form data. // const char * // O - Options or `NULL` if none papplClientGetOptions( pappl_client_t *client) // I - Client { return (client ? client->options : NULL); } // // 'papplClientGetPrinter()' - Get the target printer for an IPP request. // // This function returns the printer associated with the current IPP request. // `NULL` is returned if the request does not target a printer. // pappl_printer_t * // O - Target printer or `NULL` if none papplClientGetPrinter( pappl_client_t *client) // I - Client { return (client ? client->printer : NULL); } // // 'papplClientGetRequest()' - Get the IPP request message. // // This function returns the attributes in the current IPP request, for use // with the CUPS `ippFindAttribute`, `ippFindNextAttribute`, // `ippFirstAttribute`, and `ippNextAttribute` functions. // ipp_t * // O - IPP request message papplClientGetRequest( pappl_client_t *client) // I - Client { return (client ? client->request : NULL); } // // 'papplClientGetResponse()' - Get the IPP response message. // // This function returns the attributes in the current IPP response, for use // with the CUPS `ippAddXxx` and `ippSetXxx` functions. Use the // @link papplClientRespondIPP@ function to set the status code and message, // if any. // ipp_t * // O - IPP response message papplClientGetResponse( pappl_client_t *client) // I - Client { return (client ? client->response : NULL); } // // 'papplClientGetSystem()' - Get the containing system for the client. // // This function returns the system object that contains the client. // pappl_system_t * // O - System papplClientGetSystem( pappl_client_t *client) // I - Client { return (client ? client->system : NULL); } // // 'papplClientGetURI()' - Get the HTTP request URI. // // This function returns the URI that was sent in the current HTTP request. // // > Note: Any options in the URI are removed and can be accessed separately // > using the @link papplClientGetOptions@ function. // const char * // O - Request URI papplClientGetURI( pappl_client_t *client) // I - Client { return (client ? client->uri : NULL); } // // 'papplClientGetUsername()' - Get the authenticated username, if any. // // This function returns the current authenticated username, if any. // const char * // O - Authenticated username or `NULL` if none papplClientGetUsername( pappl_client_t *client) // I - Client { return (client && client->username[0] ? client->username : NULL); } // // '_papplClientGetAuthWebScheme()' - Get the URI scheme to use for potentially authenticated web page links. // const char * // O - "http" or "https" _papplClientGetAuthWebScheme( pappl_client_t *client) // I - Client { if (!client || (papplSystemGetOptions(client->system) & PAPPL_SOPTIONS_NO_TLS)) { // Use HTTP if TLS is disabled... return ("http"); } else if (papplSystemGetTLSOnly(client->system)) { // Use HTTPS if non-TLS is disabled... return ("https"); } else if (httpAddrIsLocalhost(httpGetAddress(client->http))) { // Use HTTP over loopback interface... return ("http"); } else if (client->system->auth_service || client->system->auth_cb || client->system->password_hash[0]) { // Use HTTPS since some form of authentication is used... return ("https"); } else { // Use HTTP since no authentication is used... return ("http"); } } // // 'papplClientIsEncrypted()' - Return whether a Client connection is encrypted. // // This function returns a boolean value indicating whether a Client connection // is encrypted with TLS. // bool // O - `true` if encrypted, `false` otherwise papplClientIsEncrypted( pappl_client_t *client) // I - Client { return (client ? httpIsEncrypted(client->http) : false); } // // 'papplClientSetUsername()' - Set the authenticated username, if any. // // This function sets the current authenticated username, if any. // void papplClientSetUsername( pappl_client_t *client, // I - Client const char *username) // I - Username or `NULL` for none { if (client) { if (username) papplCopyString(client->username, username, sizeof(client->username)); else client->username[0] = '\0'; } } pappl-1.4.9/pappl/client-auth.c000066400000000000000000000251111476704353100163500ustar00rootroot00000000000000// // Authentication support for the Printer Application Framework // // Copyright © 2017-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "client-private.h" #include "system-private.h" #if !_WIN32 # include #endif // !_WIN32 #ifdef HAVE_LIBPAM # ifdef HAVE_PAM_PAM_APPL_H # include # else # include # endif // HAVE_PAM_PAM_APPL_H #endif // HAVE_LIBPAM // // Types... // typedef struct _pappl_authdata_s // PAM authentication data { const char *username, // Username string *password; // Password string } _pappl_authdata_t; // // Local functions... // static int pappl_authenticate_user(pappl_client_t *client, const char *username, const char *password); #ifdef HAVE_LIBPAM static int pappl_pam_func(int num_msg, const struct pam_message **msg, struct pam_response **resp, _pappl_authdata_t *data); #endif // HAVE_LIBPAM // // 'papplClientIsAuthorized()' - Determine whether a client is authorized for // administrative requests. // // This function determines whether a client is authorized to submit an // administrative request. // // The return value is `HTTP_STATUS_CONTINUE` if access is authorized, // `HTTP_STATUS_FORBIDDEN` if access is not allowed, `HTTP_STATUS_UNAUTHORIZED` // if authorization is required, or `HTTP_STATUS_UPGRADE_REQUIRED` if the // connection needs to be encrypted. All of these values can be passed to the // @link papplClientRespond@ function. // http_status_t // O - HTTP status papplClientIsAuthorized( pappl_client_t *client) // I - Client { char admin_group[256]; // Admin group name gid_t admin_gid; // Admin group ID // Range check input... if (!client) return (HTTP_STATUS_BAD_REQUEST); // Authorize for admin access... _papplRWLockRead(client->system); if (client->system->admin_group) papplCopyString(admin_group, client->system->admin_group, sizeof(admin_group)); else admin_group[0] = '\0'; admin_gid = client->system->admin_gid; _papplRWUnlock(client->system); return (_papplClientIsAuthorizedForGroup(client, false, admin_group, admin_gid)); } // // '_papplClientIsAuthorizedForGroup()' - Determine whether a client is authorized for the named group. // http_status_t // O - HTTP status _papplClientIsAuthorizedForGroup( pappl_client_t *client, // I - Client bool allow_remote, // I - Allow remote access? const char *group, // I - Group name, if any gid_t groupid) // I - Group ID, if any { const char *authorization; // Authorization: header value // Local access is always allowed... #if !_WIN32 if (httpAddrGetFamily(httpGetAddress(client->http)) == AF_LOCAL) return (HTTP_STATUS_CONTINUE); #endif // !_WIN32 if ((allow_remote || httpAddrIsLocalhost(httpGetAddress(client->http))) && !client->system->auth_service && !client->system->auth_cb) return (HTTP_STATUS_CONTINUE); // Remote access is only allowed if an authentication service is configured... if (!client->system->auth_service && !client->system->auth_cb) return (HTTP_STATUS_FORBIDDEN); // Remote admin access requires encryption... if (!httpIsEncrypted(client->http) && !httpAddrIsLocalhost(httpGetAddress(client->http))) return (HTTP_STATUS_UPGRADE_REQUIRED); if (client->system->auth_cb) { // Use the authentication callback... return ((client->system->auth_cb)(client, group, groupid, client->system->auth_cbdata)); } // Get the authorization header... if ((authorization = httpGetField(client->http, HTTP_FIELD_AUTHORIZATION)) != NULL && *authorization) { if (!strncmp(authorization, "Basic ", 6)) { // Basic authentication... char username[512], // Username value *password; // Password value cups_b64len_t userlen = sizeof(username); // Length of username:password #if !_WIN32 struct passwd *user, // User information udata; // User data char ubuffer[16384]; // User strings int num_groups; // Number of authenticated groups, if any # ifdef __APPLE__ int groups[128]; // Authenticated groups, if any # else gid_t groups[128]; // Authenticated groups, if any # endif // __APPLE__ #endif // !_WIN32 for (authorization += 6; *authorization && isspace(*authorization & 255); authorization ++) ; // Skip whitespace httpDecode64(username, &userlen, authorization, NULL); if ((password = strchr(username, ':')) != NULL) { *password++ = '\0'; // Authenticate the username and password... if (pappl_authenticate_user(client, username, password)) { // Return now if there is no group for authorization... if (!group || !*group) return (HTTP_STATUS_CONTINUE); #if _WIN32 // No groups in stock Windows support... return (HTTP_STATUS_CONTINUE); #else // Get the user information (groups, etc.) if (!getpwnam_r(username, &udata, ubuffer, sizeof(ubuffer), &user) && user) { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Authenticated as \"%s\" using Basic.", username); papplCopyString(client->username, username, sizeof(client->username)); num_groups = (int)(sizeof(groups) / sizeof(groups[0])); # ifdef __APPLE__ if (getgrouplist(username, (int)user->pw_gid, groups, &num_groups) < 0) # else if (getgrouplist(username, user->pw_gid, groups, &num_groups) < 0) # endif // __APPLE__ { papplLogClient(client, PAPPL_LOGLEVEL_WARN, "User '%s' is in more than %d groups.", username, (int)(sizeof(groups) / sizeof(groups[0]))); # ifdef __GLIBC__ num_groups = (int)(sizeof(groups) / sizeof(groups[0])); # endif // __GLIBC__ } // Check group membership... if (groupid != (gid_t)-1) { if (user->pw_gid != groupid) { int i; // Looping var for (i = 0; i < num_groups; i ++) { if ((gid_t)groups[i] == groupid) break; } if (i >= num_groups) { // Not in the admin group, access is forbidden... return (HTTP_STATUS_FORBIDDEN); } } } // If we get this far, authentication and authorization are good... return (HTTP_STATUS_CONTINUE); } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to lookup user '%s'.", username); return (HTTP_STATUS_SERVER_ERROR); } #endif // _WIN32 } else { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Basic authentication of '%s' failed.", username); } } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad Basic Authorization header value seen."); return (HTTP_STATUS_BAD_REQUEST); } } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unsupported Authorization header value seen."); return (HTTP_STATUS_BAD_REQUEST); } } // If we get there then we don't have any authorization value we can use... return (HTTP_STATUS_UNAUTHORIZED); } // // 'pappl_authenticate_user()' - Validate a username + password combination. // static int // O - 1 if correct, 0 otherwise pappl_authenticate_user( pappl_client_t *client, // I - Client const char *username, // I - Username string const char *password) // I - Password string { int status = 0; // Return status #ifdef HAVE_LIBPAM _pappl_authdata_t data; // Authorization data pam_handle_t *pamh; // PAM authentication handle int pamerr; // PAM error code struct pam_conv pamdata; // PAM conversation data data.username = username; data.password = password; pamdata.conv = (int (*)(int, const struct pam_message **, struct pam_response **, void *))pappl_pam_func; pamdata.appdata_ptr = &data; pamh = NULL; if ((pamerr = pam_start(client->system->auth_service, data.username, &pamdata, &pamh)) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_start() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # ifdef PAM_RHOST else if ((pamerr = pam_set_item(pamh, PAM_RHOST, client->hostname)) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_set_item(PAM_RHOST) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # endif // PAM_RHOST # ifdef PAM_TTY else if ((pamerr = pam_set_item(pamh, PAM_TTY, "lprint")) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_set_item(PAM_TTY) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # endif // PAM_TTY else if ((pamerr = pam_authenticate(pamh, PAM_SILENT)) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_authenticate() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } else if ((pamerr = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT)) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_setcred() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } else if ((pamerr = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "pam_acct_mgmt() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } if (pamh) pam_end(pamh, PAM_SUCCESS); if (pamerr == PAM_SUCCESS) { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "PAM authentication of '%s' succeeded.", username); status = 1; } #endif // HAVE_LIBPAM return (status); } #ifdef HAVE_LIBPAM // // 'pappl_pam_func()' - PAM conversation function. // static int // O - Success or failure pappl_pam_func( int num_msg, // I - Number of messages const struct pam_message **msg, // I - Messages struct pam_response **resp, // O - Responses _pappl_authdata_t *data) // I - Authentication data { int i; // Looping var struct pam_response *replies; // Replies // Allocate memory for the responses... if ((replies = calloc((size_t)num_msg, sizeof(struct pam_response))) == NULL) return (PAM_CONV_ERR); // Answer all of the messages... for (i = 0; i < num_msg; i ++) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = strdup(data->username); break; case PAM_PROMPT_ECHO_OFF : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = strdup(data->password); break; default : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = NULL; break; } } // Return the responses back to PAM... *resp = replies; return (PAM_SUCCESS); } #endif // HAVE_LIBPAM pappl-1.4.9/pappl/client-ipp.c000066400000000000000000000257111476704353100162050ustar00rootroot00000000000000// // Common client IPP processing for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // '_papplClientFlushDocumentData()' - Safely flush remaining document data. // void _papplClientFlushDocumentData( pappl_client_t *client) // I - Client { char buffer[8192]; // Read buffer if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { while (httpRead(client->http, buffer, sizeof(buffer)) > 0) ; // Read all data } } // // '_papplClientHaveDocumentData()' - Determine whether we have more document data. // bool // O - `true` if data is present, `false` otherwise _papplClientHaveDocumentData( pappl_client_t *client) // I - Client { char temp; // Data if (httpGetState(client->http) != HTTP_STATE_POST_RECV) return (false); else return (httpPeek(client->http, &temp, 1) > 0); } // // '_papplClientProcessIPP()' - Process an IPP request. // bool // O - `true` on success, `false` on error _papplClientProcessIPP( pappl_client_t *client) // I - Client { ipp_tag_t group; // Current group tag ipp_attribute_t *attr; // Current attribute ipp_attribute_t *charset; // Character set attribute ipp_attribute_t *language; // Language attribute ipp_attribute_t *uri; // Printer URI attribute int major, minor; // Version number ipp_op_t op; // Operation code const char *name; // Name of attribute bool printer_op = true; // Printer operation? // First build an empty response message for this request... client->operation_id = ippGetOperation(client->request); client->response = ippNewResponse(client->request); // Then validate the request header and required attributes... major = ippGetVersion(client->request, &minor); op = ippGetOperation(client->request); _papplLogAttributes(client, ippOpString(op), client->request, false); if (major < 1 || major > 2) { // Return an error, since we only support IPP 1.x and 2.x. papplClientRespondIPP(client, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, "Bad request version number %d.%d.", major, minor); } else if (ippGetRequestId(client->request) <= 0) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad request-id %d.", ippGetRequestId(client->request)); } else if (!ippGetFirstAttribute(client->request)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "No attributes in request."); } else { // Make sure that the attributes are provided in the correct order and // don't repeat groups... for (attr = ippGetFirstAttribute(client->request), group = ippGetGroupTag(attr); attr; attr = ippGetNextAttribute(client->request)) { if (ippGetGroupTag(attr) < group && ippGetGroupTag(attr) != IPP_TAG_ZERO) { // Out of order; return an error... papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Attribute groups are out of order (%x < %x).", ippGetGroupTag(attr), group); break; } else group = ippGetGroupTag(attr); } if (!attr) { // Then make sure that the first three attributes are: // // attributes-charset // attributes-natural-language // system-uri/printer-uri/job-uri attr = ippGetFirstAttribute(client->request); name = ippGetName(attr); if (attr && name && !strcmp(name, "attributes-charset") && ippGetValueTag(attr) == IPP_TAG_CHARSET) charset = attr; else charset = NULL; attr = ippGetNextAttribute(client->request); name = ippGetName(attr); if (attr && name && !strcmp(name, "attributes-natural-language") && ippGetValueTag(attr) == IPP_TAG_LANGUAGE) language = attr; else language = NULL; if ((attr = ippFindAttribute(client->request, "system-uri", IPP_TAG_URI)) != NULL) uri = attr; else if ((attr = ippFindAttribute(client->request, "printer-uri", IPP_TAG_URI)) != NULL) uri = attr; else if ((attr = ippFindAttribute(client->request, "job-uri", IPP_TAG_URI)) != NULL) uri = attr; else uri = NULL; client->printer = NULL; client->job = NULL; if (charset && strcasecmp(ippGetString(charset, 0, NULL), "us-ascii") && strcasecmp(ippGetString(charset, 0, NULL), "utf-8")) { // Bad character set... papplClientRespondIPP(client, IPP_STATUS_ERROR_CHARSET, "Unsupported character set '%s'.", ippGetString(charset, 0, NULL)); attr = ippCopyAttribute(client->response, charset, false); ippSetGroupTag(client->response, &attr, IPP_TAG_UNSUPPORTED_GROUP); } else if (!charset || !language || (!uri && op != IPP_OP_CUPS_GET_DEFAULT && op != IPP_OP_CUPS_GET_PRINTERS)) { // Return an error, since attributes-charset, // attributes-natural-language, and system/printer/job-uri are required // for all operations. papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required attributes."); } else { if (uri) { char scheme[32], // URI scheme userpass[32], // Username/password in URI host[256], // Host name in URI resource[256], // Resource path in URI *resptr; // Pointer into resource int port, // Port number in URI job_id; // Job ID name = ippGetName(uri); if (httpSeparateURI(HTTP_URI_CODING_ALL, ippGetString(uri, 0, NULL), scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Bad %s value '%s'.", name, ippGetString(uri, 0, NULL)); } else if (!strcmp(name, "system-uri")) { printer_op = false; if (strcmp(resource, "/ipp/system")) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Bad %s value '%s'.", name, ippGetString(uri, 0, NULL)); } else client->printer = papplSystemFindPrinter(client->system, NULL, ippGetInteger(ippFindAttribute(client->request, "printer-id", IPP_TAG_INTEGER), 0), NULL); } else if ((client->printer = papplSystemFindPrinter(client->system, resource, 0, NULL)) != NULL) { if (!strcmp(name, "job-uri") && (resptr = strrchr(resource, '/')) != NULL) { char *endptr; // Pointer after job ID job_id = (int)strtol(resptr + 1, &endptr, 10); if (errno == ERANGE || *endptr) job_id = 0; } else job_id = ippGetInteger(ippFindAttribute(client->request, "job-id", IPP_TAG_INTEGER), 0); if (job_id) { if ((client->job = papplPrinterFindJob(client->printer, job_id)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "job-id %d not found.", job_id); } } } else { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "%s %s not found.", name, ippGetString(uri, 0, NULL)); } } else printer_op = false; if (ippGetStatusCode(client->response) == IPP_STATUS_OK) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "IPP/%d.%d %s (%s)", major, minor, ippOpString(op), httpGetField(client->http, HTTP_FIELD_USER_AGENT)); if (printer_op) { // Process job or printer operation... if (client->job) _papplJobProcessIPP(client); else _papplPrinterProcessIPP(client); } else { // Process system operation... _papplSystemProcessIPP(client); } } } } } // Send the HTTP header and return... if (httpGetState(client->http) != HTTP_STATE_POST_SEND) { // Flush trailing (junk) data _papplClientFlushDocumentData(client); } if (httpGetState(client->http) != HTTP_STATE_WAITING) return (papplClientRespond(client, HTTP_STATUS_OK, NULL, "application/ipp", 0, ippGetLength(client->response))); else return (true); } // // 'papplClientRespondIPP()' - Send an IPP response. // // This function sets the return status for an IPP request and returns the // current IPP response message. The "status" and "message" arguments replace // any existing status-code and "status-message" attribute value that may be // already present in the response. // // > Note: You should call this function prior to adding any response // > attributes. // ipp_t * // O - IPP response message papplClientRespondIPP( pappl_client_t *client, // I - Client ipp_status_t status, // I - status-code const char *message, // I - printf-style status-message ...) // I - Additional args as needed { const char *formatted = NULL; // Formatted message if (status > ippGetStatusCode(client->response)) ippSetStatusCode(client->response, status); if (message) { va_list ap; // Pointer to additional args ipp_attribute_t *attr; // New status-message attribute va_start(ap, message); if ((attr = ippFindAttribute(client->response, "status-message", IPP_TAG_TEXT)) != NULL) ippSetStringfv(client->response, &attr, 0, message, ap); else attr = ippAddStringfv(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, "status-message", NULL, message, ap); va_end(ap); formatted = ippGetString(attr, 0, NULL); } if (formatted) papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s (%s)", ippOpString(client->operation_id), ippErrorString(status), formatted); else papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s", ippOpString(client->operation_id), ippErrorString(status)); return (client->response); } // // '_papplClientRespondIPPIgnored()' - Respond with an ignored IPP attribute. // // This function returns a 'successful-ok-ignored-or-substituted-attributes' // status code and adds the specified attribute to the unsupported attributes // group in the response. // void _papplClientRespondIPPIgnored( pappl_client_t *client, // I - Client ipp_attribute_t *attr) // I - Attribute { ipp_attribute_t *temp; // Copy of attribute papplClientRespondIPP(client, IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED, "Ignoring unsupported %s %s%s value.", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr))); temp = ippCopyAttribute(client->response, attr, false); ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP); } // // 'papplClientRespondIPPUnsupported()' - Respond with an unsupported IPP attribute. // // This function returns a 'client-error-attributes-or-values-not-supported' // status code and adds the specified attribute to the unsupported attributes // group in the response. // void papplClientRespondIPPUnsupported( pappl_client_t *client, // I - Client ipp_attribute_t *attr) // I - Attribute { ipp_attribute_t *temp; // Copy of attribute papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Unsupported %s %s%s value.", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr))); temp = ippCopyAttribute(client->response, attr, 0); ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP); } pappl-1.4.9/pappl/client-loc.c000066400000000000000000000066721476704353100161770ustar00rootroot00000000000000// // Client localization functions for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "client-private.h" #include "loc-private.h" // // 'papplClientGetLoc()' - Get the localization data for a client connection. // pappl_loc_t * // O - Localization data to use papplClientGetLoc( pappl_client_t *client) // I - Client { // Range check input... if (!client) return (NULL); if (!client->loc) { const char *language; // Language name char temp[7], // Temporary language string *ptr; // Pointer into temp string // Look up language if ((language = ippGetString(ippFindAttribute(client->request, "attributes-natural-language", IPP_TAG_LANGUAGE), 0, NULL)) != NULL) { // Use IPP language specification... papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Using IPP language code '%s' for localization.", language); if ((client->loc = papplSystemFindLoc(client->system, language)) == NULL && language[2]) { // Try the generic localization... papplCopyString(temp, language, sizeof(temp)); temp[2] = '\0'; client->loc = papplSystemFindLoc(client->system, temp); } if (client->loc) papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Using language '%s'.", client->loc->name); } else if (client->language[0]) { // Parse language string... language = client->language; papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Using HTTP Accept-Language value '%s' for localization.", language); while (*language) { // Grab the next language code. The format (from RFC 7231) is: // // lang-code[;q=#][,...,land-code[;q=#]] for (ptr = temp; *language && *language != ';' && *language != ','; language ++) { if (ptr < (temp + sizeof(temp) - 1)) *ptr++ = *language; } *ptr = '\0'; if (*language == ';') { // Skip "quality" parameter... while (*language && *language != ',') language ++; } if (*language == ',') { // Skip comma and whitespace... language ++; while (*language && isspace(*language & 255)) language ++; } // Look up the language... if ((client->loc = papplSystemFindLoc(client->system, temp)) != NULL) break; // If the lookup failed and this is a regional language request, try // the generic localization for that language... if (temp[2]) { // Truncate after the 2-digit language code... temp[2] = '\0'; if ((client->loc = papplSystemFindLoc(client->system, temp)) != NULL) break; } } if (client->loc) papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Using language '%s'.", client->loc->name); } else { // Use default language... papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Using default language 'en'."); client->loc = papplSystemFindLoc(client->system, "en"); } } return (client->loc); } // // 'papplClientGetLocString()' - Get a localized string for the client. // const char * // O - Localized string papplClientGetLocString( pappl_client_t *client, // I - Client const char *s) // I - String to localize { // Range check input... if (!client) return (NULL); if (client->loc) return (papplLocGetString(client->loc, s)); else return (papplLocGetString(papplClientGetLoc(client), s)); } pappl-1.4.9/pappl/client-private.h000066400000000000000000000055401476704353100170720ustar00rootroot00000000000000// // Private client header file for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_CLIENT_PRIVATE_H_ # define _PAPPL_CLIENT_PRIVATE_H_ # include "base-private.h" # include "client.h" # include "log.h" // // Client structure... // struct _pappl_client_s // Client data { pappl_system_t *system; // Containing system int number; // Connection number pthread_t thread_id; // Thread ID http_t *http; // HTTP connection ipp_t *request, // IPP request *response; // IPP response time_t start; // Request start time http_state_t operation; // Request operation ipp_op_t operation_id; // IPP operation-id char uri[1024], // Request URI *options, // URI options host_field[HTTP_MAX_VALUE]; // Host: header int host_port; // Port number from Host: header http_addr_t addr; // Client address char hostname[256]; // Client hostname char username[256]; // Authenticated username, if any char language[256]; // Accept-Language value, if any pappl_printer_t *printer; // Printer, if any pappl_job_t *job; // Job, if any pappl_loc_t *loc; // Localization, if any int num_files; // Number of temporary files char *files[10]; // Temporary files }; // // Functions... // extern void _papplClientCleanTempFiles(pappl_client_t *client) _PAPPL_PRIVATE; extern pappl_client_t *_papplClientCreate(pappl_system_t *system, int sock) _PAPPL_PRIVATE; extern char *_papplClientCreateTempFile(pappl_client_t *client, const void *data, size_t datasize) _PAPPL_PRIVATE; extern void _papplClientDelete(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplClientFlushDocumentData(pappl_client_t *client) _PAPPL_PRIVATE; extern const char *_papplClientGetAuthWebScheme(pappl_client_t *client) _PAPPL_PRIVATE; extern bool _papplClientHaveDocumentData(pappl_client_t *client) _PAPPL_PRIVATE; extern http_status_t _papplClientIsAuthorizedForGroup(pappl_client_t *client, bool allow_remote, const char *group, gid_t groupid) _PAPPL_PUBLIC; extern bool _papplClientProcessHTTP(pappl_client_t *client) _PAPPL_PRIVATE; extern bool _papplClientProcessIPP(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplClientRespondIPPIgnored(pappl_client_t *client, ipp_attribute_t *attr) _PAPPL_PRIVATE; extern void *_papplClientRun(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplClientHTMLInfo(pappl_client_t *client, bool is_form, const char *dns_sd_name, const char *location, const char *geo_location, const char *organization, const char *org_unit, pappl_contact_t *contact); extern void _papplClientHTMLPutLinks(pappl_client_t *client, cups_array_t *links, pappl_loptions_t which); #endif // !_PAPPL_CLIENT_PRIVATE_H_ pappl-1.4.9/pappl/client-webif.c000066400000000000000000001316021476704353100165060ustar00rootroot00000000000000// // Core client web interface functions for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" #include // // 'papplClientGetCookie()' - Get a cookie from the client. // // This function gets a HTTP "cookie" value from the client request. `NULL` // is returned if no cookie has been set by a prior request, or if the user has // disabled or removed the cookie. // // Use the @link papplClientSetCookie@ function to set a cookie in a response // to a request. // // > Note: Cookies set with @link papplClientSetCookie@ will not be available to // > this function until the following request. // char * // O - Cookie value or `NULL` if not set papplClientGetCookie( pappl_client_t *client, // I - Client const char *name, // I - Name of cookie char *buffer, // I - Value buffer size_t bufsize) // I - Size of value buffer { const char *cookie = httpGetCookie(client->http); // Cookies from client char temp[256], // Temporary string *ptr, // Pointer into temporary string *end; // End of temporary string bool found; // Did we find it? // Make sure the buffer is initialize, and return if we don't have any // cookies... *buffer = '\0'; if (!cookie) return (NULL); // Scan the cookie string for 'name=value' or 'name="value"', separated by // semicolons... while (*cookie) { while (*cookie && isspace(*cookie & 255)) cookie ++; if (!*cookie) break; for (ptr = temp, end = temp + sizeof(temp) - 1; *cookie && *cookie != '='; cookie ++) { if (ptr < end) *ptr++ = *cookie; } if (*cookie == '=') { cookie ++; *ptr = '\0'; found = !strcmp(temp, name); if (found) { ptr = buffer; end = buffer + bufsize - 1; } else { ptr = temp; end = temp + sizeof(temp) - 1; } if (*cookie == '\"') { for (cookie ++; *cookie && *cookie != '\"'; cookie ++) { if (ptr < end) *ptr++ = *cookie; } if (*cookie == '\"') cookie ++; } else { for (; *cookie && *cookie != ';'; cookie ++) { if (ptr < end) *ptr++ = *cookie; } } *ptr = '\0'; if (found) return (buffer); else if (*cookie == ';') cookie ++; } } return (NULL); } // // 'papplClientGetForm()' - Get form data from the web client. // // For HTTP GET requests, the form data is collected from the request URI. For // HTTP POST requests, the form data is read from the client. // // The returned form values must be freed using the @code cupsFreeOptions@ // function. // // > Note: Because the form data is read from the client connection, this // > function can only be called once per request. // int // O - Number of form variables read papplClientGetForm( pappl_client_t *client, // I - Client cups_option_t **form) // O - Form variables { const char *content_type; // Content-Type header const char *boundary; // boundary value for multi-part char *body, // Message body *bodyptr, // Pointer into message body *bodyend; // End of message body size_t body_alloc, // Allocated message body size body_size = 0; // Size of message body ssize_t bytes; // Bytes read cups_len_t num_form = 0; // Number of form variables http_state_t initial_state; // Initial HTTP state if (!client || !form) { if (form) *form = NULL; return (0); } content_type = httpGetField(client->http, HTTP_FIELD_CONTENT_TYPE); if (client->operation == HTTP_STATE_GET) { // Copy form data from the request URI... if (!client->options) { *form = NULL; return (0); } if ((body = strdup(client->options)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for form data."); *form = NULL; return (0); } body_size = strlen(body); content_type = "application/x-www-form-urlencoded"; } else { // Read up to 2MB of data from the client... *form = NULL; initial_state = httpGetState(client->http); body_alloc = 65536; if ((body = malloc(body_alloc)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for form data."); *form = NULL; return (0); } for (bodyptr = body, bodyend = body + body_alloc; (bytes = httpRead(client->http, bodyptr, (size_t)(bodyend - bodyptr))) > 0; bodyptr += bytes) { body_size += (size_t)bytes; if (body_size >= body_alloc) { char *temp; // Temporary pointer size_t temp_offset; // Temporary offset if (body_alloc >= (2 * 1024 * 1024)) break; body_alloc += 65536; temp_offset = (size_t)(bodyptr - body); if ((temp = realloc(body, body_alloc)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for form data."); free(body); *form = NULL; return (0); } bodyptr = temp + temp_offset; bodyend = temp + body_alloc; body = temp; } } papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Read %ld bytes of form data (%s).", (long)body_size, content_type); // Flush remaining data... if (httpGetState(client->http) == initial_state) httpFlush(client->http); } // Parse the data in memory... bodyend = body + body_size; if (!strcmp(content_type, "application/x-www-form-urlencoded")) { // Read URL-encoded form data... char name[256], // Variable name *nameptr, // Pointer into name value[2048], // Variable value *valptr; // Pointer into value for (bodyptr = body; bodyptr < bodyend;) { // Get the name... nameptr = name; while (bodyptr < bodyend && *bodyptr != '=') { int ch = *bodyptr++; // Name character if (ch == '%' && isxdigit(bodyptr[0] & 255) && isxdigit(bodyptr[1] & 255)) { // Hex-encoded character if (isdigit(*bodyptr)) ch = (*bodyptr++ - '0') << 4; else ch = (tolower(*bodyptr++) - 'a' + 10) << 4; if (isdigit(*bodyptr)) ch |= *bodyptr++ - '0'; else ch |= tolower(*bodyptr++) - 'a' + 10; } else if (ch == '+') ch = ' '; if (nameptr < (name + sizeof(name) - 1)) *nameptr++ = (char)ch; } *nameptr = '\0'; if (bodyptr >= bodyend) break; // Get the value... bodyptr ++; valptr = value; while (bodyptr < bodyend && *bodyptr != '&') { int ch = *bodyptr++; // Name character if (ch == '%' && isxdigit(bodyptr[0] & 255) && isxdigit(bodyptr[1] & 255)) { // Hex-encoded character if (isdigit(*bodyptr)) ch = (*bodyptr++ - '0') << 4; else ch = (tolower(*bodyptr++) - 'a' + 10) << 4; if (isdigit(*bodyptr)) ch |= *bodyptr++ - '0'; else ch |= tolower(*bodyptr++) - 'a' + 10; } else if (ch == '+') ch = ' '; if (valptr < (value + sizeof(value) - 1)) *valptr++ = (char)ch; } *valptr = '\0'; if (bodyptr < bodyend) bodyptr ++; // Add the name + value to the option array... num_form = cupsAddOption(name, value, num_form, form); } } else if (!strncmp(content_type, "multipart/form-data; ", 21) && (boundary = strstr(content_type, "boundary=")) != NULL) { // Read multi-part form data... char name[1024], // Form variable name filename[1024], // Form filename bstring[256], // Boundary string to look for *bend, // End of value (boundary) *line, // Start of line *ptr; // Pointer into name/filename size_t blen; // Length of boundary string // Format the boundary string we are looking for... snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary + 9); blen = strlen(bstring); // Parse lines in the message body... name[0] = '\0'; filename[0] = '\0'; for (bodyptr = body; bodyptr < bodyend;) { // Split out a line... for (line = bodyptr; bodyptr < bodyend; bodyptr ++) { if (!memcmp(bodyptr, "\r\n", 2)) { *bodyptr = '\0'; bodyptr += 2; break; } } if (bodyptr >= bodyend) break; papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Line '%s'.", line); if (!*line) { // End of headers, grab value... if (!name[0]) { // No name value... papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Invalid multipart form data."); break; } for (bend = bodyend - blen, ptr = memchr(bodyptr, '\r', (size_t)(bend - bodyptr)); ptr; ptr = memchr(ptr + 1, '\r', (size_t)(bend - ptr - 1))) { // Check for boundary string... if (!memcmp(ptr, bstring, blen)) break; } if (!ptr) { // No boundary string, invalid data... papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Invalid multipart form data."); break; } // Point to the start of the boundary string... bend = ptr; ptr = bodyptr; bodyptr = bend + blen; if (filename[0]) { // Save an embedded file... const char *tempfile; // Temporary file if ((tempfile = _papplClientCreateTempFile(client, ptr, (size_t)(bend - ptr))) == NULL) break; num_form = cupsAddOption(name, tempfile, num_form, form); } else { // Save the form variable... *bend = '\0'; num_form = cupsAddOption(name, ptr, num_form, form); } name[0] = '\0'; filename[0] = '\0'; if (bodyptr < (bodyend - 1) && bodyptr[0] == '\r' && bodyptr[1] == '\n') bodyptr += 2; } else if (!strncasecmp(line, "Content-Disposition:", 20)) { if ((ptr = strstr(line + 20, " name=\"")) != NULL) { papplCopyString(name, ptr + 7, sizeof(name)); if ((ptr = strchr(name, '\"')) != NULL) *ptr = '\0'; } if ((ptr = strstr(line + 20, " filename=\"")) != NULL) { papplCopyString(filename, ptr + 11, sizeof(filename)); if ((ptr = strchr(filename, '\"')) != NULL) *ptr = '\0'; } } } } free(body); // Return whatever we got... return ((int)num_form); } // // 'papplClientHTMLAuthorize()' - Handle authorization for the web interface. // // The web interface supports both authentication against user accounts and // authentication using a single administrative access password. This function // handles the details of authentication for the web interface based on the // system authentication service configuration = the "auth_service" argument to // @link papplSystemCreate@ and any callback set using // @link papplSystemSetAuthCallback@. // // > Note: IPP operation callbacks needing to perform authorization should use // > the @link papplClientIsAuthorized@ function instead. // bool // O - `true` if authorized, `false` otherwise papplClientHTMLAuthorize( pappl_client_t *client) // I - Client { char auth_cookie[65], // Authorization cookie session_key[65], // Current session key password_hash[100], // Password hash auth_text[256]; // Authorization string unsigned char auth_hash[32]; // Authorization hash const char *status = NULL; // Status message, if any // Don't authorize if we have no auth service or we don't have a password set. if (!client || (!client->system->auth_service && !client->system->auth_cb && !client->system->password_hash[0])) { _PAPPL_DEBUG("papplClientHTMLAuthorize: auth_service='%s', auth_cb=%s, password_hash=%s\n", client->system->auth_service, client->system->auth_cb != NULL ? "set" : "unset", client->system->password_hash[0] ? "set" : "unset"); _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true."); return (true); } // When using an auth service, use HTTP Basic authentication... if (client->system->auth_service || client->system->auth_cb) { http_status_t code = papplClientIsAuthorized(client); // Authorization status code _PAPPL_DEBUG("papplClientHTMLAuthorize: code=%d.\n", code); if (code != HTTP_STATUS_CONTINUE) { _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning false.\n"); papplClientRespond(client, code, NULL, NULL, 0, 0); return (false); } else { _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n"); return (true); } } // Otherwise look for the authorization cookie... if (papplClientGetCookie(client, "auth", auth_cookie, sizeof(auth_cookie))) { _PAPPL_DEBUG("papplClientHTMLAuthorize: Got auth cookie '%s'.\n", auth_cookie); snprintf(auth_text, sizeof(auth_text), "%s:%s", papplSystemGetSessionKey(client->system, session_key, sizeof(session_key)), papplSystemGetPassword(client->system, password_hash, sizeof(password_hash))); cupsHashData("sha2-256", (unsigned char *)auth_text, strlen(auth_text), auth_hash, sizeof(auth_hash)); cupsHashString(auth_hash, sizeof(auth_hash), auth_text, sizeof(auth_text)); _PAPPL_DEBUG("papplClientHTMLAuthorize: Expect auth cookie '%s'.\n", auth_text); if (_papplIsEqual(auth_cookie, auth_text)) { // Hashes match so we are authorized. Use "web-admin" as the username. papplCopyString(client->username, "web-admin", sizeof(client->username)); _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n"); return (true); } } // No cookie, so see if this is a form submission... if (client->operation == HTTP_STATE_POST) { // Yes, grab the login information and try to authorize... cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables const char *password; // Password from user _PAPPL_DEBUG("papplClientHTMLAuthorize: POST.\n"); if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = "Invalid form data."; } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = "Invalid form submission."; } else if ((password = cupsGetOption("password", num_form, form)) == NULL) { status = "Login password required."; } else { // Hash the user-supplied password with the salt from the stored password papplSystemGetPassword(client->system, password_hash, sizeof(password_hash)); papplSystemHashPassword(client->system, password_hash, password, auth_text, sizeof(auth_text)); _PAPPL_DEBUG("papplClientHTMLAuthorize: Saved password_hash is '%s'.\n", password_hash); _PAPPL_DEBUG("papplClientHTMLAuthorize: Hashed form password is '%s'.\n", auth_text); if (_papplIsEqual(password_hash, auth_text)) { // Password hashes match, generate the cookie from the session key and // password hash... snprintf(auth_text, sizeof(auth_text), "%s:%s", papplSystemGetSessionKey(client->system, session_key, sizeof(session_key)), password_hash); cupsHashData("sha2-256", (unsigned char *)auth_text, strlen(auth_text), auth_hash, sizeof(auth_hash)); cupsHashString(auth_hash, sizeof(auth_hash), auth_text, sizeof(auth_text)); papplClientSetCookie(client, "auth", auth_text, 3600); _PAPPL_DEBUG("papplClientHTMLAuthorize: Setting 'auth' cookie to '%s'.\n", auth_text); } else { status = "Password incorrect."; } } cupsFreeOptions(num_form, form); // Make the caller think this is a GET request... client->operation = HTTP_STATE_GET; _PAPPL_DEBUG("papplClientHTMLAuthorize: Status message is '%s'.\n", status); if (!status) { // Hashes match so we are authorized. Use "web-admin" as the username. papplCopyString(client->username, "web-admin", sizeof(client->username)); _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n"); return (true); } } // If we get this far, show the standard login form... _PAPPL_DEBUG("papplClientHTMLAuthorize: Showing login form.\n"); papplClientRespond(client, HTTP_STATUS_OK, NULL, "text/html", 0, 0); papplClientHTMLHeader(client, "Login", 0); papplClientHTMLPuts(client, "
\n" "
\n" "
\n" "

Login

\n"); if (status) papplClientHTMLPrintf(client, "
%s
\n", status); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPuts(client, "

\n" " \n" "
\n" "
\n"); papplClientHTMLFooter(client); _PAPPL_DEBUG("papplClientHTMLAuthorize: Returning false.\n"); return (false); } // // 'papplClientHTMLEscape()' - Send a string to a web browser client. // // This function sends the specified string to the web browser client and // escapes special characters as HTML entities as needed, for example "&" is // sent as `&`. // void papplClientHTMLEscape( pappl_client_t *client, // I - Client const char *s, // I - String to write size_t slen) // I - Number of characters to write (`0` for nul-terminated) { const char *start, // Start of segment *end; // End of string start = s; end = s + (slen > 0 ? slen : strlen(s)); while (*s && s < end) { if (*s == '&' || *s == '<' || *s == '\"') { if (s > start) httpWrite(client->http, start, (size_t)(s - start)); if (*s == '&') httpWrite(client->http, "&", 5); else if (*s == '<') httpWrite(client->http, "<", 4); else httpWrite(client->http, """, 6); start = s + 1; } s ++; } if (s > start) httpWrite(client->http, start, (size_t)(s - start)); } // // 'papplClientHTMLFooter()' - Show the web interface footer. // // This function sends the standard web interface footer followed by a // trailing 0-length chunk to finish the current HTTP response. Use the // @link papplSystemSetFooterHTML@ function to add any custom HTML needed in // the footer. // void papplClientHTMLFooter( pappl_client_t *client) // I - Client { const char *footer = papplClientGetLocString(client, papplSystemGetFooterHTML(papplClientGetSystem(client))); // Footer HTML if (footer) { papplClientHTMLPuts(client, "
\n" "
\n" "
"); papplClientHTMLPuts(client, footer); papplClientHTMLPuts(client, "
\n" "
\n" "
\n"); } papplClientHTMLPuts(client, " \n" "\n"); httpWrite(client->http, "", 0); } // // 'papplClientHTMLHeader()' - Show the web interface header and title. // // This function sends the standard web interface header and title. If the // "refresh" argument is greater than zero, the page will automatically reload // after that many seconds. // // Use the @link papplSystemAddLink@ function to add system-wide navigation // links to the header. Similarly, use @link papplPrinterAddLink@ to add // printer-specific links, which will appear in the web interface printer if // the system is not configured to support multiple printers // (the `PAPPL_SOPTIONS_MULTI_QUEUE` option to @link papplSystemCreate@). // void papplClientHTMLHeader( pappl_client_t *client, // I - Client const char *title, // I - Title int refresh) // I - Refresh time in seconds (`0` for no refresh) { pappl_system_t *system = client->system; // System pappl_printer_t *printer; // Printer const char *name; // Name for title/header _papplRWLockRead(system); printer = (pappl_printer_t *)cupsArrayGetFirst(system->printers); _papplRWUnlock(system); if ((system->options & PAPPL_SOPTIONS_MULTI_QUEUE) || !printer) name = system->name; else name = printer->name; papplClientHTMLPrintf(client, "\n" "\n" " \n" " %s%s%s\n" " \n" " \n" " \n", title ? papplClientGetLocString(client, title) : "", title ? " - " : "", name); if (refresh > 0) papplClientHTMLPrintf(client, "\n", refresh); papplClientHTMLPuts(client, " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n"); _papplRWLockRead(system); _papplClientHTMLPutLinks(client, system->links, PAPPL_LOPTIONS_NAVIGATION); _papplRWUnlock(system); if (!(system->options & PAPPL_SOPTIONS_MULTI_QUEUE) && printer) { if (cupsArrayGetCount(system->links) > 0) papplClientHTMLPuts(client, " \n"); _papplRWLockRead(printer); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_NAVIGATION); _papplRWUnlock(printer); } papplClientHTMLPuts(client, "
\n" "
\n" "
\n"); } // // '_papplClientHTMLInfo()' - Show system/printer information. // void _papplClientHTMLInfo( pappl_client_t *client, // I - Client bool is_form, // I - `true` to show a form, `false` otherwise const char *dns_sd_name, // I - DNS-SD name, if any const char *location, // I - Location, if any const char *geo_location, // I - Geo-location, if any const char *organization, // I - Organization, if any const char *org_unit, // I - Organizational unit, if any pappl_contact_t *contact) // I - Contact, if any { double lat = 0.0, lon = 0.0; // Latitude and longitude in degrees if (geo_location) sscanf(geo_location, "geo:%lf,%lf", &lat, &lon); if (is_form) papplClientHTMLStartForm(client, client->uri, false); // DNS-SD name... papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
%s:", papplClientGetLocString(client, _PAPPL_LOC("Name"))); if (is_form) papplClientHTMLPrintf(client, "", dns_sd_name ? dns_sd_name : "", papplClientGetLocString(client, _PAPPL_LOC("DNS-SD Service Name"))); else papplClientHTMLEscape(client, dns_sd_name ? dns_sd_name : papplClientGetLocString(client, _PAPPL_LOC("Not set")), 0); // Location and geo-location... papplClientHTMLPrintf(client, "
%s:", papplClientGetLocString(client, _PAPPL_LOC("Location"))); if (is_form) { papplClientHTMLPrintf(client, "
\n" " ° latitude x  ° longitude", papplClientGetLocString(client, _PAPPL_LOC("Human-Readable Location")), location ? location : "", lat, lon); if (httpIsEncrypted(client->http)) { // If the connection is encrypted, show a button to lookup the position... papplClientHTMLPrintf(client, " ", papplClientGetLocString(client, _PAPPL_LOC("Use My Position"))); } else if (!(client->system->options & PAPPL_SOPTIONS_NO_TLS)) { // If the connection is not encrypted, redirect to a secure page... papplClientHTMLPrintf(client, " %s", client->host_field, client->host_port, client->uri, papplClientGetLocString(client, _PAPPL_LOC("Use My Position"))); } } else { papplClientHTMLPrintf(client, "%s", location ? location : papplClientGetLocString(client, _PAPPL_LOC("Not set"))); if (geo_location) papplClientHTMLPrintf(client, "
\n%g° %c %g° %c", fabs(lat), lat < 0.0 ? 'S' : 'N', fabs(lon), lon < 0.0 ? 'W' : 'E'); } // Show an embedded map of the location... if (geo_location || is_form) papplClientHTMLPrintf(client, "
\n" "", lon - 0.00025, lat - 0.00025, lon + 0.00025, lat + 0.00025, lat, lon); // Organization papplClientHTMLPrintf(client, "
%s:", papplClientGetLocString(client, _PAPPL_LOC("Organization"))); if (is_form) papplClientHTMLPrintf(client, "
\n" "", papplClientGetLocString(client, _PAPPL_LOC("Organization Name")), organization ? organization : "", papplClientGetLocString(client, _PAPPL_LOC("Organizational Unit")), org_unit ? org_unit : ""); else papplClientHTMLPrintf(client, "%s%s%s", organization ? organization : papplClientGetLocString(client, _PAPPL_LOC("Not set")), org_unit ? ", " : "", org_unit ? org_unit : ""); // Contact papplClientHTMLPrintf(client, "
%s:", papplClientGetLocString(client, _PAPPL_LOC("Contact"))); if (is_form) { papplClientHTMLPrintf(client, "
\n" "
\n" "
", papplClientGetLocString(client, _PAPPL_LOC("Name")), contact->name, contact->email, contact->telephone); } else if (contact->email[0]) { papplClientHTMLPrintf(client, "%s", contact->email, contact->name[0] ? contact->name : contact->email); if (contact->telephone[0]) papplClientHTMLPrintf(client, "
%s", contact->telephone, contact->telephone); } else if (contact->name[0]) { papplClientHTMLEscape(client, contact->name, 0); if (contact->telephone[0]) papplClientHTMLPrintf(client, "
%s", contact->telephone, contact->telephone); } else if (contact->telephone[0]) { papplClientHTMLPrintf(client, "%s", contact->telephone, contact->telephone); } else papplClientHTMLPuts(client, papplClientGetLocString(client, _PAPPL_LOC("Not set"))); papplClientHTMLPuts(client, "
\n"); if (is_form) { // The following Javascript updates the map and lat/lon fields. // // Note: I should probably use the Openstreetmap Javascript API so that // the marker position gets updated. Right now I'm setting the marker // value in the URL but the OSM simple embedding URL doesn't update the // marker position after the page is loaded... papplClientHTMLPuts(client, " \n" " \n"); } } // // 'papplClientHTMLPrinterFooter()' - Show the web interface footer for printers. // // This function sends the standard web interface footer for a printer followed // by a trailing 0-length chunk to finish the current HTTP response. Use the // @link papplSystemSetFooterHTML@ function to add any custom HTML needed in // the footer. // void papplClientHTMLPrinterFooter(pappl_client_t *client) // I - Client { papplClientHTMLPuts(client, "
\n" " \n" " \n"); papplClientHTMLFooter(client); } // // 'papplClientHTMLPrinterHeader()' - Show the web interface header and title // for printers. // // This function sends the standard web interface header and title for a // printer. If the "refresh" argument is greater than zero, the page will // automatically reload after that many seconds. // // If "label" and "path_or_url" are non-`NULL` strings, an additional navigation // link is included with the title header - this is typically used for an // action button ("Change"). // // Use the @link papplSystemAddLink@ function to add system-wide navigation // links to the header. Similarly, use @link papplPrinterAddLink@ to add // printer-specific links, which will appear in the web interface printer if // the system is not configured to support multiple printers // (the `PAPPL_SOPTIONS_MULTI_QUEUE` option to @link papplSystemCreate@). // void papplClientHTMLPrinterHeader( pappl_client_t *client, // I - Client pappl_printer_t *printer, // I - Printer const char *title, // I - Title int refresh, // I - Refresh time in seconds or 0 for none const char *label, // I - Button label or `NULL` for none const char *path_or_url) // I - Button path or `NULL` for none { const char *header; // Header text if (!papplClientRespond(client, HTTP_STATUS_OK, NULL, "text/html", 0, 0)) return; if (printer->system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { // Multi-queue mode, need to add the printer name to the title... if (title) { char full_title[1024]; // Full title // Need to grab the localized title here since the title includes the printer name... snprintf(full_title, sizeof(full_title), "%s - %s", papplClientGetLocString(client, title), printer->name); papplClientHTMLHeader(client, full_title, refresh); } else { papplClientHTMLHeader(client, printer->name, refresh); } } else { // Single queue mode - the function will automatically add the printer name and localize the title... papplClientHTMLHeader(client, title, refresh); } if (printer->system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { _papplRWLockRead(printer); papplClientHTMLPrintf(client, "
\n" "
\n" "
%s:\n", printer->uriname, printer->name); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_NAVIGATION); papplClientHTMLPuts(client, "
\n" "
\n" "
\n"); _papplRWUnlock(printer); } else if (client->system->versions[0].sversion[0]) papplClientHTMLPrintf(client, "
\n" "
\n" "
\n" " Version %s\n" "
\n" "
\n" "
\n", client->system->versions[0].sversion); papplClientHTMLPuts(client, "
\n"); if ((header = papplClientGetLocString(client, client->uri)) == client->uri) { size_t urilen = strlen(printer->uriname); // Length of printer URI name const char *uriptr = client->uri + urilen; // Pointer into client URI if (strlen(client->uri) <= urilen || !strcmp(client->uri, "/") || (header = papplClientGetLocString(client, uriptr)) == uriptr) header = NULL; } if (header) { // Show header text papplClientHTMLPuts(client, "
\n" "
\n"); papplClientHTMLPuts(client, header); papplClientHTMLPuts(client, "\n" "
\n" "
\n"); } if (title) { papplClientHTMLPrintf(client, "
\n" "
\n" "

%s", papplClientGetLocString(client, title)); if (label && path_or_url) papplClientHTMLPrintf(client, " %s", path_or_url, papplClientGetLocString(client, label)); papplClientHTMLPuts(client, "

\n"); } } // // 'papplClientHTMLPrintf()' - Send formatted text to the web browser client, // escaping as needed. // // This function sends formatted text to the web browser client using // `printf`-style formatting codes. The format string itself is not escaped // to allow for embedded HTML, however strings inserted using the '%c' or `%s` // codes are escaped properly for HTML - "&" is sent as `&`, etc. // void papplClientHTMLPrintf( pappl_client_t *client, // I - Client const char *format, // I - Printf-style format string ...) // I - Additional arguments as needed { va_list ap; // Pointer to arguments const char *start; // Start of string char size, // Size character (h, l, L) type; // Format type character int width, // Width of field prec; // Number of characters of precision char tformat[100], // Temporary format string for snprintf() *tptr, // Pointer into temporary format temp[1024]; // Buffer for formatted numbers const char *s; // Pointer to string // Loop through the format string, formatting as needed... // TODO: Support positional parameters, e.g. "%2$s" to access the second string argument va_start(ap, format); start = format; while (*format) { if (*format == '%') { if (format > start) httpWrite(client->http, start, (size_t)(format - start)); tptr = tformat; *tptr++ = *format++; if (*format == '%') { httpWrite(client->http, "%", 1); format ++; start = format; continue; } else if (strchr(" -+#\'", *format)) *tptr++ = *format++; if (*format == '*') { // Get width from argument... format ++; width = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width); tptr += strlen(tptr); } else { width = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; width = width * 10 + *format++ - '0'; } } if (*format == '.') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; format ++; if (*format == '*') { // Get precision from argument... format ++; prec = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec); tptr += strlen(tptr); } else { prec = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; prec = prec * 10 + *format++ - '0'; } } } if (*format == 'l' && format[1] == 'l') { size = 'L'; if (tptr < (tformat + sizeof(tformat) - 2)) { *tptr++ = 'l'; *tptr++ = 'l'; } format += 2; } else if (*format == 'h' || *format == 'l' || *format == 'L') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; size = *format++; } else size = 0; if (!*format) { start = format; break; } if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; type = *format++; *tptr = '\0'; start = format; switch (type) { case 'E' : // Floating point formats case 'G' : case 'e' : case 'f' : case 'g' : if ((size_t)(width + 2) > sizeof(temp)) break; snprintf(temp, sizeof(temp), tformat, va_arg(ap, double)); httpWrite(client->http, temp, strlen(temp)); break; case 'B' : // Integer formats case 'X' : case 'b' : case 'd' : case 'i' : case 'o' : case 'u' : case 'x' : if ((size_t)(width + 2) > sizeof(temp)) break; # ifdef HAVE_LONG_LONG if (size == 'L') snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long)); else # endif // HAVE_LONG_LONG if (size == 'l') snprintf(temp, sizeof(temp), tformat, va_arg(ap, long)); else snprintf(temp, sizeof(temp), tformat, va_arg(ap, int)); httpWrite(client->http, temp, strlen(temp)); break; case 'p' : // Pointer value if ((size_t)(width + 2) > sizeof(temp)) break; snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *)); httpWrite(client->http, temp, strlen(temp)); break; case 'c' : // Character or character array if (width <= 1) { temp[0] = (char)va_arg(ap, int); temp[1] = '\0'; papplClientHTMLEscape(client, temp, 1); } else papplClientHTMLEscape(client, va_arg(ap, char *), (size_t)width); break; case 's' : // String if ((s = va_arg(ap, const char *)) == NULL) s = "(null)"; papplClientHTMLEscape(client, s, strlen(s)); break; } } else format ++; } if (format > start) httpWrite(client->http, start, (size_t)(format - start)); va_end(ap); } // // '_papplClientHTMLPutLinks()' - Print an array of links. // void _papplClientHTMLPutLinks( pappl_client_t *client, // I - Client cups_array_t *links, // I - Array of links pappl_loptions_t which) // I - Which links to show { cups_len_t i, // Looping var count; // Number of links _pappl_link_t *l; // Current link const char *webscheme = _papplClientGetAuthWebScheme(client); // URL scheme for authenticated links // Loop through the links. // // Note: We use a loop and not cupsArrayGetFirst/Last because other threads may // be enumerating the same array of links. for (i = 0, count = cupsArrayGetCount(links); i < count; i ++) { l = (_pappl_link_t *)cupsArrayGetElement(links, i); if (!l || !(l->options & which)) continue; if (strcmp(client->uri, l->path_or_url)) { if (l->path_or_url[0] != '/' || !(l->options & PAPPL_LOPTIONS_HTTPS_REQUIRED)) papplClientHTMLPrintf(client, " %s\n", l->path_or_url, papplClientGetLocString(client, l->label)); else papplClientHTMLPrintf(client, " %s\n", webscheme, client->host_field, client->host_port, l->path_or_url, papplClientGetLocString(client, l->label)); } else papplClientHTMLPrintf(client, " %s\n", papplClientGetLocString(client, l->label)); } } // // 'papplClientHTMLPuts()' - Send a HTML string to the web browser client. // // This function sends a HTML string to the client without performing any // escaping of special characters. // void papplClientHTMLPuts( pappl_client_t *client, // I - Client const char *s) // I - String { if (client && s && *s) httpWrite(client->http, s, strlen(s)); } // // 'papplClientHTMLStartForm()' - Start a HTML form. // // This function starts a HTML form with the specified "action" path and // includes the CSRF token as a hidden variable. If the "multipart" argument // is `true`, the form is annotated to support file attachments up to 2MiB in // size. // void papplClientHTMLStartForm( pappl_client_t *client, // I - Client const char *action, // I - Form action URL bool multipart) // I - `true` if the form allows file uploads, `false` otherwise { char token[256]; // CSRF token if (multipart) { // When allowing file attachments, the maximum size is 2MB... papplClientHTMLPrintf(client, "
\n" " \n" " \n", action, papplClientGetCSRFToken(client, token, sizeof(token))); } else { papplClientHTMLPrintf(client, " \n" " \n", action, papplClientGetCSRFToken(client, token, sizeof(token))); } } // // 'papplClientIsValidForm()' - Validate HTML form variables. // // This function validates the contents of a HTML form using the CSRF token // included as a hidden variable. When sending a HTML form you should use the // @link papplClientStartForm@ function to start the HTML form and insert the // CSRF token for later validation. // // > Note: Callers are expected to validate all other form variables. // bool // O - `true` if the CSRF token is valid, `false` otherwise papplClientIsValidForm( pappl_client_t *client, // I - Client int num_form, // I - Number of form variables cups_option_t *form) // I - Form variables { char token[256]; // Expected CSRF token const char *session; // Form variable if ((session = cupsGetOption("session", (cups_len_t)num_form, form)) == NULL) return (false); return (!strcmp(session, papplClientGetCSRFToken(client, token, sizeof(token)))); } // // 'papplClientSetCookie()' - Set a cookie for the web browser client. // // This function sets the value of a cookie for the client by updating the // `Set-Cookie` header in the HTTP response that will be sent. The "name" and // "value" strings must contain only valid characters for a cookie and its // value as documented in RFC 6265, which basically means letters, numbers, "@", // "-", ".", and "_". // // The "expires" argument specifies how long the cookie will remain active in // seconds, for example `3600` seconds is one hour and `86400` seconds is one // day. If the value is zero or less, a "session" cookie is created instead // which will expire as soon as the web browser is closed. // void papplClientSetCookie( pappl_client_t *client, // I - Client const char *name, // I - Cookie name const char *value, // I - Cookie value int expires) // I - Expiration in seconds from now, `0` for a session cookie { const char *client_cookie = httpGetCookie(client->http); // Current cookie char buffer[1024], // New cookie buffer cookie[256], // New authorization cookie expireTime[64]; // Expiration date/time if (!name) return; if (expires > 0) snprintf(cookie, sizeof(cookie), "%s=%s; path=/; expires=%s; httponly; secure;", name, value, httpGetDateString(time(NULL) + expires, expireTime, sizeof(expireTime))); else snprintf(cookie, sizeof(cookie), "%s=%s; path=/; httponly; secure;", name, value); if (!client_cookie || !*client_cookie) { // No other cookies set... httpSetCookie(client->http, cookie); } else { // Append the new cookie with a Set-Cookie: header since libcups only // directly supports setting a single Set-Cookie header... snprintf(buffer, sizeof(buffer), "%s\r\nSet-Cookie: %s", client_cookie, cookie); httpSetCookie(client->http, buffer); } } pappl-1.4.9/pappl/client.c000066400000000000000000000541731476704353100154230ustar00rootroot00000000000000// // Client processing code for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static bool eval_if_modified(pappl_client_t *client, _pappl_resource_t *r); // // '_papplClientCleanTempFiles()' - Clean temporary files... // void _papplClientCleanTempFiles( pappl_client_t *client) // I - Client { int i; // Looping var for (i = 0; i < client->num_files; i ++) { unlink(client->files[i]); free(client->files[i]); } client->num_files = 0; } // // '_papplClientCreate()' - Accept a new network connection and create a client // object. // // The new network connection is accepted from the specified listen socket. // The client object is managed by the system and is automatically freed when // the connection is closed. // // > Note: This function is normally only called from @link papplSystemRun@. // pappl_client_t * // O - Client _papplClientCreate( pappl_system_t *system, // I - Printer int sock) // I - Listen socket { pappl_client_t *client; // Client if ((client = calloc(1, sizeof(pappl_client_t))) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for client connection: %s", strerror(errno)); return (NULL); } client->system = system; _papplRWLockWrite(system); client->number = system->next_client ++; _papplRWUnlock(system); // Accept the client and get the remote address... if ((client->http = httpAcceptConnection(sock, 1)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to accept client connection: %s", strerror(errno)); free(client); return (NULL); } httpGetHostname(client->http, client->hostname, sizeof(client->hostname)); papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Accepted connection from '%s'.", client->hostname); return (client); } // // '_papplClientCreateTempFile()' - Create a temporary file. // char * // O - Temporary filename or `NULL` on error _papplClientCreateTempFile( pappl_client_t *client, // I - Client const void *data, // I - Data size_t datasize) // I - Size of data { int fd; // File descriptor char tempfile[1024]; // Temporary filename // See if we have room for another temp file... if (client->num_files >= (int)(sizeof(client->files) / sizeof(client->files[0]))) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Too many temporary files."); return (NULL); } // Write the data to a temporary file... if ((fd = cupsCreateTempFd(NULL, NULL, tempfile, sizeof(tempfile))) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create temporary file: %s", strerror(errno)); return (NULL); } if (write(fd, data, datasize) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write to temporary file: %s", strerror(errno)); close(fd); unlink(tempfile); return (NULL); } close(fd); if ((client->files[client->num_files] = strdup(tempfile)) != NULL) client->num_files ++; else unlink(tempfile); if (client->num_files > 0) return (client->files[client->num_files - 1]); else return (NULL); } // // '_papplClientDelete()' - Close the client connection and free all memory used // by a client object. // // > Note: This function is normally only called by // void _papplClientDelete( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Closing connection from '%s'.", client->hostname); // Flush pending writes before closing... httpFlushWrite(client->http); _papplClientCleanTempFiles(client); // Free memory... httpClose(client->http); ippDelete(client->request); ippDelete(client->response); free(client); // Update the number of active clients... _papplRWLockWrite(system); system->num_clients --; _papplRWUnlock(system); } // // '_papplClientProcessHTTP()' - Process a HTTP request. // bool // O - `true` on success, `false` on failure _papplClientProcessHTTP( pappl_client_t *client) // I - Client connection { char uri[1024]; // URI http_state_t http_state; // HTTP state http_status_t http_status; // HTTP status http_version_t http_version; // HTTP version ipp_state_t ipp_state; // State of IPP transfer char scheme[32], // Method/scheme userpass[128], // Username:password hostname[HTTP_MAX_HOST]; // Hostname int port; // Port number char *ptr; // Pointer into string _pappl_resource_t *resource; // Current resource char system_host[HTTP_MAX_HOST]; // System hostname // Clear state variables... ippDelete(client->request); ippDelete(client->response); client->loc = NULL; client->request = NULL; client->response = NULL; client->operation = HTTP_STATE_WAITING; // Read a request from the connection... while ((http_state = httpReadRequest(client->http, uri, sizeof(uri))) == HTTP_STATE_WAITING) usleep(1); // Parse the request line... if (http_state == HTTP_STATE_ERROR) { if (httpGetError(client->http) != EPIPE && httpGetError(client->http)) papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Bad request line (%s).", strerror(httpGetError(client->http))); return (false); } else if (http_state == HTTP_STATE_UNKNOWN_METHOD) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad/unknown operation."); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } else if (http_state == HTTP_STATE_UNKNOWN_VERSION) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad HTTP version."); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } // Separate the URI into its components... if (httpSeparateURI(HTTP_URI_CODING_MOST, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, client->uri, sizeof(client->uri)) < HTTP_URI_STATUS_OK && (http_state != HTTP_STATE_OPTIONS || strcmp(uri, "*"))) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad URI '%s'.", uri); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } if ((client->options = strchr(client->uri, '?')) != NULL) *(client->options)++ = '\0'; // Process the request... client->start = time(NULL); client->operation = httpGetState(client->http); // Parse incoming parameters until the status changes... while ((http_status = httpUpdate(client->http)) == HTTP_STATUS_CONTINUE) ; // Read all HTTP headers... if (http_status != HTTP_STATUS_OK) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "http_status=%d", http_status); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } http_version = httpGetVersion(client->http); papplCopyString(client->language, httpGetField(client->http, HTTP_FIELD_ACCEPT_LANGUAGE), sizeof(client->language)); papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s://%s%s HTTP/%d.%d (%s)", httpStateString(http_state), httpIsEncrypted(client->http) ? "https" : "http", httpGetField(client->http, HTTP_FIELD_HOST), uri, http_version / 100, http_version % 100, client->language); // Validate the host header... if (!httpGetField(client->http, HTTP_FIELD_HOST)[0] && httpGetVersion(client->http) >= HTTP_VERSION_1_1) { // HTTP/1.1 and higher require the "Host:" field... papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } papplCopyString(client->host_field, httpGetField(client->http, HTTP_FIELD_HOST), sizeof(client->host_field)); if ((ptr = strrchr(client->host_field, ':')) != NULL) { char *end; // End of port number // Grab port number from Host: header... *ptr++ = '\0'; client->host_port = (int)strtol(ptr, &end, 10); if (errno == ERANGE || *end) client->host_port = papplSystemGetHostPort(client->system); } else { // Use the default port number... client->host_port = papplSystemGetHostPort(client->system); } ptr = strstr(client->host_field, ".local"); if (!isdigit(client->host_field[0] & 255) && client->host_field[0] != '[' && strcmp(client->host_field, papplSystemGetHostName(client->system, system_host, sizeof(system_host))) && strcmp(client->host_field, "localhost") && (!ptr || (strcmp(ptr, ".local") && strcmp(ptr, ".local.")))) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad Host: header '%s'.", client->host_field); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } // Handle HTTP Upgrade... if (!strcasecmp(httpGetField(client->http, HTTP_FIELD_CONNECTION), "Upgrade")) { if (strstr(httpGetField(client->http, HTTP_FIELD_UPGRADE), "TLS/") != NULL && !httpIsEncrypted(client->http) && !(client->system->options & PAPPL_SOPTIONS_NO_TLS)) { if (!papplClientRespond(client, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, NULL, 0, 0)) return (false); papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Upgrading to encrypted connection."); if (!httpSetEncryption(client->http, HTTP_ENCRYPTION_REQUIRED)) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to encrypt connection: %s", cupsGetErrorString()); return (false); } papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Connection now encrypted."); } else if (!papplClientRespond(client, HTTP_STATUS_NOT_IMPLEMENTED, NULL, NULL, 0, 0)) return (false); } // Handle HTTP Expect... if (httpGetExpect(client->http) && (client->operation == HTTP_STATE_POST || client->operation == HTTP_STATE_PUT)) { if (httpGetExpect(client->http) == HTTP_STATUS_CONTINUE) { // Send 100-continue header... if (!papplClientRespond(client, HTTP_STATUS_CONTINUE, NULL, NULL, 0, 0)) return (false); } else { // Send 417-expectation-failed header... if (!papplClientRespond(client, HTTP_STATUS_EXPECTATION_FAILED, NULL, NULL, 0, 0)) return (false); } } // Handle new transfers... switch (client->operation) { case HTTP_STATE_OPTIONS : // Do OPTIONS command... return (papplClientRespond(client, HTTP_STATUS_OK, NULL, NULL, 0, 0)); case HTTP_STATE_HEAD : // See if we have a matching resource to serve... if ((resource = _papplSystemFindResourceForPath(client->system, client->uri)) != NULL) { if (eval_if_modified(client, resource)) return (papplClientRespond(client, HTTP_STATUS_OK, NULL, resource->format, resource->last_modified, 0)); else return (papplClientRespond(client, HTTP_STATUS_NOT_MODIFIED, NULL, NULL, resource->last_modified, 0)); } // If we get here the resource wasn't found... return (papplClientRespond(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0, 0)); case HTTP_STATE_GET : // See if we have a matching resource to serve... if ((resource = _papplSystemFindResourceForPath(client->system, client->uri)) != NULL) { if (!eval_if_modified(client, resource)) { return (papplClientRespond(client, HTTP_STATUS_NOT_MODIFIED, NULL, NULL, resource->last_modified, 0)); } else if (resource->cb) { // Send output of a callback... return ((resource->cb)(client, resource->cbdata)); } else if (resource->filename) { // Send an external file... int fd; // Resource file descriptor char buffer[8192]; // Copy buffer ssize_t bytes; // Bytes read/written if ((fd = open(resource->filename, O_RDONLY)) >= 0) { if (!papplClientRespond(client, HTTP_STATUS_OK, NULL, resource->format, resource->last_modified, 0)) { close(fd); return (false); } while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) httpWrite(client->http, buffer, (size_t)bytes); httpWrite(client->http, "", 0); close(fd); return (true); } } else { // Send a static resource file... if (!papplClientRespond(client, HTTP_STATUS_OK, NULL, resource->format, resource->last_modified, resource->length)) return (false); httpWrite(client->http, (const char *)resource->data, resource->length); httpFlushWrite(client->http); return (true); } } // If we get here then the resource wasn't found... return (papplClientRespond(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0, 0)); case HTTP_STATE_POST : if (!strcmp(httpGetField(client->http, HTTP_FIELD_CONTENT_TYPE), "application/ipp")) { // Read the IPP request... client->request = ippNew(); while ((ipp_state = ippRead(client->http, client->request)) != IPP_STATE_DATA) { if (ipp_state == IPP_STATE_ERROR) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "IPP read error (%s).", cupsGetErrorString()); papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); return (false); } } // Now that we have the IPP request, process the request... return (_papplClientProcessIPP(client)); } else if ((resource = _papplSystemFindResourceForPath(client->system, client->uri)) != NULL) { // Serve a matching resource... if (resource->cb) { // Handle a post request through the callback... return ((resource->cb)(client, resource->cbdata)); } else { // Otherwise you can't POST to a resource... return (papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0)); } } else { // Not an IPP request or form, return an error... return (papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0)); } default : break; // Anti-compiler-warning-code } return (true); } // // 'papplClientRespond()' - Send a regular HTTP response. // // This function sends all of the required HTTP fields and includes standard // messages for errors. The following values for "code" are explicitly // supported: // // - `HTTP_STATUS_OK`: The request is successful. // - `HTTP_STATUS_BAD_REQUEST`: The client submitted a bad request. // - `HTTP_STATUS_CONTINUE`: An authentication challenge is not needed. // - `HTTP_STATUS_FORBIDDEN`: Authenticated but not allowed. // - `HTTP_STATUS_METHOD_NOT_ALLOWED`: The HTTP method is not supported for the // given URI. // - `HTTP_STATUS_UNAUTHORIZED`: Not authenticated. // - `HTTP_STATUS_UPGRADE_REQUIRED`: Redirects the client to a secure page. // // Use the @link papplClientRespondRedirect@ when you need to redirect the // client to another page. // bool // O - `true` on success, `false` on failure papplClientRespond( pappl_client_t *client, // I - Client http_status_t code, // I - HTTP status of response const char *content_encoding, // I - Content-Encoding of response const char *type, // I - MIME media type of response time_t last_modified, // I - Last-Modified date/time or `0` for none size_t length) // I - Length of response or `0` for variable-length { char message[1024], // Text message last_str[256]; // Date string if (type) papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s %d", httpStatusString(code), type, (int)length); else papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s", httpStatusString(code)); if (code == HTTP_STATUS_CONTINUE) { // 100-continue doesn't send any headers... return (httpWriteResponse(client->http, HTTP_STATUS_CONTINUE)); } // Format an error message... if (!type && !length && code != HTTP_STATUS_OK && code != HTTP_STATUS_SWITCHING_PROTOCOLS) { snprintf(message, sizeof(message), "%d - %s\n", code, httpStatusString(code)); type = "text/plain"; length = strlen(message); } else message[0] = '\0'; // Send the HTTP response header... httpClearFields(client->http); httpSetField(client->http, HTTP_FIELD_SERVER, papplSystemGetServerHeader(client->system)); if (last_modified) httpSetField(client->http, HTTP_FIELD_LAST_MODIFIED, httpGetDateString(last_modified, last_str, sizeof(last_str))); if (code == HTTP_STATUS_METHOD_NOT_ALLOWED || client->operation == HTTP_STATE_OPTIONS) httpSetField(client->http, HTTP_FIELD_ALLOW, "GET, HEAD, OPTIONS, POST"); if (code == HTTP_STATUS_UNAUTHORIZED) { char value[HTTP_MAX_VALUE]; // WWW-Authenticate value snprintf(value, sizeof(value), "%s realm=\"%s\"", client->system->auth_scheme ? client->system->auth_scheme : "Basic", client->system->name); httpSetField(client->http, HTTP_FIELD_WWW_AUTHENTICATE, value); } if (type) { if (!strcmp(type, "text/html")) httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, "text/html; charset=utf-8"); else httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, type); if (content_encoding) httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, content_encoding); } httpSetLength(client->http, length); if (code == HTTP_STATUS_UPGRADE_REQUIRED && client->operation == HTTP_STATE_GET) { char redirect[1024]; // Redirect URI code = HTTP_STATUS_MOVED_PERMANENTLY; httpAssembleURI(HTTP_URI_CODING_ALL, redirect, sizeof(redirect), "https", NULL, client->host_field, client->host_port, client->uri); httpSetField(client->http, HTTP_FIELD_LOCATION, redirect); } if (!httpWriteResponse(client->http, code)) return (false); // Send the response data... if (message[0]) { // Send a plain text message. if (httpPrintf(client->http, "%s", message) < 0) return (false); if (httpWrite(client->http, "", 0) < 0) return (false); } else if (client->response) { // Send an IPP response... _papplLogAttributes(client, ippOpString(client->operation_id), client->response, true); ippSetState(client->response, IPP_STATE_IDLE); if (ippWrite(client->http, client->response) != IPP_STATE_DATA) return (false); } return (true); } // // 'papplClientRespondRedirect()' - Respond with a redirect to another page. // // This function sends a HTTP response that redirects the client to another // page or URL. The most common "code" value to return is `HTTP_STATUS_FOUND`. // bool // O - `true` on success, `false` otherwise papplClientRespondRedirect( pappl_client_t *client, // I - Client http_status_t code, // I - `HTTP_STATUS_MOVED_PERMANENTLY` or `HTTP_STATUS_FOUND` const char *path) // I - Redirection path/URL { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s", httpStatusString(code), path); // Send the HTTP response header... httpClearFields(client->http); httpSetField(client->http, HTTP_FIELD_SERVER, papplSystemGetServerHeader(client->system)); httpSetLength(client->http, 0); if (*path == '/' || !strchr(path, ':')) { // Generate an absolute URL... char url[1024]; // Absolute URL if (*path == '/') httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), httpIsEncrypted(client->http) ? "https" : "http", NULL, client->host_field, client->host_port, path); else httpAssembleURIf(HTTP_URI_CODING_ALL, url, sizeof(url), httpIsEncrypted(client->http) ? "https" : "http", NULL, client->host_field, client->host_port, "/%s", path); httpSetField(client->http, HTTP_FIELD_LOCATION, url); } else { // The path is already an absolute URL... httpSetField(client->http, HTTP_FIELD_LOCATION, path); } if (!httpWriteResponse(client->http, code)) return (false); return (httpWrite(client->http, "", 0) >= 0); } // // '_papplClientRun()' - Process client requests on a thread. // void * // O - Exit status _papplClientRun( pappl_client_t *client) // I - Client { int first_time = 1; // First time request? // Loop until we are out of requests or timeout (30 seconds)... while (httpWait(client->http, 30000)) { if (first_time && !(client->system->options & PAPPL_SOPTIONS_NO_TLS)) { // See if we need to negotiate a TLS connection... char buf[1]; // First byte from client if (recv(httpGetFd(client->http), buf, 1, MSG_PEEK) == 1 && (!buf[0] || !strchr("DGHOPT", buf[0]))) { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Starting HTTPS session."); if (!httpSetEncryption(client->http, HTTP_ENCRYPTION_ALWAYS)) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to encrypt connection: %s", cupsGetErrorString()); break; } papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Connection now encrypted."); } first_time = 0; } if (!_papplClientProcessHTTP(client)) break; _papplClientCleanTempFiles(client); } // Close the connection to the client and return... _papplClientDelete(client); return (NULL); } // // 'eval_if_modified()' - Evaluate an "If-Modified-Since" header. // static bool // O - `true` if modified, `false` otherwise eval_if_modified( pappl_client_t *client, // I - Client _pappl_resource_t *r) // I - Resource { const char *ptr; // Pointer into field time_t date = 0; // Time/date value off_t size = 0; // Size/length value // Dynamic content always needs to be updated... if (r->cb) return (true); // Get "If-Modified-Since:" header ptr = httpGetField(client->http, HTTP_FIELD_IF_MODIFIED_SINCE); if (*ptr == '\0') return (true); // Decode the If-Modified-Since: header... while (*ptr != '\0') { while (isspace(*ptr) || *ptr == ';') ptr ++; if (!strncasecmp(ptr, "length=", 7)) { char *next; // Next character size = (off_t)strtoll(ptr + 7, &next, 10); if (!next) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "If-Modified-Since: Bad length."); return (true); } ptr = next; } else if (isalpha(*ptr & 255)) { date = httpGetDateTime(ptr); while (*ptr != '\0' && *ptr != ';') ptr ++; } else ptr ++; } // Return the evaluation based on the last modified date, time, and size... return ((size != 0 && size != (off_t)r->length) || (date != 0 && date < r->last_modified) || (size == 0 && date == 0)); } pappl-1.4.9/pappl/client.h000066400000000000000000000075501476704353100154250ustar00rootroot00000000000000// // Public client header file for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_CLIENT_H_ # define _PAPPL_CLIENT_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Functions... // extern char *papplClientGetCSRFToken(pappl_client_t *client, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplClientGetCookie(pappl_client_t *client, const char *name, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplClientGetForm(pappl_client_t *client, cups_option_t **form) _PAPPL_PUBLIC; extern const char *papplClientGetHostName(pappl_client_t *client) _PAPPL_PUBLIC; extern int papplClientGetHostPort(pappl_client_t *client) _PAPPL_PUBLIC; extern http_t *papplClientGetHTTP(pappl_client_t *client) _PAPPL_PUBLIC; extern pappl_job_t *papplClientGetJob(pappl_client_t *client) _PAPPL_PUBLIC; extern pappl_loc_t *papplClientGetLoc(pappl_client_t *client) _PAPPL_PUBLIC; extern const char *papplClientGetLocString(pappl_client_t *client, const char *s) _PAPPL_PUBLIC; extern http_state_t papplClientGetMethod(pappl_client_t *client) _PAPPL_PUBLIC; extern ipp_op_t papplClientGetOperation(pappl_client_t *client) _PAPPL_PUBLIC; extern const char *papplClientGetOptions(pappl_client_t *client) _PAPPL_PUBLIC; extern pappl_printer_t *papplClientGetPrinter(pappl_client_t *client) _PAPPL_PUBLIC; extern ipp_t *papplClientGetRequest(pappl_client_t *client) _PAPPL_PUBLIC; extern ipp_t *papplClientGetResponse(pappl_client_t *client) _PAPPL_PUBLIC; extern pappl_system_t *papplClientGetSystem(pappl_client_t *client) _PAPPL_PUBLIC; extern const char *papplClientGetURI(pappl_client_t *client) _PAPPL_PUBLIC; extern const char *papplClientGetUsername(pappl_client_t *client) _PAPPL_PUBLIC; extern bool papplClientHTMLAuthorize(pappl_client_t *client) _PAPPL_PUBLIC; extern void papplClientHTMLEscape(pappl_client_t *client, const char *s, size_t slen) _PAPPL_PUBLIC; extern void papplClientHTMLFooter(pappl_client_t *client) _PAPPL_PUBLIC; extern void papplClientHTMLHeader(pappl_client_t *client, const char *title, int refresh) _PAPPL_PUBLIC; extern void papplClientHTMLPrinterFooter(pappl_client_t *client) _PAPPL_PUBLIC; extern void papplClientHTMLPrinterHeader(pappl_client_t *client, pappl_printer_t *printer, const char *title, int refresh, const char *label, const char *path_or_url) _PAPPL_PUBLIC; extern void papplClientHTMLPrintf(pappl_client_t *client, const char *format, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(2, 3); extern void papplClientHTMLPuts(pappl_client_t *client, const char *s) _PAPPL_PUBLIC; extern void papplClientHTMLStartForm(pappl_client_t *client, const char *action, bool multipart) _PAPPL_PUBLIC; extern http_status_t papplClientIsAuthorized(pappl_client_t *client) _PAPPL_PUBLIC; extern bool papplClientIsEncrypted(pappl_client_t *client) _PAPPL_PUBLIC; extern bool papplClientIsValidForm(pappl_client_t *client, int num_form, cups_option_t *form) _PAPPL_PUBLIC; extern bool papplClientRespond(pappl_client_t *client, http_status_t code, const char *content_coding, const char *type, time_t last_modified, size_t length) _PAPPL_PUBLIC; extern ipp_t *papplClientRespondIPP(pappl_client_t *client, ipp_status_t status, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(3, 4); extern void papplClientRespondIPPUnsupported(pappl_client_t *client, ipp_attribute_t *attr) _PAPPL_PUBLIC; extern bool papplClientRespondRedirect(pappl_client_t *client, http_status_t code, const char *path) _PAPPL_PUBLIC; extern void papplClientSetCookie(pappl_client_t *client, const char * name, const char *value, int expires) _PAPPL_PUBLIC; extern void papplClientSetUsername(pappl_client_t *client, const char *username) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_CLIENT_H_ pappl-1.4.9/pappl/contact.c000066400000000000000000000101401476704353100155620ustar00rootroot00000000000000// // Contact functions for the Printer Application Framework // // Copyright © 2019-2021 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "base-private.h" // // '_papplContactExport()' - Export contact information to an "xxx-contact-col" value. // ipp_t * // O - "xxx-contact-col" value _papplContactExport( pappl_contact_t *contact) // I - Contact information { ipp_t *col = ippNew(); // "xxx-contact-col" value char tel_uri[256], // Telephone URI value mailto_uri[256], // Email URI value vcard[1024]; // VCARD value // Build values... if (contact->email[0]) httpAssembleURI(HTTP_URI_CODING_ALL, mailto_uri, sizeof(mailto_uri), "mailto", NULL, contact->email, 0, NULL); else mailto_uri[0] = '\0'; if (contact->telephone[0]) httpAssembleURI(HTTP_URI_CODING_ALL, tel_uri, sizeof(tel_uri), "tel", NULL, contact->telephone, 0, NULL); else tel_uri[0] = '\0'; snprintf(vcard, sizeof(vcard), "BEGIN:VCARD\r\n" "VERSION:4.0\r\n" "FN:%s\r\n" "TEL;VALUE=URI;TYPE=work:%s\r\n" "EMAIL;TYPE=work:%s\r\n" "END:VCARD\r\n", contact->name, tel_uri, contact->email); // Add values... ippAddString(col, IPP_TAG_ZERO, IPP_TAG_NAME, "contact-name", NULL, contact->name); if (mailto_uri[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_URI, "contact-uri", NULL, mailto_uri); else if (tel_uri[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_URI, "contact-uri", NULL, tel_uri); else ippAddString(col, IPP_TAG_ZERO, IPP_CONST_TAG(IPP_TAG_URI), "contact-uri", NULL, "data:,"); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_TEXT, "contact-vcard", NULL, vcard); return (col); } // // '_papplContactImport()' - Import contact information from an "xxx-contact-col" value. // void _papplContactImport( ipp_t *col, // I - "xxx-contact-col" value pappl_contact_t *contact) // O - Contact information { const char *val; // Value memset(contact, 0, sizeof(pappl_contact_t)); if ((val = ippGetString(ippFindAttribute(col, "contact-name", IPP_TAG_NAME), 0, NULL)) != NULL) papplCopyString(contact->name, val, sizeof(contact->name)); if ((val = ippGetString(ippFindAttribute(col, "contact-uri", IPP_TAG_NAME), 0, NULL)) != NULL) { char scheme[32], // URI scheme userpass[32], // User:pass from URI host[256], // Host from URI resource[256]; // Resource from URI int port; // Port number from URI if (httpSeparateURI(HTTP_URI_CODING_ALL, val, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) >= HTTP_URI_STATUS_OK) { if (!strcmp(scheme, "tel")) papplCopyString(contact->telephone, resource, sizeof(contact->telephone)); else if (!strcmp(scheme, "mailto")) papplCopyString(contact->email, resource, sizeof(contact->email)); } } if ((val = ippGetString(ippFindAttribute(col, "contact-vcard", IPP_TAG_TEXT), 0, NULL)) != NULL) { char vcard[1024], // Local copy of vcard data *ptr, // Pointer in data *next, // Next line *crlf; // CR LF at end of line // Note: Only VCARD data <= 1023 bytes currently supported... papplCopyString(vcard, val, sizeof(vcard)); for (ptr = vcard; *ptr; ptr = next) { // Find the end of the current line... if ((crlf = strstr(ptr, "\r\n")) != NULL) { *crlf = '\0'; next = crlf + 2; } else next = ptr + strlen(ptr); if (!strncmp(ptr, "FN:", 3) && !contact->name[0]) { papplCopyString(contact->name, ptr + 3, sizeof(contact->name)); } else if (!strncmp(ptr, "TEL;", 4) && !contact->telephone[0]) { if ((ptr = strstr(ptr, ":tel:")) != NULL) papplCopyString(contact->telephone, ptr + 5, sizeof(contact->telephone)); } else if (!strncmp(ptr, "EMAIL;", 6) && !contact->email[0]) { if ((ptr = strchr(ptr, ':')) != NULL) papplCopyString(contact->email, ptr + 1, sizeof(contact->email)); } } } } pappl-1.4.9/pappl/cppcheck.suppressions000066400000000000000000000013221476704353100202440ustar00rootroot00000000000000// Cppcheck bug: does not validate loop constraints properly... arrayIndexOutOfBounds:printer-driver.c // Bad CERT recommendation: C memory layout not determined by variable locations cert-API01-C // Don't report non-const casts. Inline suppression comments are not working, // otherwise we'd be more selective... cert-EXP05-C // Not handling "(unsigned)~CONSTANT" properly... cert-INT31-c // fopen_s is NOT supported on POSIX platforms and DOES NOT APPLY for reading // of files! cert-MSC24-C // char something[###] = "constant" should not result in an error! cert-STR05-C // Not sure why this is a thing... preprocessorErrorDirective // The cppcheck null pointer detection logic is totally broken ctunullpointer pappl-1.4.9/pappl/device-file.c000066400000000000000000000120551476704353100163120ustar00rootroot00000000000000// // File device support code for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "device-private.h" // // Local functions... // static void pappl_file_close(pappl_device_t *device); static bool pappl_file_open(pappl_device_t *device, const char *device_uri, const char *name); static ssize_t pappl_file_write(pappl_device_t *device, const void *buffer, size_t bytes); // // '_papplDeviceAddFileSchemeNoLock()' - Add the "file" device URI scheme. // void _papplDeviceAddFileSchemeNoLock(void) { _papplDeviceAddSchemeNoLock("file", PAPPL_DEVTYPE_FILE, /*list_cb*/NULL, pappl_file_open, pappl_file_close, /*read_cb*/NULL, pappl_file_write, /*status_cb*/NULL, /*supplies_cb*/NULL, /*id_cb*/NULL); } // // 'pappl_file_close()' - Close a file. // static void pappl_file_close(pappl_device_t *device)// I - Device { int *fd; // File descriptor // Make sure we have a valid file descriptor... if ((fd = papplDeviceGetData(device)) == NULL || *fd < 0) return; close(*fd); free(fd); papplDeviceSetData(device, NULL); } // // 'pappl_file_open()' - Open a file. // static bool // O - `true` on success, `false` otherwise pappl_file_open( pappl_device_t *device, // I - Device const char *device_uri, // I - Device URI const char *name) // I - Job name { int *fd; // File descriptor char scheme[32], // URI scheme userpass[32], // Username/password (not used) host[256], // Host name or make resource[256], // Resource path, if any *options, // Pointer to options, if any filename[1024], // Filename *fileptr; // Pointer into filename const char *ext = "prn"; // Extension int port; // Port number struct stat resinfo; // Resource path information // Allocate memory for a file descriptor if ((fd = (int *)malloc(sizeof(int))) == NULL) { papplDeviceError(device, "Unable to allocate memory for file: %s", strerror(errno)); return (false); } // Get the resource path for the filename... httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)); if ((options = strchr(resource, '?')) != NULL) { *options++ = '\0'; if (!strncmp(options, "ext=", 4) && !strchr(options, '/')) ext = options + 4; } if (stat(resource, &resinfo)) resinfo.st_mode = S_IFREG | 0644; #if _WIN32 if (!strcmp(resource, "/dev/null")) { if ((*fd = open("NUL:", O_WRONLY | O_BINARY)) < 0) { papplDeviceError(device, "Unable to open 'NUL:': %s", strerror(errno)); goto error; } } else #endif // _WIN32 if (S_ISDIR(resinfo.st_mode)) { // Resource is a directory, so create an output filename using the job name snprintf(filename, sizeof(filename), "%s/%s.%s", resource, name, ext); for (fileptr = filename + strlen(resource) + 1; *fileptr; fileptr ++) { if (*fileptr < ' ' || *fileptr == 0x7f || *fileptr & 0x80 || *fileptr == '/') *fileptr = '_'; } if ((*fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) < 0) { papplDeviceError(device, "Unable to create '%s': %s", filename, strerror(errno)); goto error; } } else if (S_ISCHR(resinfo.st_mode)) { // Resource is a character device... if ((*fd = open(resource, O_WRONLY | O_EXCL | O_BINARY)) < 0) { papplDeviceError(device, "Unable to open '%s': %s", resource, strerror(errno)); goto error; } } else if (S_ISREG(resinfo.st_mode)) { // Resource is a regular file... if ((*fd = open(resource, O_WRONLY | O_APPEND | O_CREAT | O_BINARY, 0666)) < 0) { papplDeviceError(device, "Unable to open '%s': %s", resource, strerror(errno)); goto error; } } else { *fd = -1; errno = EINVAL; } // Otherwise, save the file descriptor and return success... papplDeviceSetData(device, fd); return (true); // If we were unable to open the file, return an error... error: free(fd); return (false); } // // 'pappl_file_write()' - Write to a file. // static ssize_t // O - Bytes written pappl_file_write(pappl_device_t *device,// I - Device const void *buffer,// I - Buffer to write size_t bytes) // I - Bytes to write { int *fd; // File descriptor const char *ptr; // Pointer into buffer ssize_t count, // Total bytes written written; // Bytes written this time // Make sure we have a valid file descriptor... if ((fd = papplDeviceGetData(device)) == NULL || *fd < 0) return (-1); for (count = 0, ptr = (const char *)buffer; count < (ssize_t)bytes; count += written, ptr += written) { if ((written = write(*fd, ptr, bytes - (size_t)count)) < 0) { if (errno == EINTR || errno == EAGAIN) { written = 0; continue; } count = -1; break; } } return (count); } pappl-1.4.9/pappl/device-network.c000066400000000000000000002021141476704353100170610ustar00rootroot00000000000000// // Network device support code for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "device-private.h" #include "dnssd-private.h" #include "snmp-private.h" #include "printer-private.h" #include #if !_WIN32 # include # include #endif // !_WIN32 // // Local constants... // #define _PAPPL_MAX_SNMP_SUPPLY 32 // Maximum number of SNMP supplies #define _PAPPL_SNMP_TIMEOUT 2.0 // Timeout for SNMP queries // Generic enum values #define _PAPPL_TC_other 1 #define _PAPPL_TC_unknown 2 // hrPrinterDetectedErrorState values #define _PAPPL_TC_lowPaper 0x8000 #define _PAPPL_TC_noPaper 0x4000 #define _PAPPL_TC_lowToner 0x2000 #define _PAPPL_TC_noToner 0x1000 #define _PAPPL_TC_doorOpen 0x0800 #define _PAPPL_TC_jammed 0x0400 #define _PAPPL_TC_offline 0x0200 #define _PAPPL_TC_serviceRequested 0x0100 #define _PAPPL_TC_inputTrayMissing 0x0080 #define _PAPPL_TC_outputTrayMissing 0x0040 #define _PAPPL_TC_markerSupplyMissing 0x0020 #define _PAPPL_TC_outputNearFull 0x0010 #define _PAPPL_TC_outputFull 0x0008 #define _PAPPL_TC_inputTrayEmpty 0x0004 #define _PAPPL_TC_overduePreventMaint 0x0002 // prtMarkerSuppliesClass value #define _PAPPL_TC_supplyThatIsConsumed 3 // prtMarkerSuppliesSupplyUnit value #define _PAPPL_TC_percent 19 // prtLocalizationCharacterSet values #define _PAPPL_TC_csASCII 3 #define _PAPPL_TC_csISOLatin1 4 #define _PAPPL_TC_csShiftJIS 17 #define _PAPPL_TC_csUTF8 106 #define _PAPPL_TC_csUnicode 1000 // UCS2 BE #define _PAPPL_TC_csUCS4 1001 // UCS4 BE #define _PAPPL_TC_csUnicodeASCII 1002 #define _PAPPL_TC_csUnicodeLatin1 1003 #define _PAPPL_TC_csUTF16BE 1013 #define _PAPPL_TC_csUTF16LE 1014 #define _PAPPL_TC_csUTF32 1017 #define _PAPPL_TC_csUTF32BE 1018 #define _PAPPL_TC_csUTF32LE 1019 #define _PAPPL_TC_csWindows31J 2024 // // Local types... // typedef struct _pappl_socket_s // Socket device data { int fd; // File descriptor connection to device char *host; // Hostname int port; // Port number http_addrlist_t *list, // Address list *addr; // Connected address int snmp_fd, // SNMP socket charset, // Character set num_supplies; // Number of supplies pappl_supply_t supplies[_PAPPL_MAX_SNMP_SUPPLY]; // Supplies int colorants[_PAPPL_MAX_SNMP_SUPPLY], // Colorant indices levels[_PAPPL_MAX_SNMP_SUPPLY], // Current level max_capacities[_PAPPL_MAX_SNMP_SUPPLY], // Max capacity units[_PAPPL_MAX_SNMP_SUPPLY]; // Supply units } _pappl_socket_t; typedef struct _pappl_dns_sd_dev_t // DNS-SD browse data { #ifdef HAVE_MDNSRESPONDER DNSServiceRef ref; // Service reference for query #endif // HAVE_MDNSRESPONDER #ifdef HAVE_AVAHI AvahiRecordBrowser *ref; // Browser for query #endif // HAVE_AVAHI pthread_mutex_t mutex; // Update lock char *name, // Service name *domain, // Domain name *fullName, // Full name *make_and_model, // Make and model from TXT record *device_id, // 1284 device ID from TXT record *uuid; // UUID from TXT record } _pappl_dns_sd_dev_t; typedef struct _pappl_snmp_dev_s // SNMP browse data { http_addr_t address; // Address of device char *addrname, // Name of device *uri, // Device URI *device_id; // IEEE-1284 device id int port; // Port number } _pappl_snmp_dev_t; typedef enum _pappl_snmp_query_e // SNMP query request IDs for each field { _PAPPL_SNMP_QUERY_DEVICE_TYPE = 0x01, // Device type OID _PAPPL_SNMP_QUERY_DEVICE_ID, // IEEE-1284 device ID OIDs _PAPPL_SNMP_QUERY_DEVICE_SYSNAME, // sysName OID _PAPPL_SNMP_QUERY_DEVICE_PORT // Raw socket port number OIDs } _pappl_snmp_query_t; // // Local globals... // static const int DevicePrinterOID[] = { 1,3,6,1,2,1,25,3,1,5,-1 }; // Host MIB OID for "printer" type static const int SysNameOID[] = { 1,3,6,1,2,1,1,5,0,-1 }; // Host MIB sysName OID static const int HPDeviceIDOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 }; // HP MIB IEEE-1284 Device ID OID static const int LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 }; // Lexmark MIB IEEE-1284 Device ID OID static const int LexmarkPortOID[] = { 1,3,6,1,4,1,641,1,5,7,11,0,-1 }; // Lexmark MIB raw socket port number OID static const int ZebraDeviceIDOID[] = { 1,3,6,1,4,1,10642,1,3,0,-1 }; // Zebra MIB IEEE-1284 Device ID OID static const int ZebraPortOID[] = { 1,3,6,1,4,1,10642,20,10,20,15,2,1,10,1,-1 }; // Zebra MIB raw socket port number OID static const int PWGPPMDeviceIdOID[] = { 1,3,6,1,4,1,2699,1,2,1,2,1,1,3,1,-1 }; // PWG Printer Port Monitor MIB IEEE-1284 Device ID OID static const int PWGPPMPortOID[] = { 1,3,6,1,4,1,2699,1,2,1,3,1,1,6,1,1,-1 }; // PWG Printer Port Monitor MIB raw socket port number OID static const int RawTCPPortOID[] = { 1,3,6,1,4,1,683,6,3,1,4,17,0,-1 }; // Extended Networks MIB (common) raw socket port number OID static const int hrPrinterDetectedErrorState[] = { 1,3,6,1,2,1,25,3,5,1,2,-1 }; // Current status bits #define _PAPPL_PRINTERMIBv2 1,3,6,1,2,1,43 static const int prtGeneralCurrentLocalization[] = { _PAPPL_PRINTERMIBv2,5,1,1,2,1,-1 }; // Current localization static const int prtLocalizationCharacterSet[] = { _PAPPL_PRINTERMIBv2,7,1,1,4,-1 }; // Character set static const int prtMarkerSuppliesEntry[] = { _PAPPL_PRINTERMIBv2,11,1,1,-1 }; // Supply entry static const int prtMarkerSuppliesLevel[] = { _PAPPL_PRINTERMIBv2,11,1,1,9,-1 }; // Level static const int prtMarkerColorantValue[] = { _PAPPL_PRINTERMIBv2,12,1,1,4,-1 }; // Colorant value // // Local functions... // #ifdef HAVE_DNSSD # ifdef HAVE_MDNSRESPONDER static void pappl_dnssd_browse_cb(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context); static void pappl_dnssd_query_cb(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullName, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context); static void pappl_dnssd_resolve_cb(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context); # else static void pappl_dnssd_browse_cb(AvahiServiceBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *serviceName, const char *serviceType, const char *replyDomain, AvahiLookupResultFlags flags, void *context); static void pappl_dnssd_query_cb(AvahiRecordBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t rrclass, uint16_t rrtype, const void *rdata, size_t rdlen, AvahiLookupResultFlags flags, void *context); static void pappl_dnssd_resolve_cb(AvahiServiceResolver *resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *context); # endif // HAVE_MDNSRESPONDER static int pappl_dnssd_compare_devices(_pappl_dns_sd_dev_t *a, _pappl_dns_sd_dev_t *b); static void pappl_dnssd_free(_pappl_dns_sd_dev_t *d); static _pappl_dns_sd_dev_t *pappl_dnssd_get_device(cups_array_t *devices, const char *serviceName, const char *replyDomain); static bool pappl_dnssd_list(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data); static void pappl_dnssd_unescape(char *dst, const char *src, size_t dstsize); #endif // HAVE_DNSSD static int pappl_snmp_compare_devices(_pappl_snmp_dev_t *a, _pappl_snmp_dev_t *b); static bool pappl_snmp_find(pappl_device_cb_t cb, void *data, _pappl_socket_t *sock, pappl_deverror_cb_t err_cb, void *err_data); static void pappl_snmp_free(_pappl_snmp_dev_t *d); static http_addrlist_t *pappl_snmp_get_interface_addresses(void); static bool pappl_snmp_list(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data); static bool pappl_snmp_open_cb(const char *device_info, const char *device_uri, const char *device_id, void *data); static void pappl_snmp_read_response(cups_array_t *devices, int fd, pappl_deverror_cb_t err_cb, void *err_data); static void pappl_snmp_walk_cb(_pappl_snmp_t *packet, _pappl_socket_t *sock); static void pappl_socket_close(pappl_device_t *device); static char *pappl_socket_getid(pappl_device_t *device, char *buffer, size_t bufsize); static bool pappl_socket_open(pappl_device_t *device, const char *device_uri, const char *name); static ssize_t pappl_socket_read(pappl_device_t *device, void *buffer, size_t bytes); static pappl_preason_t pappl_socket_status(pappl_device_t *device); static int pappl_socket_supplies(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies); static ssize_t pappl_socket_write(pappl_device_t *device, const void *buffer, size_t bytes); static void utf16_to_utf8(char *dst, const unsigned char *src, size_t srcsize, size_t dstsize, bool le); // // '_papplDeviceAddNetworkSchemesNoLock()' - Add all of the supported network schemes. // void _papplDeviceAddNetworkSchemesNoLock(void) { #ifdef HAVE_DNSSD _papplDeviceAddSchemeNoLock("dnssd", PAPPL_DEVTYPE_DNS_SD, pappl_dnssd_list, pappl_socket_open, pappl_socket_close, pappl_socket_read, pappl_socket_write, pappl_socket_status, pappl_socket_supplies, pappl_socket_getid); #endif // HAVE_DNSSD _papplDeviceAddSchemeNoLock("snmp", PAPPL_DEVTYPE_SNMP, pappl_snmp_list, pappl_socket_open, pappl_socket_close, pappl_socket_read, pappl_socket_write, pappl_socket_status, pappl_socket_supplies, pappl_socket_getid); _papplDeviceAddSchemeNoLock("socket", PAPPL_DEVTYPE_SOCKET, NULL, pappl_socket_open, pappl_socket_close, pappl_socket_read, pappl_socket_write, pappl_socket_status, pappl_socket_supplies, pappl_socket_getid); } #ifdef HAVE_DNSSD # ifdef HAVE_MDNSRESPONDER // // 'pappl_dnssd_browse_cb()' - Browse for DNS-SD devices. // static void pappl_dnssd_browse_cb( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Option flags uint32_t interfaceIndex, // I - Interface number DNSServiceErrorType errorCode, // I - Error, if any const char *serviceName, // I - Name of service/device const char *regtype, // I - Registration type const char *replyDomain, // I - Service domain void *context) // I - Devices array { _PAPPL_DEBUG("DEBUG: pappl_browse_cb(sdRef=%p, flags=%x, interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\", context=%p)\n", sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain, context); (void)sdRef; (void)interfaceIndex; (void)regtype; // Only process "add" data... if (errorCode == kDNSServiceErr_NoError && (flags & kDNSServiceFlagsAdd)) { // Get the device... pappl_dnssd_get_device((cups_array_t *)context, serviceName, replyDomain); } } # else // // 'pappl_dnssd_browse_cb()' - Browse for DNS-SD devices. // static void pappl_dnssd_browse_cb( AvahiServiceBrowser *browser, // I - Browser AvahiIfIndex interface, // I - Interface index AvahiProtocol protocol, // I - Network protocol AvahiBrowserEvent event, // I - What happened const char *name, // I - Service name const char *type, // I - Service type const char *domain, // I - Domain AvahiLookupResultFlags flags, // I - Flags void *context) // I - Devices array { if (event == AVAHI_BROWSER_NEW) pappl_dnssd_get_device((cups_array_t *)context, name, domain); } # endif // HAVE_MDNSRESPONDER // // 'pappl_dnssd_compare_devices()' - Compare two DNS-SD devices. // static int // O - Result of comparison pappl_dnssd_compare_devices( _pappl_dns_sd_dev_t *a, // I - First device _pappl_dns_sd_dev_t *b) // I - Second device { _PAPPL_DEBUG("pappl_dnssd_compare_devices(a=%p(%s), b=%p(%s))\n", a, a->name, b, b->name); return (strcmp(a->name, b->name)); } // // 'pappl_dnssd_free()' - Free the memory used for a DNS-SD device. // static void pappl_dnssd_free(_pappl_dns_sd_dev_t *d)// I - Device { // Free all memory... free(d->name); free(d->domain); free(d->fullName); free(d->make_and_model); free(d->device_id); free(d->uuid); pthread_mutex_destroy(&d->mutex); #ifdef HAVE_MDNSRESPONDER if (d->ref) DNSServiceRefDeallocate(d->ref); #elif defined(HAVE_AVAHI) if (d->ref) { _papplDNSSDLock(); avahi_record_browser_free(d->ref); _papplDNSSDUnlock(); } #endif // HAVE_MDNSRESPONDER free(d); } // // 'pappl_dnssd_get_device()' - Create or update a DNS-SD device. // static _pappl_dns_sd_dev_t * // O - Device pappl_dnssd_get_device( cups_array_t *devices, // I - Device array const char *serviceName, // I - Name of service/device const char *replyDomain) // I - Service domain { _pappl_dns_sd_dev_t key, // Search key *device; // Device char fullName[1024]; // Full name for query _PAPPL_DEBUG("pappl_dnssd_get_device(devices=%p, serviceName=\"%s\", replyDomain=\"%s\")\n", devices, serviceName, replyDomain); // See if this is a new device... key.name = (char *)serviceName; if ((device = cupsArrayFind(devices, &key)) != NULL) { // Nope, see if this is for a different domain... if (!strcasecmp(device->domain, "local.") && strcasecmp(device->domain, replyDomain)) { // Update the .local listing to use the "global" domain name instead. free(device->domain); device->domain = strdup(replyDomain); # ifdef HAVE_MDNSRESPONDER DNSServiceConstructFullName(fullName, device->name, "_pdl-datastream._tcp.", replyDomain); # else avahi_service_name_join(fullName, sizeof(fullName), serviceName, "_pdl-datastream._tcp.", replyDomain); # endif // HAVE_MDNSRESPONDER free(device->fullName); if ((device->fullName = strdup(fullName)) == NULL) { cupsArrayRemove(devices, device); return (NULL); } } return (device); } // Yes, add the device... if ((device = calloc(sizeof(_pappl_dns_sd_dev_t), 1)) == NULL) return (NULL); pthread_mutex_init(&device->mutex, NULL); if ((device->name = strdup(serviceName)) == NULL) { free(device); return (NULL); } device->domain = strdup(replyDomain); cupsArrayAdd(devices, device); // Set the "full name" of this service, which is used for queries... # ifdef HAVE_MDNSRESPONDER DNSServiceConstructFullName(fullName, serviceName, "_pdl-datastream._tcp.", replyDomain); # else avahi_service_name_join(fullName, sizeof(fullName), serviceName, "_pdl-datastream._tcp.", replyDomain); # endif /* HAVE_MDNSRESPONDER */ if ((device->fullName = strdup(fullName)) == NULL) { cupsArrayRemove(devices, device); return (NULL); } // Query the TXT record for the device ID and make and model... #ifdef HAVE_MDNSRESPONDER device->ref = _papplDNSSDInit(NULL); DNSServiceQueryRecord(&(device->ref), kDNSServiceFlagsShareConnection, 0, device->fullName, kDNSServiceType_TXT, kDNSServiceClass_IN, pappl_dnssd_query_cb, device); #else device->ref = avahi_record_browser_new(_papplDNSSDInit(NULL), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, device->fullName, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, pappl_dnssd_query_cb, device); #endif /* HAVE_AVAHI */ return (device); } // // 'pappl_dnssd_list()' - List printers using DNS-SD. // static bool // O - `true` if the callback returned `true`, `false` otherwise pappl_dnssd_list( pappl_device_cb_t cb, // I - Callback function void *data, // I - User data for callback pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Data for error callback { bool ret = false; // Return value cups_array_t *devices; // DNS-SD devices _pappl_dns_sd_dev_t *device; // Current DNS-SD device char device_id[1024],// IEEE-1284 device ID device_name[1024], // Network device name device_uri[1024]; // Network device URI cups_len_t last_count; // Last number of devices int timeout; // Timeout counter # ifdef HAVE_MDNSRESPONDER int error; // Error code, if any DNSServiceRef pdl_ref; // Browse reference for _pdl-datastream._tcp # else AvahiServiceBrowser *pdl_ref; // Browse reference for _pdl-datastream._tcp _pappl_dns_sd_t dnssd; // DNS-SD service # endif // HAVE_MDNSRESPONDER devices = cupsArrayNew((cups_array_cb_t)pappl_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_cb_t)pappl_dnssd_free); _PAPPL_DEBUG("pappl_dnssd_find: devices=%p\n", devices); _papplDNSSDLock(); # ifdef HAVE_MDNSRESPONDER pdl_ref = _papplDNSSDInit(NULL); _PAPPL_DEBUG("pappl_dnssd_find: pdl_ref=%p (before)\n", pdl_ref); if ((error = DNSServiceBrowse(&pdl_ref, kDNSServiceFlagsShareConnection, 0, "_pdl-datastream._tcp", NULL, (DNSServiceBrowseReply)pappl_dnssd_browse_cb, devices)) != kDNSServiceErr_NoError) { _papplDeviceError(err_cb, err_data, "Unable to create service browser: %s (%d).", _papplDNSSDStrError(error), error); cupsArrayDelete(devices); _papplDNSSDUnlock(); return (ret); } _PAPPL_DEBUG("pappl_dnssd_find: pdl_ref=%p (after)\n", pdl_ref); # else if ((dnssd = _papplDNSSDInit(NULL)) == NULL) { _papplDeviceError(err_cb, err_data, "Unable to create DNSSD service."); cupsArrayDelete(devices); _papplDNSSDUnlock(); return (ret); } if ((pdl_ref = avahi_service_browser_new(dnssd, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_pdl-datastream._tcp", NULL, 0, pappl_dnssd_browse_cb, devices)) == NULL) { _papplDeviceError(err_cb, err_data, "Unable to create service browser."); cupsArrayDelete(devices); _papplDNSSDUnlock(); return (ret); } # endif // HAVE_MDNSRESPONDER _papplDNSSDUnlock(); // Wait up to 10 seconds for us to find all available devices... for (timeout = 10000, last_count = 0; timeout > 0; timeout -= 250) { // 250000 microseconds == 250 milliseconds _PAPPL_DEBUG("pappl_dnssd_find: timeout=%d, last_count=%u\n", timeout, (unsigned)last_count); usleep(250000); if (last_count == cupsArrayGetCount(devices)) break; last_count = cupsArrayGetCount(devices); } _PAPPL_DEBUG("pappl_dnssd_find: timeout=%d, last_count=%u\n", timeout, (unsigned)last_count); // Stop browsing... _papplDNSSDLock(); # ifdef HAVE_MDNSRESPONDER DNSServiceRefDeallocate(pdl_ref); # else avahi_service_browser_free(pdl_ref); # endif // HAVE_MDNSRESPONDER _papplDNSSDUnlock(); // Do the callback for each of the devices... for (device = (_pappl_dns_sd_dev_t *)cupsArrayGetFirst(devices); device; device = (_pappl_dns_sd_dev_t *)cupsArrayGetNext(devices)) { snprintf(device_name, sizeof(device_name), "%s (DNS-SD Network Printer)", device->name); if (device->uuid) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, device->fullName, 0, "/?uuid=%s", device->uuid); else httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, device->fullName, 0, "/"); pthread_mutex_lock(&device->mutex); if (device->device_id) papplCopyString(device_id, device->device_id, sizeof(device_id)); else device_id[0] = '\0'; pthread_mutex_unlock(&device->mutex); if ((*cb)(device_name, device_uri, device_id, data)) { ret = true; break; } } // Free memory and return... cupsArrayDelete(devices); return (ret); } // // 'pappl_dnssd_query_cb()' - Query a DNS-SD service. // # ifdef HAVE_MDNSRESPONDER static void pappl_dnssd_query_cb( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Data flags uint32_t interfaceIndex, // I - Interface (unused) DNSServiceErrorType errorCode, // I - Error, if any const char *fullName, // I - Full service name uint16_t rrtype, // I - Record type uint16_t rrclass, // I - Record class uint16_t rdlen, // I - Length of record data const void *rdata, // I - Record data uint32_t ttl, // I - Time-to-live void *context) // I - Device # else static void pappl_dnssd_query_cb( AvahiRecordBrowser *browser, // I - Record browser */ AvahiIfIndex interfaceIndex, // I - Interface index (unused) AvahiProtocol protocol, // I - Network protocol (unused) AvahiBrowserEvent event, // I - What happened? const char *fullName, // I - Service name uint16_t rrclass, // I - Record class uint16_t rrtype, // I - Record type const void *rdata, // I - TXT record size_t rdlen, // I - Length of TXT record AvahiLookupResultFlags flags, // I - Flags void *context) // I - Device # endif // HAVE_MDNSRESPONDER { char *ptr; // Pointer into string _pappl_dns_sd_dev_t *device = (_pappl_dns_sd_dev_t *)context; // Device const uint8_t *data, // Pointer into data *datanext, // Next key/value pair *dataend; // End of entire TXT record uint8_t datalen; // Length of current key/value pair char key[256], // Key string value[256], // Value string cmd[256], // usb_CMD string mdl[256], // usb_MDL string mfg[256], // usb_MFG string pdl[256], // pdl string product[256], // product string ty[256], // ty string device_id[1024]; // 1284 device ID */ # ifdef HAVE_MDNSRESPONDER // Only process "add" data... if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd)) return; (void)sdRef; (void)interfaceIndex; (void)fullName; (void)ttl; (void)rrtype; (void)rrclass; # else // Only process "add" data... if (event != AVAHI_BROWSER_NEW) return; (void)interfaceIndex; (void)protocol; (void)fullName; (void)rrclass; (void)rrtype; (void)flags; # endif // HAVE_MDNSRESPONDER // Pull out the make and model and device ID data from the TXT record... cmd[0] = '\0'; mfg[0] = '\0'; mdl[0] = '\0'; pdl[0] = '\0'; product[0] = '\0'; ty[0] = '\0'; for (data = rdata, dataend = data + rdlen; data < dataend; data = datanext) { // Read a key/value pair starting with an 8-bit length. Since the length is // 8 bits and the size of the key/value buffers is 256, we don't need to // check for overflow... datalen = *data++; if (!datalen || (data + datalen) > dataend) break; datanext = data + datalen; for (ptr = key; data < datanext && *data != '='; data ++) *ptr++ = (char)*data; *ptr = '\0'; if (data < datanext && *data == '=') { data ++; if (data < datanext) memcpy(value, data, (size_t)(datanext - data)); value[datanext - data] = '\0'; } else { continue; } if (!strcasecmp(key, "usb_CMD")) papplCopyString(cmd, value, sizeof(cmd)); else if (!strcasecmp(key, "usb_MDL")) papplCopyString(mdl, value, sizeof(mdl)); else if (!strcasecmp(key, "usb_MFG")) papplCopyString(mfg, value, sizeof(mfg)); else if (!strcasecmp(key, "pdl")) papplCopyString(pdl, value, sizeof(pdl)); else if (!strcasecmp(key, "product")) papplCopyString(product, value, sizeof(product)); else if (!strcasecmp(key, "ty")) papplCopyString(ty, value, sizeof(ty)); } // Synthesize values as needed... if (!cmd[0] && pdl[0]) { size_t i; // Looping var char *cmdptr, // Pointer into CMD value *pdlptr, // Pointer into pdl value mime[128], // Current pdl MIME media type *mimeptr; // Pointer into MIME media type static const char * const pdls[][2] = { // MIME media type to command set mapping { "application/postscript", "PS" }, { "application/vnd.canon-cpdl", "CPDL" }, { "application/vnd.canon-lips", "LIPS" }, { "application/vnd.hp-PCL", "PCL" }, { "application/vnd.hp-PCLXL", "PCLXL" }, { "application/vnd.ms-xpsdocument", "XPS" }, { "image/jpeg", "JPEG" }, { "image/pwg-raster", "PWGRaster" }, { "image/tiff", "TIFF" }, { "image/urf", "URF" } }; for (pdlptr = pdl, cmdptr = cmd; *pdlptr;) { // Copy current MIME media type from pdl value... for (mimeptr = mime; *pdlptr && *pdlptr != ','; pdlptr ++) { if (mimeptr < (mime + sizeof(mime) - 1)) *mimeptr++ = *pdlptr; } *mimeptr = '\0'; if (*pdlptr) pdlptr ++; // See if it is a known MIME media type and map to the corresponding 1284 // command-set name... for (i = 0; i < (sizeof(pdls) / sizeof(pdls[0])); i ++) { if (!strcasecmp(mime, pdls[i][0])) { // MIME media type matches, append this CMD value... if (cmdptr > cmd && cmdptr < (cmd + sizeof(cmd) - 1)) *cmdptr++ = ','; papplCopyString(cmdptr, pdls[i][1], sizeof(cmd) - (size_t)(cmdptr - cmd)); cmdptr += strlen(cmdptr); } } } if (!strcmp(mfg, "EPSON")) { // Append ESC/P2 for EPSON printers... if (cmdptr > cmd) papplCopyString(cmdptr, ",ESCPL2", sizeof(cmd) - (size_t)(cmdptr - cmd)); else papplCopyString(cmdptr, "ESCPL2", sizeof(cmd) - (size_t)(cmdptr - cmd)); } } if (!ty[0] && product[0]) { if (product[0] == '(') { papplCopyString(ty, product + 1, sizeof(ty)); if ((ptr = product + strlen(product) - 1) >= product && *ptr == ')') *ptr = '\0'; } else papplCopyString(ty, product, sizeof(ty)); } if (!ty[0] && mfg[0] && mdl[0]) snprintf(ty, sizeof(ty), "%s %s", mfg, mdl); if (!mfg[0] && ty[0]) { papplCopyString(mfg, ty, sizeof(mfg)); if ((ptr = strchr(mfg, ' ')) != NULL) *ptr = '\0'; } if (!mdl[0] && ty[0]) { if ((ptr = strchr(ty, ' ')) != NULL) papplCopyString(mdl, ptr + 1, sizeof(mdl)); else papplCopyString(mdl, ty, sizeof(mdl)); } snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;CMD:%s;", mfg, mdl, cmd); // Save the make and model and IEEE-1284 device ID... pthread_mutex_lock(&device->mutex); device->device_id = strdup(device_id); device->make_and_model = strdup(ty); pthread_mutex_unlock(&device->mutex); } // // 'pappl_dnssd_resolve_cb()' - Resolve a DNS-SD service. // # ifdef HAVE_MDNSRESPONDER static void pappl_dnssd_resolve_cb( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Option flags uint32_t interfaceIndex, // I - Interface number DNSServiceErrorType errorCode, // I - Error, if any const char *fullname, // I - Full service domain name const char *host_name, // I - Host name uint16_t port, // I - Port number uint16_t txtLen, // I - TXT record len const unsigned char *txtRecord, // I - TXT record void *context) // I - Device { (void)sdRef; (void)flags; (void)interfaceIndex; (void)fullname; (void)txtLen; (void)txtRecord; _PAPPL_DEBUG("pappl_dnssd_resolve_cb(sdRef=%p, flags=0x%x, interfaceIndex=%u, errorCode=%d, fullname=\"%s\", host_name=\"%s\", port=%u, txtLen=%u, txtRecord=%p, context=%p)\n", sdRef, flags, interfaceIndex, errorCode, fullname, host_name, ntohs(port), txtLen, txtRecord, context); if (errorCode == kDNSServiceErr_NoError) { _pappl_socket_t *sock = (_pappl_socket_t *)context; // Socket sock->host = strdup(host_name); sock->port = ntohs(port); } } # else // // 'pappl_dnssd_resolve_cb()' - Resolve a DNS-SD service. // static void pappl_dnssd_resolve_cb( AvahiServiceResolver *resolver, // I - Service resolver AvahiIfIndex interface, // I - Interface number AvahiProtocol protocol, // I - Network protocol AvahiResolverEvent event, // I - What happened const char *name, // I - Service name const char *type, // I - Service type const char *domain, // I - Domain const char *host_name, // I - Host name const AvahiAddress *address, // I - Address uint16_t port, // I - Port number AvahiStringList *txt, // I - TXT record AvahiLookupResultFlags flags, // I - Flags void *context) // I - Device { if (!resolver) return; if (event == AVAHI_RESOLVER_FOUND) { _pappl_socket_t *sock = (_pappl_socket_t *)context; // Socket sock->host = strdup(host_name); sock->port = port; } } # endif // HAVE_MDNSRESPONDER // // 'pappl_dnssd_unescape()' - Unescape a service name. // static void pappl_dnssd_unescape( char *dst, // I - Destination buffer const char *src, // I - Source string size_t dstsize) // I - Size of destination buffer { char *dstend = dst + dstsize - 1; // End of destination buffer while (*src && dst < dstend) { if (*src == '\\') { src ++; if (isdigit(src[0] & 255) && isdigit(src[1] & 255) && isdigit(src[2] & 255)) { *dst++ = ((((src[0] - '0') * 10) + src[1] - '0') * 10) + src[2] - '0'; src += 3; } else *dst++ = *src++; } else *dst++ = *src ++; } *dst = '\0'; } #endif // HAVE_DNSSD // // 'pappl_snmp_compare_devices()' - Compare two SNMP devices. // static int // O - Result of comparison pappl_snmp_compare_devices( _pappl_snmp_dev_t *a, // I - First device _pappl_snmp_dev_t *b) // I - Second device { int ret = strcmp(a->addrname, b->addrname); // Return value _PAPPL_DEBUG("pappl_snmp_compare_devices(a=%p(%s), b=%p(%s)) = %d\n", a, a->addrname, b, b->addrname, ret); return (ret); } // // 'pappl_snmp_find()' - Find an SNMP device. // static bool // O - `true` if found, `false` if not pappl_snmp_find( pappl_device_cb_t cb, // I - Callback function void *data, // I - User data pointer _pappl_socket_t *sock, // O - Device info pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Error callback data { bool ret = false; // Return value cups_array_t *devices = NULL;// Device array int snmp_sock = -1; // SNMP socket cups_len_t last_count; // Last devices count fd_set input; // Input set for select() struct timeval timeout; // Timeout for select() time_t endtime; // End time for scan http_addrlist_t *addrs, // List of addresses *addr; // Current address _pappl_snmp_dev_t *cur_device; // Current device #ifdef DEBUG char temp[1024]; // Temporary address string #endif // DEBUG static const int DeviceTypeOID[] = { // Device Type OID 1,3,6,1,2,1,25,3,2,1,2,1,-1 }; // Create an array to track SNMP devices... devices = cupsArrayNew((cups_array_cb_t)pappl_snmp_compare_devices, NULL, NULL, 0, NULL, (cups_afree_cb_t)pappl_snmp_free); // Open SNMP socket... if ((snmp_sock = _papplSNMPOpen(AF_INET)) < 0) { _papplDeviceError(err_cb, err_data, "Unable to open SNMP socket."); goto finished; } // Get the list of network interface broadcast addresses... if ((addrs = pappl_snmp_get_interface_addresses()) == NULL) { _papplDeviceError(err_cb, err_data, "Unable to get SNMP broadcast addresses."); goto finished; } // Send queries to every broadcast address... for (addr = addrs; addr; addr = addr->next) { _PAPPL_DEBUG("pappl_snmp_find: Sending SNMP device type get request to '%s'.\n", httpAddrGetString(&(addr->addr), temp, sizeof(temp))); _papplSNMPWrite(snmp_sock, &(addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_TYPE, DeviceTypeOID); } // Free broadcast addresses (all done with them...) httpAddrFreeList(addrs); // Wait up to 30 seconds to discover printers via SNMP... FD_ZERO(&input); for (endtime = time(NULL) + 30, last_count = 0; time(NULL) < endtime;) { // Wait up to 2 seconds for more data... timeout.tv_sec = 2; timeout.tv_usec = 0; FD_SET(snmp_sock, &input); _PAPPL_DEBUG("Running select() for %d.\n", snmp_sock); if (select(snmp_sock + 1, &input, NULL, NULL, &timeout) < 0) { _papplDeviceError(err_cb, err_data, "SNMP select() failed with error: %s", strerror(errno)); break; } if (FD_ISSET(snmp_sock, &input)) { _PAPPL_DEBUG("pappl_snmp_find: Reading SNMP response.\n"); pappl_snmp_read_response(devices, snmp_sock, err_cb, err_data); } else { if (last_count == cupsArrayGetCount(devices)) break; last_count = cupsArrayGetCount(devices); _PAPPL_DEBUG("pappl_snmp_find: timeout=%d, last_count=%u\n", (int)(endtime - time(NULL)), (unsigned)last_count); } } _PAPPL_DEBUG("pappl_snmp_find: timeout=%d, last_count=%u\n", (int)(endtime - time(NULL)), (unsigned)last_count); // Report all of the devices we found... for (cur_device = (_pappl_snmp_dev_t *)cupsArrayGetFirst(devices); cur_device; cur_device = (_pappl_snmp_dev_t *)cupsArrayGetNext(devices)) { char info[256]; // Device description cups_len_t num_did; // Number of device ID keys/values cups_option_t *did; // Device ID keys/values const char *make, // Manufacturer *model; // Model name // Skip LPD (port 515) and IPP (port 631) since they can't be raw sockets... if (cur_device->port == 515 || cur_device->port == 631 || !cur_device->uri) continue; num_did = (cups_len_t)papplDeviceParseID(cur_device->device_id, &did); if ((make = cupsGetOption("MANUFACTURER", num_did, did)) == NULL) if ((make = cupsGetOption("MFG", num_did, did)) == NULL) if ((make = cupsGetOption("MFGR", num_did, did)) == NULL) make = "Unknown"; if ((model = cupsGetOption("MODEL", num_did, did)) == NULL) if ((model = cupsGetOption("MDL", num_did, did)) == NULL) model = "Printer"; if (!strcmp(make, "HP") && !strncmp(model, "HP ", 3)) snprintf(info, sizeof(info), "%s (Network Printer %s)", model, cur_device->uri + 7); else snprintf(info, sizeof(info), "%s %s (Network Printer %s)", make, model, cur_device->uri + 7); if ((*cb)(info, cur_device->uri, cur_device->device_id, data)) { // Save the address and port... char address_str[256]; // IP address as a string sock->host = strdup(httpAddrGetString(&cur_device->address, address_str, sizeof(address_str))); sock->port = cur_device->port; ret = true; break; } } // Clean up and return... finished: cupsArrayDelete(devices); _papplSNMPClose(snmp_sock); return (ret); } // // 'pappl_snmp_free()' - Free the memory used for SNMP device. // static void pappl_snmp_free(_pappl_snmp_dev_t *d) // I - SNMP device { // Free all memory... free(d->addrname); free(d->device_id); free(d->uri); free(d); } // // 'pappl_snmp_get_interface_addresses()' - Get interface broadcast addresses. // static http_addrlist_t * // O - List of addresses pappl_snmp_get_interface_addresses(void) { #if _WIN32 return (NULL); // TODO: Implement WinSock equivalents #else struct ifaddrs *addrs, // Interface address list *addr; // Current interface address http_addrlist_t *first, // First address in list *last, // Last address in list *current; // Current address // Get a list of network interfaces... if (getifaddrs(&addrs) < 0) { // Unable to get the list... return (NULL); } // Copy the broadcast addresses into a list of addresses... for (addr = addrs, first = NULL, last = NULL; addr; addr = addr->ifa_next) { if ((addr->ifa_flags & IFF_BROADCAST) && addr->ifa_broadaddr && addr->ifa_broadaddr->sa_family == AF_INET) { // Copy this IPv4 broadcast address... if ((current = calloc(1, sizeof(http_addrlist_t))) != NULL) { memcpy(&(current->addr), addr->ifa_broadaddr, sizeof(struct sockaddr_in)); if (!last) first = current; else last->next = current; last = current; } } } // Free the original interface addresses and return... freeifaddrs(addrs); return (first); #endif // _WIN32 } // // 'pappl_snmp_list()' - List SNMP printers. // static bool // O - `true` if found, `false` otherwise pappl_snmp_list( pappl_device_cb_t cb, // I - Device callback void *data, // I - Device callback data pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Error callback data { _pappl_socket_t sock; // Socket data bool ret; // Return value memset(&sock, 0, sizeof(sock)); ret = pappl_snmp_find(cb, data, &sock, err_cb, err_data); free(sock.host); return (ret); } // // 'pappl_snmp_open_cb()' - Look for a matching device URI. // static bool // O - `true` on match, `false` otherwise pappl_snmp_open_cb( const char *device_info, // I - Device description const char *device_uri, // I - This device's URI const char *device_id, // I - IEEE-1284 Device ID void *data) // I - URI we are looking for { bool match = !strcmp(device_uri, (const char *)data); // Does this match? (void)device_info; (void)device_id; _PAPPL_DEBUG("pappl_snmp_open_cb(device_info=\"%s\", device_uri=\"%s\", device_id=\"%s\", user_data=\"%s\") = %s\n", device_info, device_uri, device_id, (char *)data, match ? "true" : "false"); return (match); } // // 'pappl_snmp_read_response()' - Read and parse a SNMP response. // static void pappl_snmp_read_response( cups_array_t *devices, // Devices array int fd, // I - SNMP socket file descriptor pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Data for error callback { int i; // Looping variable _pappl_snmp_t packet; // Decoded packet _pappl_snmp_dev_t *device, // Matching device *temp; // New device entry char addrname[256]; // Source address name // Read the response data if (!_papplSNMPRead(fd, &packet, -1.0)) { _papplDeviceError(err_cb, err_data, "Unable to read SNMP response data: %s", strerror(errno)); return; } httpAddrGetString(&(packet.address), addrname, sizeof(addrname)); // Look for the response status code in the SNMP message header if (packet.error) { _papplDeviceError(err_cb, err_data, "Bad SNMP packet from '%s': %s", addrname, packet.error); return; } _PAPPL_DEBUG("pappl_snmp_read_response: community=\"%s\"\n", packet.community); _PAPPL_DEBUG("pappl_snmp_read_response: request-id=%u\n", packet.request_id); _PAPPL_DEBUG("pappl_snmp_read_response: error-status=%d\n", packet.error_status); if (packet.error_status && packet.request_id != _PAPPL_SNMP_QUERY_DEVICE_TYPE) return; // Find a matching device in the cache for (device = (_pappl_snmp_dev_t *)cupsArrayGetFirst(devices); device; device = (_pappl_snmp_dev_t *)cupsArrayGetNext(devices)) { if (!strcmp(device->addrname, addrname)) break; } // Process the message switch (packet.request_id) { case _PAPPL_SNMP_QUERY_DEVICE_TYPE: if (device) { _PAPPL_DEBUG("pappl_snmp_read_response: Discarding duplicate device type for \"%s\".\n", addrname); return; } for (i = 0; DevicePrinterOID[i] >= 0; i ++) { if (DevicePrinterOID[i] != packet.object_value.oid[i]) { _PAPPL_DEBUG("pappl_snmp_read_response: Discarding device (not printer).\n"); return; } } if (packet.object_value.oid[i] >= 0) { _PAPPL_DEBUG("pappl_snmp_read_response: Discarding device (not printer).\n"); return; } // Add the device and request the device data if ((temp = calloc(1, sizeof(_pappl_snmp_dev_t))) == NULL) { _PAPPL_DEBUG("pappl_snmp_read_response: Unable to allocate memory for device.\n"); return; } temp->address = packet.address; temp->addrname = strdup(addrname); temp->port = 9100; // Default port to use if (!temp->addrname) { _PAPPL_DEBUG("pappl_snmp_read_response: Unable to allocate memory for device name.\n"); free(temp); return; } cupsArrayAdd(devices, temp); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_SYSNAME, SysNameOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, HPDeviceIDOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, LexmarkDeviceIdOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, PWGPPMDeviceIdOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, ZebraDeviceIDOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_PORT, LexmarkPortOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_PORT, ZebraPortOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_PORT, PWGPPMPortOID); _papplSNMPWrite(fd, &(packet.address), _PAPPL_SNMP_VERSION_1, packet.community, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_PORT, RawTCPPortOID); break; case _PAPPL_SNMP_QUERY_DEVICE_ID: if (device && packet.object_type == _PAPPL_ASN1_OCTET_STRING && (!device->device_id || strlen(device->device_id) < packet.object_value.string.num_bytes)) { char *ptr; // Pointer into device ID for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++) { if (*ptr == '\n') // A lot of bad printers put a newline *ptr = ';'; } free(device->device_id); device->device_id = strdup((char *)packet.object_value.string.bytes); } break; case _PAPPL_SNMP_QUERY_DEVICE_SYSNAME: if (device && packet.object_type == _PAPPL_ASN1_OCTET_STRING && !device->uri) { char uri[2048]; // Device URI snprintf(uri, sizeof(uri), "snmp://%s", (char *)packet.object_value.string.bytes); device->uri = strdup(uri); } break; case _PAPPL_SNMP_QUERY_DEVICE_PORT: if (device) { if (packet.object_type == _PAPPL_ASN1_INTEGER) { device->port = packet.object_value.integer; } else if (packet.object_type == _PAPPL_ASN1_OCTET_STRING) { char *end; // End of string device->port = (int)strtol((char *)packet.object_value.string.bytes, &end, 10); if (errno == ERANGE || *end) device->port = 0; } } break; } } // // 'pappl_snmp_walk_cb()' - Update supply information. // static void pappl_snmp_walk_cb( _pappl_snmp_t *packet, // I - SNMP packet _pappl_socket_t *sock) // I - Socket device { int i, j, // Looping vars element; // Element in supply table char *ptr; // Pointer into colorant name static const pappl_supply_type_t types[] = { // Supply types mapped from SNMP TC values PAPPL_SUPPLY_TYPE_OTHER, PAPPL_SUPPLY_TYPE_UNKNOWN, PAPPL_SUPPLY_TYPE_TONER, PAPPL_SUPPLY_TYPE_WASTE_TONER, PAPPL_SUPPLY_TYPE_INK, PAPPL_SUPPLY_TYPE_INK_CARTRIDGE, PAPPL_SUPPLY_TYPE_INK_RIBBON, PAPPL_SUPPLY_TYPE_WASTE_INK, PAPPL_SUPPLY_TYPE_OPC, PAPPL_SUPPLY_TYPE_DEVELOPER, PAPPL_SUPPLY_TYPE_FUSER_OIL, PAPPL_SUPPLY_TYPE_SOLID_WAX, PAPPL_SUPPLY_TYPE_RIBBON_WAX, PAPPL_SUPPLY_TYPE_WASTE_WAX, PAPPL_SUPPLY_TYPE_FUSER, PAPPL_SUPPLY_TYPE_CORONA_WIRE, PAPPL_SUPPLY_TYPE_FUSER_OIL_WICK, PAPPL_SUPPLY_TYPE_CLEANER_UNIT, PAPPL_SUPPLY_TYPE_FUSER_CLEANING_PAD, PAPPL_SUPPLY_TYPE_TRANSFER_UNIT, PAPPL_SUPPLY_TYPE_TONER_CARTRIDGE, PAPPL_SUPPLY_TYPE_FUSER_OILER, PAPPL_SUPPLY_TYPE_WATER, PAPPL_SUPPLY_TYPE_WASTE_WATER, PAPPL_SUPPLY_TYPE_GLUE_WATER_ADDITIVE, PAPPL_SUPPLY_TYPE_WASTE_PAPER, PAPPL_SUPPLY_TYPE_BINDING_SUPPLY, PAPPL_SUPPLY_TYPE_BANDING_SUPPLY, PAPPL_SUPPLY_TYPE_STITCHING_WIRE, PAPPL_SUPPLY_TYPE_SHRINK_WRAP, PAPPL_SUPPLY_TYPE_PAPER_WRAP, PAPPL_SUPPLY_TYPE_STAPLES, PAPPL_SUPPLY_TYPE_INSERTS, PAPPL_SUPPLY_TYPE_COVERS }; if (_papplSNMPIsOIDPrefixed(packet, prtMarkerColorantValue) && packet->object_type == _PAPPL_ASN1_OCTET_STRING) { // Get colorant... i = packet->object_name[sizeof(prtMarkerColorantValue) / sizeof(prtMarkerColorantValue[0])]; _PAPPL_DEBUG("pappl_snmp_walk_cb: prtMarkerColorantValue.1.%d = \"%s\"\n", i, (char *)packet->object_value.string.bytes); // Strip "ink" or "toner" off the end of the colorant name... if ((ptr = strstr((char *)packet->object_value.string.bytes, " ink")) != NULL) *ptr = '\0'; else if ((ptr = strstr((char *)packet->object_value.string.bytes, " toner")) != NULL) *ptr = '\0'; // Map to each supply using this colorant... for (j = 0; j < sock->num_supplies; j ++) { if (sock->colorants[j] == i) sock->supplies[j].color = _papplSupplyColorValue((char *)packet->object_value.string.bytes); } } else if (_papplSNMPIsOIDPrefixed(packet, prtMarkerSuppliesEntry)) { // Get indices... element = packet->object_name[sizeof(prtMarkerSuppliesEntry) / sizeof(prtMarkerSuppliesEntry[0]) - 1]; i = packet->object_name[sizeof(prtMarkerSuppliesEntry) / sizeof(prtMarkerSuppliesEntry[0]) + 1]; _PAPPL_DEBUG("pappl_snmp_walk_cb: prtMarkerSuppliesEntry.%d.%d\n", element, i); if (element < 1 || i < 1 || i > _PAPPL_MAX_SNMP_SUPPLY) return; if (i > sock->num_supplies) sock->num_supplies = i; i --; switch (element) { case 3 : // prtMarkerSuppliesColorantIndex if (packet->object_type == _PAPPL_ASN1_INTEGER) sock->colorants[i] = packet->object_value.integer; break; case 4 : // prtMarkerSuppliesClass if (packet->object_type == _PAPPL_ASN1_INTEGER) sock->supplies[i].is_consumed = packet->object_value.integer == _PAPPL_TC_supplyThatIsConsumed; break; case 5 : // prtMarkerSuppliesType if (packet->object_type == _PAPPL_ASN1_INTEGER && packet->object_value.integer >= 1 && packet->object_value.integer <= (int)(sizeof(types) / sizeof(types[0]))) sock->supplies[i].type = types[packet->object_value.integer - 1]; break; case 6 : // prtMarkerSuppliesDescription if (packet->object_type != _PAPPL_ASN1_OCTET_STRING) break; switch (sock->charset) { case _PAPPL_TC_csASCII : case _PAPPL_TC_csUTF8 : case _PAPPL_TC_csUnicodeASCII : papplCopyString(sock->supplies[i].description, (char *)packet->object_value.string.bytes, sizeof(sock->supplies[i].description)); break; case _PAPPL_TC_csISOLatin1 : case _PAPPL_TC_csUnicodeLatin1 : cupsCharsetToUTF8((cups_utf8_t *)sock->supplies[i].description, (char *)packet->object_value.string.bytes, (cups_len_t)sizeof(sock->supplies[i].description), CUPS_ENCODING_ISO8859_1); break; case _PAPPL_TC_csShiftJIS : case _PAPPL_TC_csWindows31J : /* Close enough for our purposes */ cupsCharsetToUTF8((cups_utf8_t *)sock->supplies[i].description, (char *)packet->object_value.string.bytes, (cups_len_t)sizeof(sock->supplies[i].description), CUPS_ENCODING_JIS_X0213); break; case _PAPPL_TC_csUCS4 : case _PAPPL_TC_csUTF32 : case _PAPPL_TC_csUTF32BE : case _PAPPL_TC_csUTF32LE : cupsUTF32ToUTF8((cups_utf8_t *)sock->supplies[i].description, (cups_utf32_t *)packet->object_value.string.bytes, (cups_len_t)sizeof(sock->supplies[i].description)); break; case _PAPPL_TC_csUnicode : case _PAPPL_TC_csUTF16BE : case _PAPPL_TC_csUTF16LE : utf16_to_utf8(sock->supplies[i].description, packet->object_value.string.bytes, packet->object_value.string.num_bytes, sizeof(sock->supplies[i].description), sock->charset == _PAPPL_TC_csUTF16LE); break; default : // If we get here, the printer is using an unknown character set and // we just want to copy characters that look like ASCII... { char *src, *dst, *dstend; // Pointers into strings for (src = (char *)packet->object_value.string.bytes, dst = sock->supplies[i].description, dstend = dst + sizeof(sock->supplies[i].description) - 1; *src && dst < dstend; src ++) { if ((*src & 0x80) || *src < ' ' || *src == 0x7f) *dst++ = '?'; else *dst++ = *src; } *dst = '\0'; } break; } break; case 7 : // prtMarkerSuppliesSupplyUnit if (packet->object_type == _PAPPL_ASN1_INTEGER && packet->object_value.integer == _PAPPL_TC_percent) sock->max_capacities[i] = 100; break; case 8 : // prtMarkerSuppliesMaxCapacity if (packet->object_type == _PAPPL_ASN1_INTEGER && sock->max_capacities[i] == 0 && packet->object_value.integer > 0) sock->max_capacities[i] = packet->object_value.integer; break; case 9 : // prtMarkerSuppliesLevel if (packet->object_type == _PAPPL_ASN1_INTEGER) sock->levels[i] = packet->object_value.integer; break; } } } // // 'pappl_socket_close()' - Close a network socket. // static void pappl_socket_close( pappl_device_t *device) // I - Device { _pappl_socket_t *sock; // Socket device if ((sock = papplDeviceGetData(device)) == NULL) return; #if _WIN32 closesocket(sock->fd); closesocket(sock->snmp_fd); #else close(sock->fd); close(sock->snmp_fd); #endif // _WIN32 httpAddrFreeList(sock->list); free(sock); papplDeviceSetData(device, NULL); } // // 'pappl_socket_getid()' - Get the current IEEE-1284 device ID via SNMP. // static char * // O - Device ID or `NULL` on error pappl_socket_getid( pappl_device_t *device, // I - Device char *buffer, // I - Buffer size_t bufsize) // I - Size of buffer { _pappl_socket_t *sock; // Socket device struct pollfd data; // poll() data _pappl_snmp_t packet; // Decoded packet *buffer = '\0'; // Get the socket data... if ((sock = papplDeviceGetData(device)) == NULL) return (NULL); // Send queries to the printer... _papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, PWGPPMDeviceIdOID); _papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, HPDeviceIDOID); _papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, LexmarkDeviceIdOID); _papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, _PAPPL_SNMP_QUERY_DEVICE_ID, ZebraDeviceIDOID); // Wait up to 10 seconds to get a response... data.fd = sock->snmp_fd; data.events = POLLIN; while (poll(&data, 1, 10000) > 0) { if (!_papplSNMPRead(sock->snmp_fd, &packet, -1.0)) continue; if (packet.error || packet.error_status) continue; if (packet.object_type == _PAPPL_ASN1_OCTET_STRING) { char *ptr; // Pointer into device ID for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++) { if (*ptr == '\n') // A lot of bad printers put a newline *ptr = ';'; } strncpy(buffer, (char *)packet.object_value.string.bytes, bufsize - 1); buffer[bufsize - 1] = '\0'; break; } } return (*buffer ? buffer : NULL); } // // 'pappl_socket_open()' - Open a network socket. // static bool // O - `true` on success, `false` on failure pappl_socket_open( pappl_device_t *device, // I - Device const char *device_uri, // I - Device URI const char *job_name) // I - Job name { _pappl_socket_t *sock; // Socket device char scheme[32], // URI scheme userpass[32], // Username/password (not used) host[256], // Host name or make resource[256], // Resource path, if any *options; // Pointer to options, if any int port; // Port number char port_str[32]; // String for port number (void)job_name; // Allocate memory for the socket... if ((sock = (_pappl_socket_t *)calloc(1, sizeof(_pappl_socket_t))) == NULL) { papplDeviceError(device, "Unable to allocate memory for socket device: %s", strerror(errno)); return (false); } sock->snmp_fd = -1; sock->charset = -1; sock->num_supplies = -1; // Split apart the URI... httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)); if ((options = strchr(resource, '?')) != NULL) *options++ = '\0'; if (!strcmp(scheme, "dnssd")) { // DNS-SD discovered device #ifdef HAVE_DNSSD int i; // Looping var char srvname[256], // Service name *type, // Service type *domain; // Domain _pappl_dns_sd_t master; // DNS-SD context # ifdef HAVE_MDNSRESPONDER int error; // Error code, if any DNSServiceRef resolver; // Resolver # else AvahiServiceResolver *resolver; // Resolver # endif // HAVE_MDNSRESPONDER if ((domain = strstr(host, "._tcp.")) != NULL) { // Truncate host at domain portion... domain += 5; *domain++ = '\0'; // Then separate the service type portion... type = strstr(host, "._"); *type ++ = '\0'; // Unescape the service name... pappl_dnssd_unescape(srvname, host, sizeof(srvname)); master = _papplDNSSDInit(NULL); _PAPPL_DEBUG("pappl_socket_open: host='%s', srvname='%s', type='%s', domain='%s'\n", host, srvname, type, domain); # ifdef HAVE_MDNSRESPONDER resolver = master; if ((error = DNSServiceResolve(&resolver, kDNSServiceFlagsShareConnection, 0, srvname, type, domain, (DNSServiceResolveReply)pappl_dnssd_resolve_cb, sock)) != kDNSServiceErr_NoError) { papplDeviceError(device, "Unable to resolve '%s': %s", device_uri, _papplDNSSDStrError(error)); goto error; } # else _papplDNSSDLock(); if ((resolver = avahi_service_resolver_new(master, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, srvname, type, domain, AVAHI_PROTO_UNSPEC, 0, (AvahiServiceResolverCallback)pappl_dnssd_resolve_cb, sock)) == NULL) { papplDeviceError(device, "Unable to resolve '%s'.", device_uri); _papplDNSSDUnlock(); goto error; } _papplDNSSDUnlock(); # endif // HAVE_MDNSRESPONDER // Wait up to 30 seconds for the resolve to complete... for (i = 0; i < 30000 && !sock->host; i ++) usleep(1000); # ifdef HAVE_MDNSRESPONDER DNSServiceRefDeallocate(resolver); # else _papplDNSSDLock(); avahi_service_resolver_free(resolver); _papplDNSSDUnlock(); # endif // HAVE_MDNSRESPONDER if (!sock->host) { papplDeviceError(device, "Unable to resolve '%s'.", device_uri); goto error; } } #endif // HAVE_DNSSD } else if (!strcmp(scheme, "snmp")) { // SNMP discovered device if (!pappl_snmp_find(pappl_snmp_open_cb, (void *)device_uri, sock, NULL, NULL)) goto error; } else if (!strcmp(scheme, "socket")) { // Raw socket (JetDirect or similar) sock->host = strdup(host); sock->port = port; } // Lookup the address of the printer... snprintf(port_str, sizeof(port_str), "%d", sock->port); if ((sock->list = httpAddrGetList(sock->host, AF_UNSPEC, port_str)) == NULL) { papplDeviceError(device, "Unable to lookup '%s:%d': %s", sock->host, sock->port, cupsGetErrorString()); goto error; } sock->fd = -1; sock->addr = httpAddrConnect(sock->list, &sock->fd, 30000, NULL); if (sock->fd < 0) { papplDeviceError(device, "Unable to connect to '%s:%d': %s", sock->host, sock->port, cupsGetErrorString()); goto error; } // Open SNMP socket... if ((sock->snmp_fd = _papplSNMPOpen(httpAddrGetFamily(&(sock->addr->addr)))) < 0) { papplDeviceError(device, "Unable to open SNMP socket."); return (false); } papplDeviceSetData(device, sock); _PAPPL_DEBUG("Connection successful, device fd = %d\n", sock->fd); return (true); // If we get here there was an error... error: free(sock->host); httpAddrFreeList(sock->list); free(sock); return (false); } // // 'pappl_socket_read()' - Read from a network socket. // static ssize_t // O - Number of bytes read pappl_socket_read( pappl_device_t *device, // I - Device void *buffer, // I - Buffer to read into size_t bytes) // I - Bytes to read { _pappl_socket_t *sock; // Socket device ssize_t count; // Total bytes read struct pollfd data; // poll() data int nfds; // poll() return value if ((sock = papplDeviceGetData(device)) == NULL) return (-1); // Only read if we have data to read within 100ms... data.fd = sock->fd; data.events = POLLIN; data.revents = 0; while ((nfds = poll(&data, 1, 10000)) < 0) { if (errno != EINTR && errno != EAGAIN) break; } if (nfds < 1 || !(data.revents & POLLIN)) return (-1); // Read data from the socket, protecting against signals and busy kernels... #if _WIN32 while ((count = recv(sock->fd, buffer, (int)bytes, 0)) < 0) #else while ((count = read(sock->fd, buffer, bytes)) < 0) #endif // _WIN32 { if (errno != EINTR && errno != EAGAIN) break; } return (count); } // // 'pappl_socket_status()' - Get the current network device status. // static pappl_preason_t // O - New "printer-state-reasons" values pappl_socket_status( pappl_device_t *device) // I - Device { _pappl_socket_t *sock; // Socket device pappl_preason_t reasons = PAPPL_PREASON_NONE; // "printer-state-reasons" values _pappl_snmp_t packet; // SNMP packet int state; // State bits // Get the device data... if ((sock = papplDeviceGetData(device)) == NULL) return (0); if (!_papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, 1, hrPrinterDetectedErrorState)) return (reasons); if (!_papplSNMPRead(sock->snmp_fd, &packet, _PAPPL_SNMP_TIMEOUT) || packet.object_type != _PAPPL_ASN1_OCTET_STRING) return (reasons); if (packet.object_value.string.num_bytes == 2) state = (packet.object_value.string.bytes[0] << 8) | packet.object_value.string.bytes[1]; else if (packet.object_value.string.num_bytes == 1) state = (packet.object_value.string.bytes[0] << 8); else state = 0; if (state & (_PAPPL_TC_noPaper | _PAPPL_TC_inputTrayEmpty)) reasons |= PAPPL_PREASON_MEDIA_EMPTY; if (state & _PAPPL_TC_doorOpen) reasons |= PAPPL_PREASON_DOOR_OPEN; if (state & _PAPPL_TC_inputTrayMissing) reasons |= PAPPL_PREASON_INPUT_TRAY_MISSING; return (reasons); } // // 'pappl_socket_supplies()' - Query supply levels via SNMP. // static int // O - Number of supplies pappl_socket_supplies( pappl_device_t *device, // I - Device int max_supplies, // I - Maximum number of supply levels pappl_supply_t *supplies) // I - Supply levels { _pappl_socket_t *sock; // Socket device int i; // Looping var #ifdef DEBUG char temp[1024]; // OID string #endif // DEBUG // Get the device data... _PAPPL_DEBUG("pappl_socket_supplies(device=%p, max_supplies=%d, supplies=%p)\n", device, max_supplies, supplies); if ((sock = papplDeviceGetData(device)) == NULL) return (0); // Get the current character set as needed... if (sock->charset < 0) { _pappl_snmp_t packet; // SNMP packet int oid[_PAPPL_SNMP_MAX_OID]; // OID for property if (!_papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, 1, prtGeneralCurrentLocalization)) { _PAPPL_DEBUG("pappl_socket_supplies: Unable to query prtGeneralCurrentLocalization\n"); return (0); } if (!_papplSNMPRead(sock->snmp_fd, &packet, _PAPPL_SNMP_TIMEOUT) || packet.object_type != _PAPPL_ASN1_INTEGER) { _PAPPL_DEBUG("pappl_socket_supplies: Unable to read prtGeneralCurrentLocalization value.\n"); return (0); } _papplSNMPCopyOID(oid, prtLocalizationCharacterSet, _PAPPL_SNMP_MAX_OID); oid[sizeof(prtLocalizationCharacterSet) / sizeof(prtLocalizationCharacterSet[0]) - 1] = packet.object_value.integer; oid[sizeof(prtLocalizationCharacterSet) / sizeof(prtLocalizationCharacterSet[0])] = 1; oid[sizeof(prtLocalizationCharacterSet) / sizeof(prtLocalizationCharacterSet[0]) + 1] = -1; _PAPPL_DEBUG("pappl_socket_supplies: Looking up %s.\n", _papplSNMPOIDToString(oid, temp, sizeof(temp))); if (!_papplSNMPWrite(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, _PAPPL_ASN1_GET_REQUEST, 1, oid)) { _PAPPL_DEBUG("pappl_socket_supplies: Unable to query prtLocalizationCharacterSet.%d\n", packet.object_value.integer); return (0); } if (!_papplSNMPRead(sock->snmp_fd, &packet, _PAPPL_SNMP_TIMEOUT) || packet.object_type != _PAPPL_ASN1_INTEGER) { _PAPPL_DEBUG("pappl_socket_supplies: Unable to read prtLocalizationCharacterSet value.\n"); return (0); } sock->charset = packet.object_value.integer; _PAPPL_DEBUG("pappl_socket_supplies: charset=%d\n", sock->charset); } // Query supplies... if (sock->num_supplies > 0) { // Just update the levels... _papplSNMPWalk(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, prtMarkerSuppliesLevel, _PAPPL_SNMP_TIMEOUT, (_pappl_snmp_cb_t)pappl_snmp_walk_cb, sock); } else { // Query all of the supply elements... _papplSNMPWalk(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, prtMarkerSuppliesEntry, _PAPPL_SNMP_TIMEOUT, (_pappl_snmp_cb_t)pappl_snmp_walk_cb, sock); _papplSNMPWalk(sock->snmp_fd, &(sock->addr->addr), _PAPPL_SNMP_VERSION_1, _PAPPL_SNMP_COMMUNITY, prtMarkerColorantValue, _PAPPL_SNMP_TIMEOUT, (_pappl_snmp_cb_t)pappl_snmp_walk_cb, sock); } // Update levels... for (i = 0; i < sock->num_supplies; i ++) { int percent; // Supply level if (sock->max_capacities[i] > 0 && sock->levels[i] >= 0) percent = 100 * sock->levels[i] / sock->max_capacities[i]; else if (sock->levels[i] >= 0 && sock->levels[i] <= 100) percent = sock->levels[i]; else percent = 50; if (sock->supplies[i].is_consumed) sock->supplies[i].level = percent; else sock->supplies[i].level = 100 - percent; } // Return the supplies that are cached in the socket device... if (sock->num_supplies > 0) { if (sock->num_supplies > max_supplies) memcpy(supplies, sock->supplies, (size_t)max_supplies * sizeof(pappl_supply_t)); else memcpy(supplies, sock->supplies, (size_t)sock->num_supplies * sizeof(pappl_supply_t)); } return (sock->num_supplies); } // // 'pappl_socket_write()' - Write to a network socket. // static ssize_t // O - Number of bytes written pappl_socket_write( pappl_device_t *device, // I - Device const void *buffer, // I - Write buffer size_t bytes) // I - Bytes to write { _pappl_socket_t *sock; // Socket device ssize_t count, // Total bytes written written; // Bytes written this time const char *ptr; // Pointer into buffer if ((sock = papplDeviceGetData(device)) == NULL) return (-1); for (count = 0, ptr = (const char *)buffer; count < (ssize_t)bytes; count += written, ptr += written) { #if _WIN32 if ((written = send(sock->fd, ptr, (int)(bytes - (size_t)count), 0)) < 0) #else if ((written = write(sock->fd, ptr, bytes - (size_t)count)) < 0) #endif // _WIN32 { if (errno == EINTR || errno == EAGAIN) { written = 0; continue; } count = -1; break; } } return (count); } // // 'utf16_to_utf8()' - Convert UTF-16 text to UTF-8. // static void utf16_to_utf8( char *dst, // I - Destination buffer const unsigned char *src, // I - Source string size_t srcsize, // I - Size of source string size_t dstsize, // I - Size of destination buffer bool le) // I - Source is little-endian? { cups_utf32_t ch, // Current character temp[_PAPPL_SNMP_MAX_STRING], // UTF-32 string *ptr; // Pointer into UTF-32 string for (ptr = temp; srcsize >= 2;) { if (le) ch = (cups_utf32_t)(src[0] | (src[1] << 8)); else ch = (cups_utf32_t)((src[0] << 8) | src[1]); src += 2; srcsize -= 2; if (ch >= 0xd800 && ch <= 0xdbff && srcsize >= 2) { // Multi-word UTF-16 char... cups_utf32_t lch; // Lower word if (le) lch = (cups_utf32_t)(src[0] | (src[1] << 8)); else lch = (cups_utf32_t)((src[0] << 8) | src[1]); if (lch >= 0xdc00 && lch <= 0xdfff) { src += 2; srcsize -= 2; ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; } } if (ptr < (temp + _PAPPL_SNMP_MAX_STRING - 1)) *ptr++ = ch; } *ptr = '\0'; cupsUTF32ToUTF8((cups_utf8_t *)dst, temp, (cups_len_t)dstsize); } pappl-1.4.9/pappl/device-private.h000066400000000000000000000046061476704353100170550ustar00rootroot00000000000000// // Private device communication functions for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_DEVICE_PRIVATE_H_ # define _PAPPL_DEVICE_PRIVATE_H_ # include "base-private.h" # include "device.h" // // Constants... // #define PAPPL_DEVICE_BUFSIZE 8192 // Size of write buffer // // Types... // struct _pappl_device_s // Device connection data { pappl_devclose_cb_t close_cb; // Close callback pappl_deverror_cb_t error_cb; // Error callback pappl_devid_cb_t id_cb; // IEEE-1284 device ID callback pappl_devread_cb_t read_cb; // Read callback pappl_devstatus_cb_t status_cb; // Status callback pappl_devsupplies_cb_t supplies_cb; // Supplies callback pappl_devwrite_cb_t write_cb; // Write callback void *device_data, // Data pointer for device *error_data; // Data pointer for error callback char buffer[PAPPL_DEVICE_BUFSIZE]; // Write buffer size_t bufused; // Number of bytes in write buffer pappl_devmetrics_t metrics; // Device metrics }; typedef void (*_pappl_devscheme_cb_t)(const char *scheme, void *data); typedef struct _pappl_dinfo_s // Device information { char *device_info, // Device *device_uri, // Device URI string *device_id; // IEEE-1284 device ID string } _pappl_dinfo_t; // // Functions... // extern void _papplDeviceAddFileSchemeNoLock(void) _PAPPL_PRIVATE; extern void _papplDeviceAddNetworkSchemesNoLock(void) _PAPPL_PRIVATE; extern void _papplDeviceAddSchemeNoLock(const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devsupplies_cb_t supplies_cb, pappl_devid_cb_t id_cb) _PAPPL_PRIVATE; extern void _papplDeviceAddSupportedSchemes(ipp_t *attrs) _PAPPL_PRIVATE; extern void _papplDeviceAddUSBSchemeNoLock(void) _PAPPL_PRIVATE; extern void _papplDeviceError(pappl_deverror_cb_t err_cb, void *err_data, const char *message, ...) _PAPPL_FORMAT(3,4) _PAPPL_PRIVATE; extern bool _papplDeviceInfoCallback(const char *device_info, const char *device_uri, const char *device_id, cups_array_t *devices) _PAPPL_PRIVATE; extern cups_array_t *_papplDeviceInfoCreateArray(void) _PAPPL_PRIVATE; #endif // !_PAPPL_DEVICE_H_ pappl-1.4.9/pappl/device-usb.c000066400000000000000000000562301476704353100161670ustar00rootroot00000000000000// // USB device support code for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // //#define DEBUG 1 #include "device-private.h" #include "printer.h" #ifdef HAVE_LIBUSB # include #endif // HAVE_LIBUSB // // Local constants... // #define _PAPPL_MAX_DEVICE_ID 1024 // Maximum length of device ID string // // Local types... // #ifdef HAVE_LIBUSB typedef struct _pappl_usb_dev_s // USB device data { struct libusb_device *device; // Device info struct libusb_device_handle *handle; // Open handle to device int conf, // Configuration origconf, // Original configuration iface, // Interface ifacenum, // Interface number altset, // Alternate setting write_endp, // Write endpoint read_endp, // Read endpoint protocol; // Protocol: 1 = Uni-di, 2 = Bi-di. char device_id[_PAPPL_MAX_DEVICE_ID]; // IEEE-1284 device ID } _pappl_usb_dev_t; #endif // HAVE_LIBUSB // // Local functions... // #ifdef HAVE_LIBUSB static void pappl_usb_close(pappl_device_t *device); static bool pappl_usb_find(pappl_device_cb_t cb, void *data, _pappl_usb_dev_t *device, pappl_deverror_cb_t err_cb, void *err_data); static char *pappl_usb_getid(pappl_device_t *device, char *buffer, size_t bufsize); static bool pappl_usb_list(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data); static bool pappl_usb_open(pappl_device_t *device, const char *device_uri, const char *name); static bool pappl_usb_open_cb(const char *device_info, const char *device_uri, const char *device_id, void *data); static ssize_t pappl_usb_read(pappl_device_t *device, void *buffer, size_t bytes); static pappl_preason_t pappl_usb_status(pappl_device_t *device); static ssize_t pappl_usb_write(pappl_device_t *device, const void *buffer, size_t bytes); #endif // HAVE_LIBUSB // // '_papplDeviceAddUSBSchemeNoLock()' - Add the USB scheme. // void _papplDeviceAddUSBSchemeNoLock(void) { #ifdef HAVE_LIBUSB _papplDeviceAddSchemeNoLock("usb", PAPPL_DEVTYPE_USB, pappl_usb_list, pappl_usb_open, pappl_usb_close, pappl_usb_read, pappl_usb_write, pappl_usb_status, /*supplies_cb*/NULL, pappl_usb_getid); #endif // HAVE_LIBUSB } #ifdef HAVE_LIBUSB // // 'pappl_usb_close()' - Close a USB device. // static void pappl_usb_close(pappl_device_t *device) // I - Device { _pappl_usb_dev_t *usb = (_pappl_usb_dev_t *)papplDeviceGetData(device); // USB device data libusb_close(usb->handle); libusb_unref_device(usb->device); free(usb); papplDeviceSetData(device, NULL); } // // 'pappl_usb_find()' - Find a USB printer. // static bool // O - `true` if found, `false` if not pappl_usb_find( pappl_device_cb_t cb, // I - Callback function void *data, // I - User data pointer _pappl_usb_dev_t *device, // O - USB device info pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Error callback data { ssize_t err = 0, // Current error i, // Looping var num_udevs; // Number of USB devices libusb_device **udevs; // USB devices /* * Get the list of connected USB devices... */ device->device = NULL; device->handle = NULL; if ((err = libusb_init(NULL)) != 0) { _papplDeviceError(err_cb, err_data, "Unable to initialize USB access: %s", libusb_strerror((enum libusb_error)err)); return (false); } num_udevs = libusb_get_device_list(NULL, &udevs); _PAPPL_DEBUG("pappl_usb_find: num_udevs=%d\n", (int)num_udevs); // Find the printers and do the callback until we find a match. for (i = 0; i < num_udevs; i ++) { libusb_device *udevice = udevs[i]; // Current device char device_id_buf[_PAPPL_MAX_DEVICE_ID + 2], // Current device ID buffer device_info[256], // Current device description device_uri[1024]; // Current device URI struct libusb_device_descriptor devdesc; // Current device descriptor struct libusb_config_descriptor *confptr = NULL; // Pointer to current configuration const struct libusb_interface *ifaceptr = NULL; // Pointer to current interface const struct libusb_interface_descriptor *altptr = NULL; // Pointer to current alternate setting const struct libusb_endpoint_descriptor *endpptr = NULL; // Pointer to current endpoint uint8_t conf, // Current configuration iface, // Current interface altset, // Current alternate setting endp, // Current endpoint read_endp, // Current read endpoint write_endp; // Current write endpoint // Ignore devices with no configuration data and anything that is not // a printer... if (libusb_get_device_descriptor(udevice, &devdesc) < 0) { _PAPPL_DEBUG("pappl_usb_find: udev%d - no descriptor.\n", (int)i); continue; } _PAPPL_DEBUG("pappl_usb_find: udev%d -\n", (int)i); _PAPPL_DEBUG("pappl_usb_find: bLength=%d\n", devdesc.bLength); _PAPPL_DEBUG("pappl_usb_find: bDescriptorType=%d\n", devdesc.bDescriptorType); _PAPPL_DEBUG("pappl_usb_find: bcdUSB=%04x\n", devdesc.bcdUSB); _PAPPL_DEBUG("pappl_usb_find: bDeviceClass=%d\n", devdesc.bDeviceClass); _PAPPL_DEBUG("pappl_usb_find: bDeviceSubClass=%d\n", devdesc.bDeviceSubClass); _PAPPL_DEBUG("pappl_usb_find: bDeviceProtocol=%d\n", devdesc.bDeviceProtocol); _PAPPL_DEBUG("pappl_usb_find: bMaxPacketSize0=%d\n", devdesc.bMaxPacketSize0); _PAPPL_DEBUG("pappl_usb_find: idVendor=0x%04x\n", devdesc.idVendor); _PAPPL_DEBUG("pappl_usb_find: idProduct=0x%04x\n", devdesc.idProduct); _PAPPL_DEBUG("pappl_usb_find: bcdDevice=%04x\n", devdesc.bcdDevice); _PAPPL_DEBUG("pappl_usb_find: iManufacturer=%d\n", devdesc.iManufacturer); _PAPPL_DEBUG("pappl_usb_find: iProduct=%d\n", devdesc.iProduct); _PAPPL_DEBUG("pappl_usb_find: iSerialNumber=%d\n", devdesc.iSerialNumber); _PAPPL_DEBUG("pappl_usb_find: bNumConfigurations=%d\n", devdesc.bNumConfigurations); if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct) continue; if (devdesc.idVendor == 0x05ac) continue; // Skip Apple devices... device->device = udevice; device->handle = NULL; device->conf = -1; device->origconf = -1; device->iface = -1; device->ifacenum = -1; device->altset = -1; device->write_endp = -1; device->read_endp = -1; device->protocol = 0; for (conf = 0; conf < devdesc.bNumConfigurations; conf ++) { if (libusb_get_config_descriptor(udevice, conf, &confptr) < 0) { _PAPPL_DEBUG("pappl_usb_find: conf%d - no descriptor\n", conf); continue; } _PAPPL_DEBUG("pappl_usb_find: conf%d -\n", conf); _PAPPL_DEBUG("pappl_usb_find: bLength=%d\n", confptr->bLength); _PAPPL_DEBUG("pappl_usb_find: bDescriptorType=%d\n", confptr->bDescriptorType); _PAPPL_DEBUG("pappl_usb_find: wTotalLength=%d\n", confptr->wTotalLength); _PAPPL_DEBUG("pappl_usb_find: bNumInterfaces=%d\n", confptr->bNumInterfaces); _PAPPL_DEBUG("pappl_usb_find: bConfigurationValue=%d\n", confptr->bConfigurationValue); _PAPPL_DEBUG("pappl_usb_find: iConfiguration=%d\n", confptr->iConfiguration); _PAPPL_DEBUG("pappl_usb_find: bmAttributes=%d\n", confptr->bmAttributes); _PAPPL_DEBUG("pappl_usb_find: MaxPower=%d\n", confptr->MaxPower); _PAPPL_DEBUG("pappl_usb_find: interface=%p\n", confptr->interface); _PAPPL_DEBUG("pappl_usb_find: extra=%p\n", confptr->extra); _PAPPL_DEBUG("pappl_usb_find: extra_length=%d\n", confptr->extra_length); // Some printers offer multiple interfaces... for (iface = 0, ifaceptr = confptr->interface; iface < confptr->bNumInterfaces; iface ++, ifaceptr ++) { if (!ifaceptr->altsetting) { _PAPPL_DEBUG("pappl_usb_find: iface%d - no alternate setting\n", iface); continue; } _PAPPL_DEBUG("pappl_usb_find: iface%d -\n", iface); _PAPPL_DEBUG("pappl_usb_find: num_altsetting=%d\n", ifaceptr->num_altsetting); _PAPPL_DEBUG("pappl_usb_find: altsetting=%p\n", ifaceptr->altsetting); device->protocol = 0; for (altset = 0, altptr = ifaceptr->altsetting; (int)altset < ifaceptr->num_altsetting; altset ++, altptr ++) { _PAPPL_DEBUG("pappl_usb_find: altset%d - bInterfaceClass=%d, bInterfaceSubClass=%d, bInterfaceProtocol=%d\n", altset, altptr->bInterfaceClass, altptr->bInterfaceSubClass, altptr->bInterfaceProtocol); if (altptr->bInterfaceClass != LIBUSB_CLASS_PRINTER || altptr->bInterfaceSubClass != 1) continue; if (altptr->bInterfaceProtocol != 1 && altptr->bInterfaceProtocol != 2) continue; if (altptr->bInterfaceProtocol < device->protocol || altptr->bInterfaceProtocol > 2) continue; read_endp = 0xff; write_endp = 0xff; for (endp = 0, endpptr = altptr->endpoint; endp < altptr->bNumEndpoints; endp ++, endpptr ++) { if ((endpptr->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK) { if (endpptr->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) read_endp = endp; else write_endp = endp; } } if (write_endp != 0xff) { // Save the best match so far... device->protocol = altptr->bInterfaceProtocol; device->altset = altptr->bAlternateSetting; device->ifacenum = altptr->bInterfaceNumber; device->write_endp = write_endp; if (device->protocol > 1) device->read_endp = read_endp; } } _PAPPL_DEBUG("pappl_usb_find: device->protocol=%d\n", device->protocol); if (device->protocol > 0) { device->conf = conf; device->iface = iface; if (!libusb_open(udevice, &device->handle)) { uint8_t current; // Current configuration // Opened the device, try to set the configuration... if (libusb_control_transfer(device->handle, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE, 8, /* GET_CONFIGURATION */ 0, 0, (unsigned char *)¤t, 1, 5000) < 0) current = 0; #ifdef __linux // Make sure the old, busted usblp kernel driver is not loaded... if (libusb_kernel_driver_active(device->handle, device->iface) == 1) { if ((err = libusb_detach_kernel_driver(device->handle, device->iface)) < 0 && err != LIBUSB_ERROR_NOT_FOUND) { _papplDeviceError(err_cb, err_data, "Unable to detach usblp kernel driver for USB printer %04x:%04x: %s", devdesc.idVendor, devdesc.idProduct, libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } #endif // __linux if (device->handle && confptr->bConfigurationValue != current) { // Select the configuration we want... if (libusb_set_configuration(device->handle, confptr->bConfigurationValue) < 0) { libusb_close(device->handle); device->handle = NULL; } } if (device->handle) { // Claim the interface... if ((err = libusb_claim_interface(device->handle, device->ifacenum)) < 0) { _papplDeviceError(err_cb, err_data, "Unable to claim USB interface: %s", libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } if (device->handle && ifaceptr->num_altsetting > 1) { // Set the alternate setting as needed... if ((err = libusb_set_interface_alt_setting(device->handle, device->ifacenum, device->altset)) < 0) { _papplDeviceError(err_cb, err_data, "Unable to set alternate USB interface: %s", libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } if (device->handle) { // Get the 1284 Device ID... if ((err = libusb_control_transfer(device->handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE, 0, (uint16_t)device->conf, (uint16_t)((device->iface << 8) | device->altset), (unsigned char *)device_id_buf, sizeof(device_id_buf), 5000)) < 0) { _papplDeviceError(err_cb, err_data, "Unable to get IEEE-1284 device ID: %s", libusb_strerror((enum libusb_error)err)); device_id_buf[0] = '\0'; libusb_close(device->handle); device->handle = NULL; } else { int length = ((device_id_buf[0] & 255) << 8) | (device_id_buf[1] & 255); if (length < 14 || length > (int)(sizeof(device->device_id) - 2)) length = ((device_id_buf[1] & 255) << 8) | (device_id_buf[0] & 255); if (length > (int)(sizeof(device->device_id) - 2)) length = (int)(sizeof(device->device_id) - 2); else if (length < 2) length = 0; else length -= 2; if (length > 0) memmove(device->device_id, device_id_buf + 2, (size_t)length); device->device_id[length] = '\0'; _PAPPL_DEBUG("pappl_usb_find: device_id=\"%s\"\n", device->device_id); } } if (device->handle) { // Build the device URI... const char *make, // Pointer to make *model; // Pointer to model char *ptr, // Pointer into device ID copy_did[_PAPPL_MAX_DEVICE_ID], // Copy of device ID temp_mfg[256], // Temporary string for manufacturer temp_mdl[256], // Temporary string for model sn[256]; // String for serial # if (libusb_get_string_descriptor_ascii(device->handle, devdesc.iManufacturer, (unsigned char *)temp_mfg, sizeof(temp_mfg)) <= 0) papplCopyString(temp_mfg, "Unknown", sizeof(temp_mfg)); if (libusb_get_string_descriptor_ascii(device->handle, devdesc.iProduct, (unsigned char *)temp_mdl, sizeof(temp_mdl)) <= 0) papplCopyString(temp_mdl, "Product", sizeof(temp_mdl)); if (libusb_get_string_descriptor_ascii(device->handle, devdesc.iSerialNumber, (unsigned char *)sn, sizeof(sn)) <= 0) snprintf(sn, sizeof(sn), "%d.%d", device->conf, device->iface); if (!device->device_id[0]) { // Blank device ID, build one from the USB device strings... snprintf(device->device_id, sizeof(device->device_id), "MFG:%s;MDL:%s;SN:%s;", temp_mfg, temp_mdl, sn); } papplCopyString(copy_did, device->device_id, sizeof(copy_did)); if ((make = strstr(copy_did, "MANUFACTURER:")) != NULL) make += 13; else if ((make = strstr(copy_did, "MFG:")) != NULL) make += 4; else make = temp_mfg; if ((model = strstr(copy_did, "MODEL:")) != NULL) model += 6; else if ((model = strstr(copy_did, "MDL:")) != NULL) model += 4; else model = temp_mdl; if (make) { if ((ptr = strchr(make, ';')) != NULL) *ptr = '\0'; } if (model) { if ((ptr = strchr(model, ';')) != NULL) *ptr = '\0'; } httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "usb", NULL, make, 0, "/%s?serial=%s", model, sn); if (!strcmp(make, "HP") && !strncmp(model, "HP ", 3)) snprintf(device_info, sizeof(device_info), "%s (USB)", model); else snprintf(device_info, sizeof(device_info), "%s %s (USB)", make, model); if ((*cb)(device_info, device_uri, device->device_id, data)) { _PAPPL_DEBUG("pappl_usb_find: Found a match.\n"); libusb_ref_device(device->device); if (device->read_endp != -1) device->read_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device->read_endp].bEndpointAddress; if (device->write_endp != -1) device->write_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device->write_endp].bEndpointAddress; goto match_found; } libusb_close(device->handle); device->handle = NULL; } } } } // iface loop libusb_free_config_descriptor(confptr); } // conf loop } match_found: _PAPPL_DEBUG("pappl_usb_find: device->handle=%p\n", device->handle); // Clean up .... if (num_udevs >= 0) libusb_free_device_list(udevs, 1); return (device->handle != NULL); } // // 'pappl_usb_getid()' - Get the current IEEE-1284 device ID. // static char * // O - Device ID or `NULL` on error pappl_usb_getid( pappl_device_t *device, // I - Device char *buffer, // I - Buffer size_t bufsize) // I - Size of buffer { _pappl_usb_dev_t *usb = (_pappl_usb_dev_t *)papplDeviceGetData(device); // USB device data size_t length; // Length of device ID int error; // USB transfer error _PAPPL_DEBUG("pappl_usb_getid(device=%p, buffer=%p, bufsize=%ld) usb->conf=%d, ->iface=%d, ->altset=%d\n", device, buffer, (long)bufsize, usb->conf, usb->iface, usb->altset); // Get the 1284 Device ID... if ((error = libusb_control_transfer(usb->handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE, 0, (uint16_t)usb->conf, (uint16_t)((usb->iface << 8) | usb->altset), (unsigned char *)buffer, (uint16_t)bufsize, 5000)) < 0) { papplDeviceError(device, "Unable to get IEEE-1284 device ID from USB port: %s", libusb_strerror((enum libusb_error)error)); buffer[0] = '\0'; return (NULL); } // Nul-terminate length = (size_t)(((buffer[0] & 255) << 8) | (buffer[1] & 255)); if (length < 14 || length > bufsize) // Some printers do it wrong (LSB)... length = (size_t)(((buffer[1] & 255) << 8) | (buffer[0] & 255)); if (length > bufsize) length = bufsize; length -= 2; if (length > 0) { // Copy live value... memmove(buffer, buffer + 2, length); buffer[length] = '\0'; } else { // Use cached value... papplCopyString(buffer, usb->device_id, bufsize); } return (buffer); } // // 'pappl_usb_list()' - List USB devices. // static bool // O - `true` if found, `false` if not pappl_usb_list( pappl_device_cb_t cb, // I - Callback function void *data, // I - User data pointer pappl_deverror_cb_t err_cb, // I - Error callback void *err_data) // I - Error callback data { _pappl_usb_dev_t usb; // USB device bool ret; // Return value ret = pappl_usb_find(cb, data, &usb, err_cb, err_data); if (usb.handle) { libusb_close(usb.handle); libusb_unref_device(usb.device); } return (ret); } // // 'pappl_usb_open()' - Open a USB device. // static bool // `true` on success, `false` on error pappl_usb_open( pappl_device_t *device, // I - Device const char *device_uri, // I - Device URI const char *job_name) // I - Job name (unused) { _pappl_usb_dev_t *usb; // USB device (void)job_name; if ((usb = (_pappl_usb_dev_t *)calloc(1, sizeof(_pappl_usb_dev_t))) == NULL) { papplDeviceError(device, "Unable to allocate memory for USB device: %s", strerror(errno)); return (false); } if (!pappl_usb_find(pappl_usb_open_cb, (void *)device_uri, usb, device->error_cb, device->error_data)) { free(usb); return (false); } papplDeviceSetData(device, usb); return (true); } // // 'pappl_usb_open_cb()' - Look for a matching device URI. // static bool // O - `true` on match, `false` otherwise pappl_usb_open_cb( const char *device_info, // I - Description of device const char *device_uri, // I - This device's URI const char *device_id, // I - IEEE-1284 Device ID void *data) // I - URI we are looking for { bool match = !strcmp(device_uri, (const char *)data); // Does this match? (void)device_info; (void)device_id; _PAPPL_DEBUG("pappl_usb_open_cb(device_info=\"%s\", device_uri=\"%s\", device_id=\"%s\", user_data=\"%s\") returning %s.\n", device_info, device_uri, device_id, (char *)data, match ? "true" : "false"); return (match); } // // 'pappl_usb_read()' - Read data from a USB device. // static ssize_t // O - Bytes read pappl_usb_read(pappl_device_t *device, // I - Device void *buffer, // I - Read buffer size_t bytes) // I - Bytes to read { _pappl_usb_dev_t *usb = (_pappl_usb_dev_t *)papplDeviceGetData(device); // USB device data int icount; // Bytes that were read int error; // USB transfer error if (usb->read_endp < 0) return (-1); // No read endpoint! if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->read_endp, buffer, (int)bytes, &icount, 10000)) < 0) { papplDeviceError(device, "Unable to read from USB port: %s", libusb_strerror((enum libusb_error)error)); return (-1); } else return ((ssize_t)icount); } // // 'pappl_usb_status()' - Get the USB printer status. // static pappl_preason_t // O - IPP "printer-state-reasons" values pappl_usb_status(pappl_device_t *device)// I - Device { _pappl_usb_dev_t *usb = (_pappl_usb_dev_t *)papplDeviceGetData(device); // USB device data pappl_preason_t status = PAPPL_PREASON_NONE; // IPP "printer-state-reasons" values unsigned char port_status = 0x08; // Centronics port status byte int error; // USB transfer error if ((error = libusb_control_transfer(usb->handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE, 1, 0, (uint16_t)(usb->iface << 8), &port_status, 1, 0)) < 0) { papplDeviceError(device, "Unable to get USB port status: %s", libusb_strerror((enum libusb_error)error)); } else { if (!(port_status & 0x08)) status |= PAPPL_PREASON_OTHER; if (port_status & 0x20) status |= PAPPL_PREASON_MEDIA_EMPTY; if (port_status & 0x40) // Vendor extension status |= PAPPL_PREASON_MEDIA_JAM; if (port_status & 0x80) // Vendor extension status |= PAPPL_PREASON_COVER_OPEN; } return (status); } // // 'pappl_usb_write()' - Write data to a USB device. // static ssize_t // O - Bytes written pappl_usb_write(pappl_device_t *device, // I - Device const void *buffer, // I - Write buffer size_t bytes) // I - Bytes to write { _pappl_usb_dev_t *usb = (_pappl_usb_dev_t *)papplDeviceGetData(device); // USB device data int icount; // Bytes that were written int error; // USB transfer error if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->write_endp, (unsigned char *)buffer, (int)bytes, &icount, 0)) < 0) { papplDeviceError(device, "Unable to write %d bytes to USB port: %s", (int)bytes, libusb_strerror((enum libusb_error)error)); return (-1); } else return ((ssize_t)icount); } #endif // HAVE_LIBUSB pappl-1.4.9/pappl/device.c000066400000000000000000001047151476704353100154020ustar00rootroot00000000000000// // Common device support code for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "device-private.h" #include "printer.h" #include // // Types... // typedef struct _pappl_devscheme_s // Device scheme data { char *scheme; // URI scheme pappl_devtype_t dtype; // Device type pappl_devlist_cb_t list_cb; // List devices callback, if any pappl_devopen_cb_t open_cb; // Open callback pappl_devclose_cb_t close_cb; // Close callback pappl_devread_cb_t read_cb; // Read callback pappl_devwrite_cb_t write_cb; // Write callback pappl_devid_cb_t id_cb; // IEEE-1284 device ID callback, if any pappl_devstatus_cb_t status_cb; // Status callback, if any pappl_devsupplies_cb_t supplies_cb; // Supplies callback, if any } _pappl_devscheme_t; // // Local globals... // static pthread_rwlock_t device_rwlock = PTHREAD_RWLOCK_INITIALIZER; // Reader/writer lock for device schemes static cups_array_t *device_schemes = NULL; // Array of device schemes // // Local functions... // static int pappl_compare_schemes(_pappl_devscheme_t *a, _pappl_devscheme_t *b); static void pappl_create_schemes_no_lock(void); static void pappl_default_error_cb(const char *message, void *data); static void pappl_free_dinfo(_pappl_dinfo_t *d); static ssize_t pappl_write(pappl_device_t *device, const void *buffer, size_t bytes); // // '_papplDeviceAddSchemeNoLock()' - Add a device URI scheme with supply-level queries. // // This function registers a device URI scheme with PAPPL, so that devices using // the named scheme can receive print data, report status information, and so // forth. PAPPL includes support for the following URI schemes: // // - `dnssd`: Network printers discovered using DNS-SD. // - `file`: Character device files, plain files, and directories. // - `snmp`: Network printers discovered using SNMPv1. // - `socket`: Network printers using a hostname or numeric IP address. // - `usb`: Class 1 (unidirectional) or 2 (bidirectional) USB printers. // // The "scheme" parameter specifies the URI scheme and must consist of lowercase // letters, digits, "-", "_", and/or ".", for example "x-foo" or // "com.example.bar". // // The "dtype" parameter specifies the device type and should be // `PAPPL_DTYPE_CUSTOM_LOCAL` for locally connected printers and // `PAPPL_DTYPE_CUSTOM_NETWORK` for network printers. // // Each of the callbacks corresponds to one of the `papplDevice` functions: // // - "list_cb": Implements discovery of devices (optional) // - "open_cb": Opens communication with a device and allocates any device- // specific data as needed // - "close_cb": Closes communication with a device and frees any device- // specific data as needed // - "read_cb": Reads data from a device // - "write_cb": Write data to a device // - "status_cb": Gets basic printer state information from a device (optional) // - "supplies_cb": Gets supply level information from a device (optional) // - "id_cb": Gets the current IEEE-1284 device ID from a device (optional) // // The "open_cb" callback typically calls @link papplDeviceSetData@ to store a // pointer to contextual information for the connection while the "close_cb", // "id_cb", "read_cb", "write_cb", "status_cb", and "supplies_cb" callbacks // typically call @link papplDeviceGetData@ to retrieve it. // void _papplDeviceAddSchemeNoLock( const char *scheme, // I - URI scheme pappl_devtype_t dtype, // I - Device type (`PAPPL_DEVTYPE_CUSTOM_LOCAL` or `PAPPL_DEVTYPE_CUSTOM_NETWORK`) pappl_devlist_cb_t list_cb, // I - List devices callback, if any pappl_devopen_cb_t open_cb, // I - Open callback pappl_devclose_cb_t close_cb, // I - Close callback pappl_devread_cb_t read_cb, // I - Read callback pappl_devwrite_cb_t write_cb, // I - Write callback pappl_devstatus_cb_t status_cb, // I - Status callback, if any pappl_devsupplies_cb_t supplies_cb, // I - Supply level callback, if any pappl_devid_cb_t id_cb) // I - IEEE-1284 device ID callback, if any { _pappl_devscheme_t *ds, // Device URI scheme data dkey; // Search key // Create the schemes array as needed... if (!device_schemes) { if ((device_schemes = cupsArrayNew((cups_array_cb_t)pappl_compare_schemes, NULL, NULL, 0, NULL, NULL)) == NULL) return; } dkey.scheme = (char *)scheme; if ((ds = (_pappl_devscheme_t *)cupsArrayFind(device_schemes, &dkey)) == NULL) { // Add the scheme... if ((ds = (_pappl_devscheme_t *)calloc(1, sizeof(_pappl_devscheme_t))) == NULL) return; if ((ds->scheme = strdup(scheme)) == NULL) { free(ds); return; } cupsArrayAdd(device_schemes, ds); } ds->dtype = dtype; ds->list_cb = list_cb; ds->open_cb = open_cb; ds->close_cb = close_cb; ds->read_cb = read_cb; ds->write_cb = write_cb; ds->status_cb = status_cb; ds->supplies_cb = supplies_cb; ds->id_cb = id_cb; } // // 'papplDeviceAddScheme()' - Add a device URI scheme. // // This function registers a device URI scheme with PAPPL, so that devices using // the named scheme can receive print data, report status information, and so // forth. PAPPL includes support for the following URI schemes: // // - `dnssd`: Network printers discovered using DNS-SD. // - `file`: Character device files, plain files, and directories. // - `snmp`: Network printers discovered using SNMPv1. // - `socket`: Network printers using a hostname or numeric IP address. // - `usb`: Class 1 (unidirectional) or 2 (bidirectional) USB printers. // // The "scheme" parameter specifies the URI scheme and must consist of lowercase // letters, digits, "-", "_", and/or ".", for example "x-foo" or // "com.example.bar". // // The "dtype" parameter specifies the device type and should be // `PAPPL_DTYPE_CUSTOM_LOCAL` for locally connected printers and // `PAPPL_DTYPE_CUSTOM_NETWORK` for network printers. // // Each of the callbacks corresponds to one of the `papplDevice` functions: // // - "list_cb": Implements discovery of devices (optional) // - "open_cb": Opens communication with a device and allocates any device- // specific data as needed // - "close_cb": Closes communication with a device and frees any device- // specific data as needed // - "read_cb": Reads data from a device // - "write_cb": Write data to a device // - "status_cb": Gets basic printer state information from a device (optional) // - "id_cb": Gets the current IEEE-1284 device ID from a device (optional) // // The "open_cb" callback typically calls @link papplDeviceSetData@ to store a // pointer to contextual information for the connection while the "close_cb", // "id_cb", "read_cb", "write_cb", and "status_cb" callbacks typically call // @link papplDeviceGetData@ to retrieve it. // void papplDeviceAddScheme( const char *scheme, // I - URI scheme pappl_devtype_t dtype, // I - Device type (`PAPPL_DEVTYPE_CUSTOM_LOCAL` or `PAPPL_DEVTYPE_CUSTOM_NETWORK`) pappl_devlist_cb_t list_cb, // I - List devices callback, if any pappl_devopen_cb_t open_cb, // I - Open callback pappl_devclose_cb_t close_cb, // I - Close callback pappl_devread_cb_t read_cb, // I - Read callback pappl_devwrite_cb_t write_cb, // I - Write callback pappl_devstatus_cb_t status_cb, // I - Status callback, if any pappl_devid_cb_t id_cb) // I - IEEE-1284 device ID callback, if any { papplDeviceAddScheme2(scheme, dtype, list_cb, open_cb, close_cb, read_cb, write_cb, status_cb, /*supplies_cb*/NULL, id_cb); } // // 'papplDeviceAddScheme2()' - Add a device URI scheme with supply-level queries. // // This function registers a device URI scheme with PAPPL, so that devices using // the named scheme can receive print data, report status information, and so // forth. PAPPL includes support for the following URI schemes: // // - `dnssd`: Network printers discovered using DNS-SD. // - `file`: Character device files, plain files, and directories. // - `snmp`: Network printers discovered using SNMPv1. // - `socket`: Network printers using a hostname or numeric IP address. // - `usb`: Class 1 (unidirectional) or 2 (bidirectional) USB printers. // // The "scheme" parameter specifies the URI scheme and must consist of lowercase // letters, digits, "-", "_", and/or ".", for example "x-foo" or // "com.example.bar". // // The "dtype" parameter specifies the device type and should be // `PAPPL_DTYPE_CUSTOM_LOCAL` for locally connected printers and // `PAPPL_DTYPE_CUSTOM_NETWORK` for network printers. // // Each of the callbacks corresponds to one of the `papplDevice` functions: // // - "list_cb": Implements discovery of devices (optional) // - "open_cb": Opens communication with a device and allocates any device- // specific data as needed // - "close_cb": Closes communication with a device and frees any device- // specific data as needed // - "read_cb": Reads data from a device // - "write_cb": Write data to a device // - "status_cb": Gets basic printer state information from a device (optional) // - "supplies_cb": Gets supply level information from a device (optional) // - "id_cb": Gets the current IEEE-1284 device ID from a device (optional) // // The "open_cb" callback typically calls @link papplDeviceSetData@ to store a // pointer to contextual information for the connection while the "close_cb", // "id_cb", "read_cb", "write_cb", "status_cb", and "supplies_cb" callbacks // typically call @link papplDeviceGetData@ to retrieve it. // void papplDeviceAddScheme2( const char *scheme, // I - URI scheme pappl_devtype_t dtype, // I - Device type (`PAPPL_DEVTYPE_CUSTOM_LOCAL` or `PAPPL_DEVTYPE_CUSTOM_NETWORK`) pappl_devlist_cb_t list_cb, // I - List devices callback, if any pappl_devopen_cb_t open_cb, // I - Open callback pappl_devclose_cb_t close_cb, // I - Close callback pappl_devread_cb_t read_cb, // I - Read callback pappl_devwrite_cb_t write_cb, // I - Write callback pappl_devstatus_cb_t status_cb, // I - Status callback, if any pappl_devsupplies_cb_t supplies_cb, // I - Supply level callback, if any pappl_devid_cb_t id_cb) // I - IEEE-1284 device ID callback, if any { pthread_rwlock_wrlock(&device_rwlock); // Create the schemes array as needed... if (!device_schemes) pappl_create_schemes_no_lock(); _papplDeviceAddSchemeNoLock(scheme, dtype, list_cb, open_cb, close_cb, read_cb, write_cb, status_cb, supplies_cb, id_cb); pthread_rwlock_unlock(&device_rwlock); } // // '_papplDeviceAddSupportedSchemes()' - Add the available URI schemes. // void _papplDeviceAddSupportedSchemes( ipp_t *attrs) // I - Attributes { cups_len_t i; // Looping var ipp_attribute_t *attr; // IPP attribute _pappl_devscheme_t *devscheme; // Current device scheme pthread_rwlock_rdlock(&device_rwlock); if (!device_schemes) pappl_create_schemes_no_lock(); attr = ippAddStrings(attrs, IPP_TAG_SYSTEM, IPP_TAG_URISCHEME, "smi55357-device-uri-schemes-supported", IPP_NUM_CAST cupsArrayGetCount(device_schemes), NULL, NULL); for (i = 0, devscheme = (_pappl_devscheme_t *)cupsArrayGetFirst(device_schemes); devscheme; i ++, devscheme = (_pappl_devscheme_t *)cupsArrayGetNext(device_schemes)) ippSetString(attrs, &attr, i, devscheme->scheme); pthread_rwlock_unlock(&device_rwlock); } // // 'papplDeviceClose()' - Close a device connection. // // This function flushes any pending write data and closes the connection to a // device. // void papplDeviceClose( pappl_device_t *device) // I - Device to close { if (device) { if (device->bufused > 0) pappl_write(device, device->buffer, device->bufused); (device->close_cb)(device); free(device); } } // // '_papplDeviceError()' - Report an error. // void _papplDeviceError( pappl_deverror_cb_t err_cb, // I - Error callback void *err_data, // I - Error callback data const char *message, // I - Printf-style message ...) // I - Additional args as needed { va_list ap; // Pointer to additional args char buffer[8192]; // Formatted message if (!err_cb) return; va_start(ap, message); vsnprintf(buffer, sizeof(buffer), message, ap); va_end(ap); (*err_cb)(buffer, err_data); } // // 'papplDeviceError()' - Report an error on a device. // // This function reports an error on a device using the client-supplied callback // function. It is normally called from any custom device URI scheme callbacks // you implement. // void papplDeviceError( pappl_device_t *device, // I - Device const char *message, // I - Printf-style error message ...) // I - Additional arguments as needed { va_list ap; // Pointer to additional args char buffer[8192]; // Formatted message if (!device || !device->error_cb) return; va_start(ap, message); vsnprintf(buffer, sizeof(buffer), message, ap); va_end(ap); (device->error_cb)(buffer, device->error_data); } // // 'papplDeviceFlush()' - Flush any buffered data to the device. // // This function flushes any pending write data sent using the // @link papplDevicePrintf@, @link papplDevicePuts@, or @link papplDeviceWrite@ // functions to the device. // void papplDeviceFlush(pappl_device_t *device)// I - Device { if (device && device->bufused > 0) { pappl_write(device, device->buffer, device->bufused); device->bufused = 0; } } // // 'papplDeviceGetData()' - Get device-specific data. // // This function returns any device-specific data that has been set by the // device open callback. It is normally only called from any custom device URI // scheme callbacks you implement. // void * // O - Device data pointer papplDeviceGetData( pappl_device_t *device) // I - Device { return (device ? device->device_data : NULL); } // // 'papplDeviceGetID()' - Get the IEEE-1284 device ID. // // This function queries the IEEE-1284 device ID from the device and copies it // to the provided buffer. The buffer must be at least 64 bytes and should be // at least 1024 bytes in length. // // > *Note:* This function can block for up to several seconds depending on // > the type of connection. // char * // O - IEEE-1284 device ID or `NULL` on failure papplDeviceGetID( pappl_device_t *device, // I - Device char *buffer, // I - Buffer for IEEE-1284 device ID size_t bufsize) // I - Size of buffer { struct timeval starttime, // Start time endtime; // End time char *ret; // Return value // Range check input... if (buffer) *buffer = '\0'; if (!device || !device->id_cb || !buffer || bufsize < 64) return (NULL); // Get the device ID and collect timing metrics... gettimeofday(&starttime, NULL); ret = (device->id_cb)(device, buffer, bufsize); gettimeofday(&endtime, NULL); device->metrics.status_requests ++; device->metrics.status_msecs += (size_t)(1000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec) / 1000); // Return the device ID return (ret); } // // 'papplDeviceGetMetrics()' - Get the device metrics. // // This function returns a copy of the device metrics data, which includes the // number, length (in bytes), and duration (in milliseconds) of read, status, // and write requests for the current session. This information is normally // used for performance measurement and optimization during development of a // printer application. It can also be useful diagnostic information. // pappl_devmetrics_t * // O - Metrics data papplDeviceGetMetrics( pappl_device_t *device, // I - Device pappl_devmetrics_t *metrics) // I - Buffer for metrics data { if (device && metrics) memcpy(metrics, &device->metrics, sizeof(pappl_devmetrics_t)); else if (metrics) memset(metrics, 0, sizeof(pappl_devmetrics_t)); return (metrics); } // // 'papplDeviceGetDeviceStatus()' - Get the printer status bits. // // This function returns the current printer status bits, as applicable to the // current device. // // The status bits for USB devices come from the original Centronics parallel // printer "standard" which was later formally standardized in IEEE 1284-1984 // and the USB Device Class Definition for Printing Devices. Some vendor // extensions are also supported. // // The status bits for network devices come from the hrPrinterDetectedErrorState // property that is defined in the SNMP Printer MIB v2 (RFC 3805). // // This function returns a @link pappl_preason_t@ bitfield which can be // passed to the @link papplPrinterSetReasons@ function. Use the // @link PAPPL_PREASON_DEVICE_STATUS@ value as the value of the "remove" // argument. // // > Note: This function can block for several seconds while getting the status // > information. // pappl_preason_t // O - IPP "printer-state-reasons" values papplDeviceGetStatus( pappl_device_t *device) // I - Device { struct timeval starttime, // Start time endtime; // End time pappl_preason_t status = PAPPL_PREASON_NONE; // IPP "printer-state-reasons" values if (device) { gettimeofday(&starttime, NULL); if (device->status_cb) status = (device->status_cb)(device); gettimeofday(&endtime, NULL); device->metrics.status_requests ++; device->metrics.status_msecs += (size_t)(1000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec) / 1000); } return (status); } // // 'papplDeviceGetSupplies()' - Get the current printer supplies. // // This function returns the number, type, and level of current printer supply // levels, as applicable to the current device. // // The supply levels for network devices come from the prtSupplyTable and // prtMarkerColorantTable properties that are defined in the SNMP Printer MIB // v2 (RFC 3805). // // The supply levels for other devices are not standardized and must be queried // using other methods. // // > Note: This function can block for several seconds while getting the supply // > information. // int // O - Number of supplies papplDeviceGetSupplies( pappl_device_t *device, // I - Device int max_supplies, // I - Maximum supplies pappl_supply_t *supplies) // I - Supplies { if (device && device->supplies_cb) return ((device->supplies_cb)(device, max_supplies, supplies)); else return (0); } // // '_papplDeviceInfoCallback()' - Add device information to the array. // bool // O - `true` to continue, `false` to stop _papplDeviceInfoCallback( const char *device_info, // I - Device info const char *device_uri, // I - Device URI const char *device_id, // I - Device ID cups_array_t *devices) // I - Callback data (devices array) { _pappl_dinfo_t *d; // Found device data // Allocate a found device... if ((d = malloc(sizeof(_pappl_dinfo_t))) != NULL) { // Make copies of the strings... d->device_info = strdup(device_info); d->device_uri = strdup(device_uri); d->device_id = strdup(device_id ? device_id : ""); if (d->device_info && d->device_uri && d->device_id) { // Add to device array cupsArrayAdd(devices, d); } else { // Free what got copied... free(d->device_info); free(d->device_uri); free(d->device_id); free(d); } } return (false); } // // '_papplDeviceInfoCreateArray()' - Create an array for device information. // cups_array_t * // O - Device info array _papplDeviceInfoCreateArray(void) { return (cupsArrayNew(/*compare_cb*/NULL, /*cb_data*/NULL, /*hash_cb*/NULL, /*hash_size*/0, /*copy_cb*/NULL, (cups_afree_cb_t)pappl_free_dinfo)); } // // 'papplDeviceIsSupported()' - Determine whether a given URI is supported. // // This function determines whether a given URI or URI scheme is supported as // a device. // bool // O - `true` if supported, `false` otherwise papplDeviceIsSupported( const char *uri) // I - URI { char scheme[32], // Device scheme userpass[32], // Device user/pass host[256], // Device host resource[256]; // Device resource int port; // Device port _pappl_devscheme_t key, // Device search key *match; // Matching key // Separate out the components of the URI... if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) return (false); // Files are OK if the resource path is writable... if (!strcmp(scheme, "file")) { char *options = strchr(resource, '?'); // Device options, if any if (options) *options = '\0'; // Strip options before writability test return (!access(resource, W_OK)); } // Make sure schemes are added... pthread_rwlock_rdlock(&device_rwlock); if (!device_schemes) { pthread_rwlock_unlock(&device_rwlock); pthread_rwlock_wrlock(&device_rwlock); if (!device_schemes) pappl_create_schemes_no_lock(); } // Otherwise try to lookup the URI scheme... key.scheme = scheme; match = (_pappl_devscheme_t *)cupsArrayFind(device_schemes, &key); pthread_rwlock_unlock(&device_rwlock); return (match != NULL); } // // 'papplDeviceList()' - List available devices. // // This function lists the available devices, calling the "cb" function once per // device that is discovered/listed. The callback function receives the device // URI, IEEE-1284 device ID (if any), and "data" pointer, and returns `true` to // stop listing devices and `false` to continue. // // The "types" argument determines which devices are listed, for example // `PAPPL_DEVTYPE_ALL` will list all types of devices while `PAPPL_DEVTYPE_USB` only // lists USB printers. // // Any errors are reported using the supplied "err_cb" function. If you specify // `NULL` for this argument, errors are sent to `stderr`. // // > Note: This function will block (not return) until each of the device URI // > schemes has reported all of the devices *or* the supplied callback function // > returns `true`. // bool // O - `true` if the callback returned `true`, `false` otherwise papplDeviceList( pappl_devtype_t types, // I - Device types pappl_device_cb_t cb, // I - Callback function void *data, // I - User data for callback pappl_deverror_cb_t err_cb, // I - Error callback or `NULL` for default void *err_data) // I - Data for error callback { bool ret = false; // Return value _pappl_devscheme_t *ds; // Current device scheme pthread_rwlock_rdlock(&device_rwlock); if (!device_schemes) { pthread_rwlock_unlock(&device_rwlock); pthread_rwlock_wrlock(&device_rwlock); if (!device_schemes) pappl_create_schemes_no_lock(); } if (!err_cb) err_cb = pappl_default_error_cb; for (ds = (_pappl_devscheme_t *)cupsArrayGetFirst(device_schemes); ds && !ret; ds = (_pappl_devscheme_t *)cupsArrayGetNext(device_schemes)) { if ((types & ds->dtype) && ds->list_cb) ret = (ds->list_cb)(cb, data, err_cb, err_data); } pthread_rwlock_unlock(&device_rwlock); return (ret); } // // 'papplDeviceOpen()' - Open a connection to a device. // // This function opens a connection to the specified device URI. The "name" // argument provides textual context for the connection and is usually the name // (title) of the print job. // // Any errors are reported using the supplied "err_cb" function. If you specify // `NULL` for this argument, errors are sent to `stderr`. // pappl_device_t * // O - Device connection or `NULL` on error papplDeviceOpen( const char *device_uri, // I - Device URI const char *name, // I - Job name pappl_deverror_cb_t err_cb, // I - Error callback or `NULL` for default void *err_data) // I - Data for error callback { _pappl_devscheme_t *ds, // Scheme dkey; // Search key pappl_device_t *device; // Device structure char scheme[32], // URI scheme userpass[32], // Username/password (not used) host[256], // Host name or make resource[256], // Resource path, if any *options; // Pointer to options, if any int port; // Port number http_uri_status_t status; // URI status if (!device_uri) { _papplDeviceError(err_cb, err_data, "Bad NULL device URI."); return (NULL); } if ((status = httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource))) < HTTP_URI_STATUS_OK) { _papplDeviceError(err_cb, err_data, "Bad device URI '%s': %s", device_uri, httpURIStatusString(status)); return (NULL); } if ((options = strchr(resource, '?')) != NULL) *options++ = '\0'; pthread_rwlock_rdlock(&device_rwlock); if (!device_schemes) { pthread_rwlock_unlock(&device_rwlock); pthread_rwlock_wrlock(&device_rwlock); if (!device_schemes) pappl_create_schemes_no_lock(); } dkey.scheme = scheme; ds = (_pappl_devscheme_t *)cupsArrayFind(device_schemes, &dkey); pthread_rwlock_unlock(&device_rwlock); if (!ds) { _papplDeviceError(err_cb, err_data, "Unsupported device URI scheme '%s'.", scheme); return (NULL); } if ((device = calloc(1, sizeof(pappl_device_t))) == NULL) { _papplDeviceError(err_cb, err_data, "Unable to allocate memory for device: %s", strerror(errno)); return (NULL); } device->close_cb = ds->close_cb; device->error_cb = err_cb ? err_cb : pappl_default_error_cb; device->error_data = err_data; device->id_cb = ds->id_cb; device->read_cb = ds->read_cb; device->status_cb = ds->status_cb; device->supplies_cb = ds->supplies_cb; device->write_cb = ds->write_cb; if (!(ds->open_cb)(device, device_uri, name)) { free(device); return (NULL); } return (device); } // // 'papplDeviceParseID()' - Parse an IEEE-1284 device ID string. // // This function parses an IEEE-1284 device ID string and returns an array of // key/value pairs as a `cups_option_t` array. The returned array must be // freed using the `cupsFreeOptions` function. // int // O - Number of key/value pairs papplDeviceParseID( const char *device_id, // I - IEEE-1284 device ID string cups_option_t **pairs) // O - Key/value pairs { cups_len_t num_pairs = 0; // Number of key/value pairs char name[256], // Key name value[256], // Value *ptr; // Pointer into key/value // Range check input... if (pairs) *pairs = NULL; if (!device_id || !pairs) return (0); // Scan the IEEE-1284 device ID string... while (*device_id) { // Skip leading whitespace... while (*device_id && isspace(*device_id)) device_id ++; if (!*device_id) break; // Get the key name... for (ptr = name; *device_id && *device_id != ':'; device_id ++) { if (ptr < (name + sizeof(name) - 1)) *ptr++ = *device_id; } *ptr = '\0'; if (*device_id != ':') break; device_id ++; // Skip leading whitespace in value... while (*device_id && isspace(*device_id)) device_id ++; for (ptr = value; *device_id && *device_id != ';'; device_id ++) { if (ptr < (value + sizeof(value) - 1)) *ptr++ = *device_id; } *ptr = '\0'; if (*device_id == ';') device_id ++; num_pairs = cupsAddOption(name, value, num_pairs, pairs); } return ((int)num_pairs); } // // 'papplDevicePrintf()' - Write a formatted string. // // This function buffers a formatted string that will be sent to the device. // The "format" argument accepts all `printf` format specifiers and behaves // identically to that function. // // Call the @link papplDeviceFlush@ function to ensure that the formatted string // is immediately sent to the device. // ssize_t // O - Number of characters or -1 on error papplDevicePrintf( pappl_device_t *device, // I - Device const char *format, // I - Printf-style format string ...) // I - Additional args as needed { va_list ap; // Pointer to additional args char buffer[8192]; // Output buffer int bytes; // Bytes to write va_start(ap, format); bytes = vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); if (bytes > 0) return (papplDeviceWrite(device, buffer, (size_t)bytes)); else return ((ssize_t)bytes); } // // 'papplDevicePuts()' - Write a literal string. // // This function buffers a literal string that will be sent to the device. // Call the @link papplDeviceFlush@ function to ensure that the literal string // is immediately sent to the device. // ssize_t // O - Number of characters or -1 on error papplDevicePuts( pappl_device_t *device, // I - Device const char *s) // I - Literal string { return (papplDeviceWrite(device, s, strlen(s))); } // // 'papplDeviceRead()' - Read from a device. // // This function reads data from the device. Depending on the device, this // function may block indefinitely. // ssize_t // O - Number of bytes read or -1 on error papplDeviceRead( pappl_device_t *device, // I - Device void *buffer, // I - Read buffer size_t bytes) // I - Max bytes to read { struct timeval starttime, // Start time endtime; // End time ssize_t count; // Bytes read this time if (!device || !device->read_cb) return (-1); // Make sure any pending IO is flushed... if (device->bufused > 0) papplDeviceFlush(device); gettimeofday(&starttime, NULL); count = (device->read_cb)(device, buffer, bytes); gettimeofday(&endtime, NULL); device->metrics.read_requests ++; device->metrics.read_msecs += (size_t)(1000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec) / 1000); if (count > 0) device->metrics.read_bytes += (size_t)count; return (count); } // // 'papplDeviceRemoveScheme()' - Remove the named device URI scheme. // // This function removes support for the named device URI scheme. Use only // when you want to disable a URI scheme for security or functional reasons, // for example to disable the "file" URI scheme. // void papplDeviceRemoveScheme( const char *scheme) // I - Device URI scheme to remove { _pappl_devscheme_t *ds, // Device URI scheme data dkey; // Search key pthread_rwlock_wrlock(&device_rwlock); // Create the schemes array as needed... if (!device_schemes) pappl_create_schemes_no_lock(); // See if the scheme is added... dkey.scheme = (char *)scheme; if ((ds = (_pappl_devscheme_t *)cupsArrayFind(device_schemes, &dkey)) != NULL) { // Found it, now remove and free it... cupsArrayRemove(device_schemes, ds); free(ds->scheme); free(ds); } pthread_rwlock_unlock(&device_rwlock); } // // 'papplDeviceRemoveTypes()' - Remove device URI schemes of the specified types. // // This function removes device URI schemes of the specified types. Use only // when you want to disable URI schemes for security or functional reasons, // for example to disable all network URI schemes. // void papplDeviceRemoveTypes( pappl_devtype_t types) // I - Device types to remove { _pappl_devscheme_t *ds; // Device URI scheme data pthread_rwlock_wrlock(&device_rwlock); // Create the schemes array as needed... if (!device_schemes) pappl_create_schemes_no_lock(); // Find schemes that match the types... for (ds = (_pappl_devscheme_t *)cupsArrayGetFirst(device_schemes); ds; ds = (_pappl_devscheme_t *)cupsArrayGetNext(device_schemes)) { if (ds->dtype & types) { // Matching type, remove and free it... cupsArrayRemove(device_schemes, ds); free(ds->scheme); free(ds); } } pthread_rwlock_unlock(&device_rwlock); } // // 'papplDeviceSetData()' - Set device-specific data. // // This function sets any device-specific data needed to communicate with the // device. It is normally only called from the open callback that was // registered for the device URI scheme. // void papplDeviceSetData( pappl_device_t *device, // I - Device void *data) // I - Device data pointer { if (device) device->device_data = data; } // // 'papplDeviceWrite()' - Write to a device. // // This function buffers data that will be sent to the device. Call the // @link papplDeviceFlush@ function to ensure that the data is immediately sent // to the device. // ssize_t // O - Number of bytes written or -1 on error papplDeviceWrite( pappl_device_t *device, // I - Device const void *buffer, // I - Write buffer size_t bytes) // I - Number of bytes to write { if (!device) return (-1); if ((device->bufused + bytes) > sizeof(device->buffer)) { // Flush the write buffer... if (pappl_write(device, device->buffer, device->bufused) < 0) return (-1); device->bufused = 0; } if (bytes < sizeof(device->buffer)) { memcpy(device->buffer + device->bufused, buffer, bytes); device->bufused += bytes; return ((ssize_t)bytes); } return (pappl_write(device, buffer, bytes)); } // // 'pappl_compare_schemes()' - Compare two device URI schemes. // static int // O - Result of comparison pappl_compare_schemes( _pappl_devscheme_t *a, // I - First URI scheme _pappl_devscheme_t *b) // I - Second URI scheme { return (strcmp(a->scheme, b->scheme)); } // // 'pappl_create_schemes_no_lock()' - Create the default device URI schemes. // static void pappl_create_schemes_no_lock(void) { _papplDeviceAddFileSchemeNoLock(); _papplDeviceAddNetworkSchemesNoLock(); _papplDeviceAddUSBSchemeNoLock(); } // // 'pappl_default_error_cb()' - Send device errors to stderr. // static void pappl_default_error_cb( const char *message, // I - Error message void *data) // I - Callback data (unused) { (void)data; fprintf(stderr, "%s\n", message); } // // 'pappl_free_dinfo()' - Free device information. // static void pappl_free_dinfo(_pappl_dinfo_t *d) // I - Device info { free(d->device_info); free(d->device_uri); free(d->device_id); free(d); } // // 'pappl_write()' - Write data to the device. // static ssize_t // O - Number of bytes written or `-1` on error pappl_write(pappl_device_t *device, // I - Device const void *buffer, // I - Buffer size_t bytes) // I - Bytes to write { struct timeval starttime, // Start time endtime; // End time ssize_t count; // Total bytes written gettimeofday(&starttime, NULL); count = (device->write_cb)(device, buffer, bytes); gettimeofday(&endtime, NULL); device->metrics.write_requests ++; device->metrics.write_msecs += (size_t)(1000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec) / 1000); if (count > 0) device->metrics.write_bytes += (size_t)count; return (count); } pappl-1.4.9/pappl/device.h000066400000000000000000000130111476704353100153730ustar00rootroot00000000000000// // Device communication functions for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_DEVICE_H_ # define _PAPPL_DEVICE_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Types... // typedef struct pappl_devmetrics_s // Device metrics { size_t read_bytes; // Total number of bytes read size_t read_requests; // Total number of read requests size_t read_msecs; // Total number of milliseconds spent reading size_t status_requests; // Total number of status requests size_t status_msecs; // Total number of milliseconds spent getting status size_t write_bytes; // Total number of bytes written size_t write_requests; // Total number of write requests size_t write_msecs; // Total number of milliseconds spent writing } pappl_devmetrics_t; enum pappl_devtype_e // Device type bit values { PAPPL_DEVTYPE_FILE = 0x01, // Local file/directory PAPPL_DEVTYPE_USB = 0x02, // USB printers PAPPL_DEVTYPE_SERIAL = 0x04, // Serial printers (not currently implemented) @private@ PAPPL_DEVTYPE_CUSTOM_LOCAL = 0x08, // Local printer using a custom interface or protocol PAPPL_DEVTYPE_SOCKET = 0x10, // Network printers using raw socket PAPPL_DEVTYPE_DNS_SD = 0x20, // Network printers discovered via DNS-SD/mDNS PAPPL_DEVTYPE_SNMP = 0x40, // Network printers discovered via SNMP PAPPL_DEVTYPE_CUSTOM_NETWORK = 0x80, // Network printer using a custom interface or protocol PAPPL_DEVTYPE_LOCAL = 0x0f, // All local printers PAPPL_DEVTYPE_NETWORK = 0xf0, // All network printers PAPPL_DEVTYPE_ALL = 0xff // All printers }; typedef unsigned pappl_devtype_t; // Device type bitfield typedef bool (*pappl_device_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data); // Device callback - return `true` to stop, `false` to continue typedef void (*pappl_devclose_cb_t)(pappl_device_t *device); // Device close callback typedef void (*pappl_deverror_cb_t)(const char *message, void *err_data); // Device error callback typedef char *(*pappl_devid_cb_t)(pappl_device_t *device, char *buffer, size_t bufsize); // Device ID callback typedef bool (*pappl_devlist_cb_t)(pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data); // Device list callback typedef bool (*pappl_devopen_cb_t)(pappl_device_t *device, const char *device_uri, const char *name); // Device open callback typedef ssize_t (*pappl_devread_cb_t)(pappl_device_t *device, void *buffer, size_t bytes); // Device read callback typedef pappl_preason_t (*pappl_devstatus_cb_t)(pappl_device_t *device); // Device status callback typedef int (*pappl_devsupplies_cb_t)(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies); // Device supplies callback typedef ssize_t (*pappl_devwrite_cb_t)(pappl_device_t *device, const void *buffer, size_t bytes); // Device write callback // // Functions... // extern void papplDeviceAddScheme(const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devid_cb_t id_cb) _PAPPL_PUBLIC; extern void papplDeviceAddScheme2(const char *scheme, pappl_devtype_t dtype, pappl_devlist_cb_t list_cb, pappl_devopen_cb_t open_cb, pappl_devclose_cb_t close_cb, pappl_devread_cb_t read_cb, pappl_devwrite_cb_t write_cb, pappl_devstatus_cb_t status_cb, pappl_devsupplies_cb_t supplies_cb, pappl_devid_cb_t id_cb) _PAPPL_PUBLIC; extern void papplDeviceClose(pappl_device_t *device) _PAPPL_PUBLIC; extern void papplDeviceError(pappl_device_t *device, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(2,3); extern void papplDeviceFlush(pappl_device_t *device) _PAPPL_PUBLIC; extern void *papplDeviceGetData(pappl_device_t *device) _PAPPL_PUBLIC; extern char *papplDeviceGetID(pappl_device_t *device, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern pappl_devmetrics_t *papplDeviceGetMetrics(pappl_device_t *device, pappl_devmetrics_t *metrics) _PAPPL_PUBLIC; extern pappl_preason_t papplDeviceGetStatus(pappl_device_t *device) _PAPPL_PUBLIC; extern int papplDeviceGetSupplies(pappl_device_t *device, int max_supplies, pappl_supply_t *supplies) _PAPPL_PUBLIC; extern bool papplDeviceIsSupported(const char *uri) _PAPPL_PUBLIC; extern bool papplDeviceList(pappl_devtype_t types, pappl_device_cb_t cb, void *data, pappl_deverror_cb_t err_cb, void *err_data) _PAPPL_PUBLIC; extern pappl_device_t *papplDeviceOpen(const char *device_uri, const char *name, pappl_deverror_cb_t err_cb, void *err_data) _PAPPL_PUBLIC; extern int papplDeviceParseID(const char *device_id, cups_option_t **pairs) _PAPPL_PUBLIC; extern ssize_t papplDevicePrintf(pappl_device_t *device, const char *format, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(2, 3); extern ssize_t papplDevicePuts(pappl_device_t *device, const char *s) _PAPPL_PUBLIC; extern ssize_t papplDeviceRead(pappl_device_t *device, void *buffer, size_t bytes) _PAPPL_PUBLIC; extern void papplDeviceRemoveScheme(const char *scheme) _PAPPL_PUBLIC; extern void papplDeviceRemoveTypes(pappl_devtype_t types) _PAPPL_PUBLIC; extern void papplDeviceSetData(pappl_device_t *device, void *data) _PAPPL_PUBLIC; extern ssize_t papplDeviceWrite(pappl_device_t *device, const void *buffer, size_t bytes) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_DEVICE_H_ pappl-1.4.9/pappl/dnssd-private.h000066400000000000000000000034641476704353100167320ustar00rootroot00000000000000// // Private DNS-SD header file for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_DNSSD_PRIVATE_H_ # define _PAPPL_DNSSD_PRIVATE_H_ # include "base-private.h" # ifdef HAVE_MDNSRESPONDER # include # elif defined(HAVE_AVAHI) # include # include # include # include # include # include # include # endif // HAVE_MDNSRESPONDER // // Types and structures... // # ifdef HAVE_MDNSRESPONDER typedef DNSServiceRef _pappl_srv_t; // DNS-SD service reference typedef TXTRecordRef _pappl_txt_t; // DNS-SD TXT record typedef DNSServiceRef _pappl_dns_sd_t; // DNS-SD master reference #elif defined(HAVE_AVAHI) typedef AvahiEntryGroup *_pappl_srv_t; // DNS-SD service reference typedef AvahiStringList *_pappl_txt_t; // DNS-SD TXT record typedef AvahiClient *_pappl_dns_sd_t; // DNS-SD master reference #else typedef void *_pappl_srv_t; // DNS-SD service reference typedef void *_pappl_txt_t; // DNS-SD TXT record typedef void *_pappl_dns_sd_t; // DNS-SD master reference #endif // HAVE_MDNSRESPONDER // // Functions... // extern const char *_papplDNSSDCopyHostName(char *buffer, size_t bufsize) _PAPPL_PRIVATE; extern int _papplDNSSDGetHostChanges(void) _PAPPL_PRIVATE; extern _pappl_dns_sd_t _papplDNSSDInit(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplDNSSDLock(void) _PAPPL_PRIVATE; extern const char *_papplDNSSDStrError(int error) _PAPPL_PRIVATE; extern void _papplDNSSDUnlock(void) _PAPPL_PRIVATE; #endif // !_PAPPL_DNSSD_PRIVATE_H_ pappl-1.4.9/pappl/dnssd.c000066400000000000000000001463741476704353100152650ustar00rootroot00000000000000// // DNS-SD support for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Constants... // #ifdef HAVE_AVAHI # define AVAHI_DNS_TYPE_LOC 29 // Per RFC 1876 #endif // HAVE_AVAHI // // Local globals... // static char pappl_dns_sd_hostname[256] = ""; // Current DNS-SD hostname static int pappl_dns_sd_hostname_changes = 0; // Number of host name changes/collisions static pthread_mutex_t pappl_dns_sd_hostname_mutex = PTHREAD_MUTEX_INITIALIZER; // Host name mutex #ifdef HAVE_MDNSRESPONDER static DNSServiceRef pappl_dns_sd_hostname_ref = NULL; // Host name query reference #endif // HAVE_MDNSRESPONDER static _pappl_dns_sd_t pappl_dns_sd_master = NULL; // DNS-SD master reference static pthread_mutex_t pappl_dns_sd_mutex = PTHREAD_MUTEX_INITIALIZER; // DNS-SD master mutex #ifdef HAVE_AVAHI static AvahiThreadedPoll *pappl_dns_sd_poll = NULL; // Avahi background thread #endif // HAVE_AVAHI // // Local functions... // static void dns_sd_geo_to_loc(const char *geo, unsigned char loc[16]); #ifdef HAVE_MDNSRESPONDER static void DNSSD_API dns_sd_hostname_callback(DNSServiceRef ref, DNSServiceFlags flags, uint32_t if_index, DNSServiceErrorType error, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context); static void DNSSD_API dns_sd_printer_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, pappl_printer_t *printer); static void *dns_sd_run(void *data); static void DNSSD_API dns_sd_system_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, pappl_system_t *system); #elif defined(HAVE_AVAHI) static void dns_sd_client_cb(AvahiClient *c, AvahiClientState state, void *data); static void dns_sd_printer_callback(AvahiEntryGroup *p, AvahiEntryGroupState state, pappl_printer_t *printer); static void dns_sd_system_callback(AvahiEntryGroup *p, AvahiEntryGroupState state, pappl_system_t *system); #endif // HAVE_MDNSRESPONDER // // '_papplDNSSDCopyHostName()' - Copy the current DNS-SD hostname. // const char * // O - Current DNS-SD hostname _papplDNSSDCopyHostName(char *buffer, // I - Hostname buffer size_t bufsize) // I - Size of hostname buffer { pthread_mutex_lock(&pappl_dns_sd_hostname_mutex); if (pappl_dns_sd_hostname[0]) papplCopyString(buffer, pappl_dns_sd_hostname, bufsize); else httpGetHostname(NULL, buffer, (cups_len_t)bufsize); pthread_mutex_unlock(&pappl_dns_sd_hostname_mutex); return (buffer); } // // '_papplDNSSDGetHostChanges()' - Get the number of host name changes/collisions so far. // int // O - Number of host name changes/collisions _papplDNSSDGetHostChanges(void) { int changes; // Return value pthread_mutex_lock(&pappl_dns_sd_hostname_mutex); changes = pappl_dns_sd_hostname_changes; pthread_mutex_unlock(&pappl_dns_sd_hostname_mutex); return (changes); } // // '_papplDNSSDInit()' - Initialize DNS-SD services. // _pappl_dns_sd_t // O - DNS-SD master reference _papplDNSSDInit( pappl_system_t *system) // I - System { #ifdef HAVE_MDNSRESPONDER int error; // Error code, if any pthread_t tid; // Thread ID pthread_mutex_lock(&pappl_dns_sd_mutex); if (pappl_dns_sd_master) { pthread_mutex_unlock(&pappl_dns_sd_mutex); return (pappl_dns_sd_master); } if ((error = DNSServiceCreateConnection(&pappl_dns_sd_master)) == kDNSServiceErr_NoError) { // Start a query for the 1.0.0.127 PTR record (localhost) httpGetHostname(NULL, pappl_dns_sd_hostname, sizeof(pappl_dns_sd_hostname)); pappl_dns_sd_hostname_ref = pappl_dns_sd_master; if ((error = DNSServiceQueryRecord(&pappl_dns_sd_hostname_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "1.0.0.127.in-addr.arpa.", kDNSServiceType_PTR, kDNSServiceClass_IN, dns_sd_hostname_callback, NULL)) != kDNSServiceErr_NoError) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to query PTR record for local hostname: %s", _papplDNSSDStrError(error)); pappl_dns_sd_hostname_ref = NULL; } if (pthread_create(&tid, NULL, dns_sd_run, system)) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create DNS-SD thread: %s", strerror(errno)); DNSServiceRefDeallocate(pappl_dns_sd_master); pappl_dns_sd_master = NULL; } else { pthread_detach(tid); } } else { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to initialize DNS-SD: %s", _papplDNSSDStrError(error)); DNSServiceRefDeallocate(pappl_dns_sd_master); pappl_dns_sd_master = NULL; } pthread_mutex_unlock(&pappl_dns_sd_mutex); #elif defined(HAVE_AVAHI) int error; // Error code, if any pthread_mutex_lock(&pappl_dns_sd_mutex); if (pappl_dns_sd_master) { pthread_mutex_unlock(&pappl_dns_sd_mutex); return (pappl_dns_sd_master); } if ((pappl_dns_sd_poll = avahi_threaded_poll_new()) == NULL) { // Unable to create the background thread... papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to initialize DNS-SD thread: %s", strerror(errno)); } else if ((pappl_dns_sd_master = avahi_client_new(avahi_threaded_poll_get(pappl_dns_sd_poll), AVAHI_CLIENT_NO_FAIL, (AvahiClientCallback)dns_sd_client_cb, system, &error)) == NULL) { // Unable to create the client... papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to initialize DNS-SD: %s", _papplDNSSDStrError(error)); avahi_threaded_poll_free(pappl_dns_sd_poll); pappl_dns_sd_poll = NULL; } else { // Get the current mDNS hostname... const char *dns_sd_hostname = avahi_client_get_host_name_fqdn(pappl_dns_sd_master); // mDNS hostname if (dns_sd_hostname) papplCopyString(pappl_dns_sd_hostname, dns_sd_hostname, sizeof(pappl_dns_sd_hostname)); else httpGetHostname(NULL, pappl_dns_sd_hostname, sizeof(pappl_dns_sd_hostname)); // Start the background thread... avahi_threaded_poll_start(pappl_dns_sd_poll); } pthread_mutex_unlock(&pappl_dns_sd_mutex); #endif // HAVE_MDNSRESPONDER return (pappl_dns_sd_master); } // // '_papplDNSSDLock()' - Grab a lock to make DNS-SD changes. // void _papplDNSSDLock(void) { #ifdef HAVE_AVAHI if (pappl_dns_sd_poll) avahi_threaded_poll_lock(pappl_dns_sd_poll); #endif // HAVE_AVAHI } // // '_papplDNSSDStrError()' - Return a string for the given DNS-SD error code. // const char * // O - Error message _papplDNSSDStrError(int error) // I - Error code { #ifdef HAVE_MDNSRESPONDER switch (error) { case kDNSServiceErr_NoError : return ("No error"); case kDNSServiceErr_Unknown : default : return ("Unknown error"); case kDNSServiceErr_NoSuchName : return ("Name not found"); case kDNSServiceErr_NoMemory : return ("Out of memory"); case kDNSServiceErr_BadParam : return ("Bad parameter"); case kDNSServiceErr_BadReference : return ("Bad service reference"); case kDNSServiceErr_BadState : return ("Bad state"); case kDNSServiceErr_BadFlags : return ("Bad flags argument"); case kDNSServiceErr_Unsupported : return ("Unsupported feature"); case kDNSServiceErr_NotInitialized : return ("Not initialized"); case kDNSServiceErr_AlreadyRegistered : return ("Name already registered"); case kDNSServiceErr_NameConflict : return ("Name conflicts"); case kDNSServiceErr_Invalid : return ("Invalid argument"); case kDNSServiceErr_Firewall : return ("Firewall prevents access"); case kDNSServiceErr_Incompatible : return ("Client library incompatible with background daemon"); case kDNSServiceErr_BadInterfaceIndex : return ("Bad interface index"); case kDNSServiceErr_Refused : return ("Connection refused"); case kDNSServiceErr_NoSuchRecord : return ("DNS record not found"); case kDNSServiceErr_NoAuth : return ("No authoritative answer"); case kDNSServiceErr_NoSuchKey : return ("TXT record key not found"); case kDNSServiceErr_NATTraversal : return ("Unable to traverse via NAT"); case kDNSServiceErr_DoubleNAT : return ("Double NAT is in use"); case kDNSServiceErr_BadTime : return ("Bad time value"); case kDNSServiceErr_BadSig : return ("Bad signal"); case kDNSServiceErr_BadKey : return ("Bad TXT record key"); case kDNSServiceErr_Transient : return ("Transient error"); case kDNSServiceErr_ServiceNotRunning : return ("Background daemon not running"); case kDNSServiceErr_NATPortMappingUnsupported : return ("NAT doesn't support PCP, NAT-PMP or UPnP"); case kDNSServiceErr_NATPortMappingDisabled : return ("NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator"); case kDNSServiceErr_NoRouter : return ("No router configured, probably no network connectivity"); case kDNSServiceErr_PollingMode : return ("Polling error"); case kDNSServiceErr_Timeout : return ("Timeout"); #if !_WIN32 case kDNSServiceErr_DefunctConnection : return ("Connection lost"); #endif // !_WIN32 } #elif defined(HAVE_AVAHI) return (avahi_strerror(error)); #else return (""); #endif // HAVE_MDNSRESPONDER } // // '_papplDNSSDUnlock()' - Release a lock after making DNS-SD changes. // void _papplDNSSDUnlock(void) { #ifdef HAVE_AVAHI if (pappl_dns_sd_poll) avahi_threaded_poll_unlock(pappl_dns_sd_poll); #endif // HAVE_AVAHI } // // '_papplPrinterRegisterDNSSDNoLock()' - Register a printer's DNS-SD service. // bool // O - `true` on success, `false` on failure _papplPrinterRegisterDNSSDNoLock( pappl_printer_t *printer) // I - Printer { bool ret = true; // Return value #ifdef HAVE_DNSSD pappl_system_t *system = printer->system; // System uint32_t if_index; // Interface index _pappl_txt_t txt; // DNS-SD TXT record cups_len_t i, // Looping var count; // Number of values ipp_attribute_t *color_supported, *document_format_supported, *printer_kind, *printer_uuid, *urf_supported; // Printer attributes const char *value; // Value string char adminurl[246], // Admin URL formats[252], // List of supported formats kind[251], // List of printer-kind values urf[252], // List of supported URF values *ptr; // Pointer into string char regtype[256]; // DNS-SD service type char product[248]; // Make and model (legacy) int max_width; // Maximum media width (legacy) const char *papermax; // PaperMax string value (legacy) # ifdef HAVE_MDNSRESPONDER DNSServiceErrorType error; // Error from mDNSResponder # else int error; // Error from Avahi char fullname[256]; // Full service name # endif // HAVE_MDNSRESPONDER _pappl_dns_sd_t master; // DNS-SD master reference if (!printer->dns_sd_name || !printer->system->is_running) return (false); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s'.", printer->dns_sd_name); # ifdef HAVE_MDNSRESPONDER if_index = !strcmp(system->hostname, "localhost") ? kDNSServiceInterfaceIndexLocalOnly : kDNSServiceInterfaceIndexAny; # else if_index = !strcmp(system->hostname, "localhost") ? if_nametoindex("lo") : AVAHI_IF_UNSPEC; # endif // HAVE_MDNSRESPONDER // Get attributes and values for the TXT record... color_supported = ippFindAttribute(printer->driver_attrs, "color-supported", IPP_TAG_BOOLEAN); document_format_supported = ippFindAttribute(printer->driver_attrs, "document-format-supported", IPP_TAG_MIMETYPE); printer_kind = ippFindAttribute(printer->driver_attrs, "printer-kind", IPP_TAG_KEYWORD); printer_uuid = ippFindAttribute(printer->attrs, "printer-uuid", IPP_TAG_URI); urf_supported = ippFindAttribute(printer->driver_attrs, "urf-supported", IPP_TAG_KEYWORD); for (i = 0, count = ippGetCount(document_format_supported), ptr = formats; i < count; i ++) { value = ippGetString(document_format_supported, i, NULL); if (!strcasecmp(value, "application/octet-stream")) continue; if (ptr > formats && ptr < (formats + sizeof(formats) - 1)) *ptr++ = ','; papplCopyString(ptr, value, sizeof(formats) - (size_t)(ptr - formats)); ptr += strlen(ptr); if (ptr >= (formats + sizeof(formats) - 1)) break; } kind[0] = '\0'; for (i = 0, count = ippGetCount(printer_kind), ptr = kind; i < count; i ++) { value = ippGetString(printer_kind, i, NULL); if (ptr > kind && ptr < (kind + sizeof(kind) - 1)) *ptr++ = ','; papplCopyString(ptr, value, sizeof(kind) - (size_t)(ptr - kind)); ptr += strlen(ptr); if (ptr >= (kind + sizeof(kind) - 1)) break; } snprintf(product, sizeof(product), "(%s)", printer->driver_data.make_and_model); for (i = 0, max_width = 0; i < (cups_len_t)printer->driver_data.num_media; i ++) { pwg_media_t *media = pwgMediaForPWG(printer->driver_data.media[i]); // Current media size if (media && media->width > max_width) max_width = media->width; } if (max_width < 21000) papermax = " urf && ptr < (urf + sizeof(urf) - 1)) *ptr++ = ','; papplCopyString(ptr, value, sizeof(urf) - (size_t)(ptr - urf)); ptr += strlen(ptr); if (ptr >= (urf + sizeof(urf) - 1)) break; } httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl, sizeof(adminurl), "http", NULL, printer->system->hostname, printer->system->port, "%s/", printer->uriname); if (printer->geo_location) dns_sd_geo_to_loc(printer->geo_location, printer->dns_sd_loc); // Rename the service as needed... if (printer->dns_sd_collision) { char new_dns_sd_name[256]; // New DNS-SD name const char *serial = strstr(printer->device_uri, "?serial="); // Serial number const char *uuid = ippGetString(printer_uuid, 0, NULL); // "printer-uuid" value printer->dns_sd_serial ++; if (printer->dns_sd_serial == 1) { if (printer->system->options & PAPPL_SOPTIONS_DNSSD_HOST) snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s (%s)", printer->dns_sd_name, printer->system->hostname); else if (serial) snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s (%s)", printer->dns_sd_name, serial + 8); else snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s (%c%c%c%c%c%c)", printer->dns_sd_name, toupper(uuid[39]), toupper(uuid[40]), toupper(uuid[41]), toupper(uuid[42]), toupper(uuid[43]), toupper(uuid[44])); } else { char base_dns_sd_name[256]; // Base DNS-SD name papplCopyString(base_dns_sd_name, printer->dns_sd_name, sizeof(base_dns_sd_name)); if ((ptr = strrchr(base_dns_sd_name, '(')) != NULL) *ptr = '\0'; snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s(%d)", base_dns_sd_name, printer->dns_sd_serial); } free(printer->dns_sd_name); if ((printer->dns_sd_name = strdup(new_dns_sd_name)) != NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "DNS-SD name collision, trying new DNS-SD service name '%s'.", printer->dns_sd_name); printer->dns_sd_collision = false; } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "DNS-SD name collision, failed to allocate new DNS-SD service name."); return (false); } } if ((master = _papplDNSSDInit(printer->system)) == NULL) return (false); #endif // HAVE_DNSSD #ifdef HAVE_MDNSRESPONDER // Build the TXT record for IPP... TXTRecordCreate(&txt, 1024, NULL); TXTRecordSetValue(&txt, "rp", (uint8_t)strlen(printer->resource) - 1, printer->resource + 1); if (printer->driver_data.make_and_model[0]) TXTRecordSetValue(&txt, "ty", (uint8_t)strlen(printer->driver_data.make_and_model), printer->driver_data.make_and_model); TXTRecordSetValue(&txt, "adminurl", (uint8_t)strlen(adminurl), adminurl); if (printer->location) TXTRecordSetValue(&txt, "note", (uint8_t)strlen(printer->location), printer->location); else TXTRecordSetValue(&txt, "note", 0, ""); TXTRecordSetValue(&txt, "pdl", (uint8_t)strlen(formats), formats); if (kind[0]) TXTRecordSetValue(&txt, "kind", (uint8_t)strlen(kind), kind); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) TXTRecordSetValue(&txt, "UUID", (uint8_t)strlen(value) - 9, value + 9); if (urf[0]) TXTRecordSetValue(&txt, "URF", (uint8_t)strlen(urf), urf); TXTRecordSetValue(&txt, "Color", 1, ippGetBoolean(color_supported, 0) ? "T" : "F"); TXTRecordSetValue(&txt, "Duplex", 1, (printer->driver_data.sides_supported & PAPPL_SIDES_TWO_SIDED_LONG_EDGE) ? "T" : "F"); TXTRecordSetValue(&txt, "TLS", 3, "1.2"); TXTRecordSetValue(&txt, "txtvers", 1, "1"); TXTRecordSetValue(&txt, "qtotal", 1, "1"); TXTRecordSetValue(&txt, "priority", 1, "0"); TXTRecordSetValue(&txt, "mopria-certified", 3, "1.3"); // Legacy keys... TXTRecordSetValue(&txt, "product", (uint8_t)strlen(product), product); TXTRecordSetValue(&txt, "Fax", 1, "F"); TXTRecordSetValue(&txt, "PaperMax", (uint8_t)strlen(papermax), papermax); TXTRecordSetValue(&txt, "Scan", 1, "F"); // Register the _printer._tcp (LPD) service type with a port number of 0 to // defend our service name but not actually support LPD... if (printer->dns_sd_printer_ref) DNSServiceRefDeallocate(printer->dns_sd_printer_ref); printer->dns_sd_printer_ref = master; if ((error = DNSServiceRegister(&printer->dns_sd_printer_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, printer->dns_sd_name, "_printer._tcp", NULL /* domain */, /*hostname*/NULL, 0 /* port */, 0 /* txtLen */, NULL /* txtRecord */, (DNSServiceRegisterReply)dns_sd_printer_callback, printer)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._printer._tcp': %s", printer->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } // Then register the corresponding IPP service types with the real port // number to advertise our printer... if (printer->dns_sd_ipp_ref) DNSServiceRefDeallocate(printer->dns_sd_ipp_ref); printer->dns_sd_ipp_ref = master; if (system->subtypes && *system->subtypes) snprintf(regtype, sizeof(regtype), "_ipp._tcp,%s", system->subtypes); else papplCopyString(regtype, "_ipp._tcp", sizeof(regtype)); if ((error = DNSServiceRegister(&printer->dns_sd_ipp_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, printer->dns_sd_name, regtype, NULL /* domain */, /*hostname*/NULL, htons(system->port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), (DNSServiceRegisterReply)dns_sd_printer_callback, printer)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } if (printer->geo_location && ret) { if ((error = DNSServiceAddRecord(printer->dns_sd_ipp_ref, &printer->dns_sd_ipp_loc_ref, 0, kDNSServiceType_LOC, sizeof(printer->dns_sd_loc), printer->dns_sd_loc, 0)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } } if (printer->dns_sd_ipps_ref) DNSServiceRefDeallocate(printer->dns_sd_ipps_ref); if (!(printer->system->options & PAPPL_SOPTIONS_NO_TLS)) { printer->dns_sd_ipps_ref = master; if (system->subtypes && *system->subtypes) snprintf(regtype, sizeof(regtype), "_ipps._tcp,%s", system->subtypes); else papplCopyString(regtype, "_ipps._tcp", sizeof(regtype)); if ((error = DNSServiceRegister(&printer->dns_sd_ipps_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, printer->dns_sd_name, regtype, NULL /* domain */, /*hostname*/NULL, htons(system->port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), (DNSServiceRegisterReply)dns_sd_printer_callback, printer)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } if (printer->geo_location && ret) { if ((error = DNSServiceAddRecord(printer->dns_sd_ipps_ref, &printer->dns_sd_ipps_loc_ref, 0, kDNSServiceType_LOC, sizeof(printer->dns_sd_loc), printer->dns_sd_loc, 0)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } } } else printer->dns_sd_ipps_ref = NULL; TXTRecordDeallocate(&txt); if ((system->options & PAPPL_SOPTIONS_RAW_SOCKET) && printer->num_raw_listeners > 0) { // Register a PDL datastream (raw socket) service... TXTRecordCreate(&txt, 1024, NULL); if (printer->driver_data.make_and_model[0]) TXTRecordSetValue(&txt, "ty", (uint8_t)strlen(printer->driver_data.make_and_model), printer->driver_data.make_and_model); TXTRecordSetValue(&txt, "adminurl", (uint8_t)strlen(adminurl), adminurl); if (printer->location) TXTRecordSetValue(&txt, "note", (uint8_t)strlen(printer->location), printer->location); else TXTRecordSetValue(&txt, "note", 0, ""); TXTRecordSetValue(&txt, "pdl", (uint8_t)strlen(formats), formats); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) TXTRecordSetValue(&txt, "UUID", (uint8_t)strlen(value) - 9, value + 9); TXTRecordSetValue(&txt, "Color", 1, ippGetBoolean(color_supported, 0) ? "T" : "F"); TXTRecordSetValue(&txt, "Duplex", 1, (printer->driver_data.sides_supported & PAPPL_SIDES_TWO_SIDED_LONG_EDGE) ? "T" : "F"); TXTRecordSetValue(&txt, "txtvers", 1, "1"); TXTRecordSetValue(&txt, "qtotal", 1, "1"); TXTRecordSetValue(&txt, "priority", 3, "100"); // Legacy keys... TXTRecordSetValue(&txt, "product", (uint8_t)strlen(product), product); TXTRecordSetValue(&txt, "Fax", 1, "F"); TXTRecordSetValue(&txt, "PaperMax", (uint8_t)strlen(papermax), papermax); TXTRecordSetValue(&txt, "Scan", 1, "F"); if (printer->dns_sd_pdl_ref) DNSServiceRefDeallocate(printer->dns_sd_pdl_ref); printer->dns_sd_pdl_ref = master; if ((error = DNSServiceRegister(&printer->dns_sd_pdl_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, printer->dns_sd_name, "_pdl-datastream._tcp", NULL /* domain */, /*hostname*/NULL, htons(9099 + printer->printer_id), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), (DNSServiceRegisterReply)dns_sd_printer_callback, printer)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, "_pdl-datastream._tcp", _papplDNSSDStrError(error)); ret = false; } TXTRecordDeallocate(&txt); } // Register the _http._tcp,_printer (HTTP) service type with the real port // number to advertise our web interface... if (printer->dns_sd_http_ref) DNSServiceRefDeallocate(printer->dns_sd_http_ref); snprintf(adminurl, sizeof(adminurl), "%s/", printer->uriname); TXTRecordCreate(&txt, 1024, NULL); TXTRecordSetValue(&txt, "path", (uint8_t)strlen(adminurl), adminurl); printer->dns_sd_http_ref = master; if ((error = DNSServiceRegister(&printer->dns_sd_http_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, printer->dns_sd_name, "_http._tcp,_printer", NULL /* domain */, /*hostname*/NULL, htons(system->port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), (DNSServiceRegisterReply)dns_sd_printer_callback, printer)) != kDNSServiceErr_NoError) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, "_http._tcp,_printer", _papplDNSSDStrError(error)); ret = false; } TXTRecordDeallocate(&txt); #elif defined(HAVE_AVAHI) // Create the TXT record... txt = NULL; txt = avahi_string_list_add_printf(txt, "rp=%s", printer->resource + 1); if (printer->driver_data.make_and_model[0]) txt = avahi_string_list_add_printf(txt, "ty=%s", printer->driver_data.make_and_model); txt = avahi_string_list_add_printf(txt, "adminurl=%s", adminurl); txt = avahi_string_list_add_printf(txt, "note=%s", printer->location ? printer->location : ""); txt = avahi_string_list_add_printf(txt, "pdl=%s", formats); if (kind[0]) txt = avahi_string_list_add_printf(txt, "kind=%s", kind); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) txt = avahi_string_list_add_printf(txt, "UUID=%s", value + 9); if (urf[0]) txt = avahi_string_list_add_printf(txt, "URF=%s", urf); txt = avahi_string_list_add_printf(txt, "TLS=1.2"); txt = avahi_string_list_add_printf(txt, "Color=%s", ippGetBoolean(color_supported, 0) ? "T" : "F"); txt = avahi_string_list_add_printf(txt, "Duplex=%s", (printer->driver_data.sides_supported & PAPPL_SIDES_TWO_SIDED_LONG_EDGE) ? "T" : "F"); txt = avahi_string_list_add_printf(txt, "txtvers=1"); txt = avahi_string_list_add_printf(txt, "qtotal=1"); txt = avahi_string_list_add_printf(txt, "priority=0"); txt = avahi_string_list_add_printf(txt, "mopria-certified=1.3"); // Legacy keys... txt = avahi_string_list_add_printf(txt, "product=%s", product); txt = avahi_string_list_add_printf(txt, "Fax=F"); txt = avahi_string_list_add_printf(txt, "PaperMax=%s", papermax); txt = avahi_string_list_add_printf(txt, "Scan=F"); // Register _printer._tcp (LPD) with port 0 to reserve the service name... _papplDNSSDLock(); if (printer->dns_sd_ref) avahi_entry_group_free(printer->dns_sd_ref); if ((printer->dns_sd_ref = avahi_entry_group_new(master, (AvahiEntryGroupCallback)dns_sd_printer_callback, printer)) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register printer, is the Avahi daemon running?"); _papplDNSSDUnlock(); avahi_string_list_free(txt); return (false); } if ((error = avahi_entry_group_add_service_strlst(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_printer._tcp", NULL, NULL, 0, NULL)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._printer._tcp': %s", printer->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } // Then register the IPP/IPPS services... if ((error = avahi_entry_group_add_service_strlst(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipp._tcp", NULL, /*hostname*/NULL, system->port, txt)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._ipp._tcp': %s", printer->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } if (system->subtypes && *system->subtypes) { char *temptypes = strdup(system->subtypes), *start, *end; // Pointers into sub-types... for (start = temptypes; start && *start; start = end) { if ((end = strchr(start, ',')) != NULL) *end++ = '\0'; else end = start + strlen(start); snprintf(regtype, sizeof(regtype), "%s._sub._ipp._tcp", start); if ((error = avahi_entry_group_add_service_subtype(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipp._tcp", NULL, regtype)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } } free(temptypes); } if (!(printer->system->options & PAPPL_SOPTIONS_NO_TLS)) { if ((error = avahi_entry_group_add_service_strlst(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipps._tcp", NULL, /*hostname*/NULL, system->port, txt)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._ipps._tcp': %s", printer->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } if (system->subtypes && *system->subtypes) { char *temptypes = strdup(system->subtypes), *start, *end; // Pointers into sub-types... for (start = temptypes; start && *start; start = end) { if ((end = strchr(start, ',')) != NULL) *end++ = '\0'; else end = start + strlen(start); snprintf(regtype, sizeof(regtype), "%s._sub._ipps._tcp", start); if ((error = avahi_entry_group_add_service_subtype(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipps._tcp", NULL, regtype)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", printer->dns_sd_name, regtype, _papplDNSSDStrError(error)); ret = false; } } free(temptypes); } } avahi_string_list_free(txt); if ((system->options & PAPPL_SOPTIONS_RAW_SOCKET) && printer->num_raw_listeners > 0) { // Register a PDL datastream (raw socket) service... txt = NULL; if (printer->driver_data.make_and_model[0]) txt = avahi_string_list_add_printf(txt, "ty=%s", printer->driver_data.make_and_model); txt = avahi_string_list_add_printf(txt, "adminurl=%s", adminurl); txt = avahi_string_list_add_printf(txt, "note=%s", printer->location ? printer->location : ""); txt = avahi_string_list_add_printf(txt, "pdl=%s", formats); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) txt = avahi_string_list_add_printf(txt, "UUID=%s", value + 9); txt = avahi_string_list_add_printf(txt, "Color=%s", ippGetBoolean(color_supported, 0) ? "T" : "F"); txt = avahi_string_list_add_printf(txt, "Duplex=%s", (printer->driver_data.sides_supported & PAPPL_SIDES_TWO_SIDED_LONG_EDGE) ? "T" : "F"); txt = avahi_string_list_add_printf(txt, "txtvers=1"); txt = avahi_string_list_add_printf(txt, "qtotal=1"); txt = avahi_string_list_add_printf(txt, "priority=100"); // Legacy keys... txt = avahi_string_list_add_printf(txt, "product=%s", product); txt = avahi_string_list_add_printf(txt, "Fax=F"); txt = avahi_string_list_add_printf(txt, "PaperMax=%s", papermax); txt = avahi_string_list_add_printf(txt, "Scan=F"); if ((error = avahi_entry_group_add_service_strlst(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_pdl-datastream._tcp", NULL, /*hostname*/NULL, 9099 + printer->printer_id, txt)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._pdl-datastream._tcp': %s", printer->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } avahi_string_list_free(txt); } // Register the geolocation of the service... if (printer->geo_location && ret) { snprintf(fullname, sizeof(fullname), "%s._ipp._tcp.local.", printer->dns_sd_name); if ((error = avahi_entry_group_add_record(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_LOC, 75 * 60, printer->dns_sd_loc, sizeof(printer->dns_sd_loc))) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s': %s", fullname, _papplDNSSDStrError(error)); ret = false; } snprintf(fullname, sizeof(fullname), "%s._ipps._tcp.local.", printer->dns_sd_name); if ((error = avahi_entry_group_add_record(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_LOC, 75 * 60, printer->dns_sd_loc, sizeof(printer->dns_sd_loc))) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s': %s", fullname, _papplDNSSDStrError(error)); ret = false; } } // Finally _http.tcp (HTTP) for the web interface... txt = NULL; txt = avahi_string_list_add_printf(txt, "path=%s/", printer->uriname); avahi_entry_group_add_service_strlst(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_http._tcp", NULL, /*hostname*/NULL, system->port, txt); avahi_entry_group_add_service_subtype(printer->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_http._tcp", NULL, "_printer._sub._http._tcp"); avahi_string_list_free(txt); // Commit it... avahi_entry_group_commit(printer->dns_sd_ref); _papplDNSSDUnlock(); #endif // HAVE_MDNSRESPONDER return (ret); } // // '_papplPrinterUnregisterDNSSDNoLock()' - Unregister a printer's DNS-SD service. // void _papplPrinterUnregisterDNSSDNoLock( pappl_printer_t *printer) // I - Printer { #if HAVE_MDNSRESPONDER if (printer->dns_sd_printer_ref) { DNSServiceRefDeallocate(printer->dns_sd_printer_ref); printer->dns_sd_printer_ref = NULL; } if (printer->dns_sd_ipp_ref) { DNSServiceRefDeallocate(printer->dns_sd_ipp_ref); printer->dns_sd_ipp_ref = NULL; printer->dns_sd_ipp_loc_ref = NULL; } if (printer->dns_sd_ipps_ref) { DNSServiceRefDeallocate(printer->dns_sd_ipps_ref); printer->dns_sd_ipps_ref = NULL; printer->dns_sd_ipps_loc_ref = NULL; } if (printer->dns_sd_http_ref) { DNSServiceRefDeallocate(printer->dns_sd_http_ref); printer->dns_sd_http_ref = NULL; } #elif defined(HAVE_AVAHI) _papplDNSSDLock(); if (printer->dns_sd_ref) { avahi_entry_group_free(printer->dns_sd_ref); printer->dns_sd_ref = NULL; } _papplDNSSDUnlock(); #else (void)printer; #endif // HAVE_MDNSRESPONDER } // // '_papplSystemRegisterDNSSDNoLock()' - Register a system's DNS-SD service. // bool // O - `true` on success, `false` on failure _papplSystemRegisterDNSSDNoLock( pappl_system_t *system) // I - System { bool ret = true; // Return value #ifdef HAVE_DNSSD _pappl_dns_sd_t master; // DNS-SD master reference _pappl_txt_t txt; // DNS-SD TXT record uint32_t if_index; // Interface index # ifdef HAVE_MDNSRESPONDER DNSServiceErrorType error; // Error from mDNSResponder # else int error; // Error from Avahi char fullname[256]; // Full name of services # endif // HAVE_MDNSRESPONDER // Make sure we have all of the necessary information to register the system... if (!system->dns_sd_name || !system->hostname || !system->uuid || !system->is_running) return (false); papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s'.", system->dns_sd_name); # ifdef HAVE_MDNSRESPONDER if_index = !strcmp(system->hostname, "localhost") ? kDNSServiceInterfaceIndexLocalOnly : kDNSServiceInterfaceIndexAny; # else if_index = !strcmp(system->hostname, "localhost") ? if_nametoindex("lo") : AVAHI_IF_UNSPEC; # endif // HAVE_MDNSRESPONDER if (system->geo_location) dns_sd_geo_to_loc(system->geo_location, system->dns_sd_loc); // Rename the service as needed... if (system->dns_sd_collision) { char new_dns_sd_name[256]; // New DNS-SD name system->dns_sd_serial ++; if (system->dns_sd_serial == 1) { if (system->options & PAPPL_SOPTIONS_DNSSD_HOST) snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s (%s)", system->dns_sd_name, system->hostname); else snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s (%c%c%c%c%c%c)", system->dns_sd_name, toupper(system->uuid[39]), toupper(system->uuid[40]), toupper(system->uuid[41]), toupper(system->uuid[42]), toupper(system->uuid[43]), toupper(system->uuid[44])); } else { char base_dns_sd_name[256], // Base DNS-SD name *ptr; // Pointer into name papplCopyString(base_dns_sd_name, system->dns_sd_name, sizeof(base_dns_sd_name)); if ((ptr = strrchr(base_dns_sd_name, '(')) != NULL) *ptr = '\0'; snprintf(new_dns_sd_name, sizeof(new_dns_sd_name), "%s(%d)", base_dns_sd_name, system->dns_sd_serial); } free(system->dns_sd_name); if ((system->dns_sd_name = strdup(new_dns_sd_name)) != NULL) { papplLog(system, PAPPL_LOGLEVEL_INFO, "DNS-SD name collision, trying new DNS-SD service name '%s'.", system->dns_sd_name); system->dns_sd_collision = false; } else { papplLog(system, PAPPL_LOGLEVEL_ERROR, "DNS-SD name collision, unable to allocate new DNS-SD service name."); return (false); } } if ((master = _papplDNSSDInit(system)) == NULL) return (false); #endif // HAVE_DNSSD #ifdef HAVE_MDNSRESPONDER // Build the TXT record... TXTRecordCreate(&txt, 1024, NULL); if (system->location != NULL) TXTRecordSetValue(&txt, "note", (uint8_t)strlen(system->location), system->location); TXTRecordSetValue(&txt, "UUID", (uint8_t)strlen(system->uuid) - 9, system->uuid + 9); // Then register the corresponding IPPS service type to advertise our system... if (system->dns_sd_ipps_ref) DNSServiceRefDeallocate(system->dns_sd_ipps_ref); if (!(system->options & PAPPL_SOPTIONS_NO_TLS)) { system->dns_sd_ipps_ref = master; if ((error = DNSServiceRegister(&system->dns_sd_ipps_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, system->dns_sd_name, "_ipps-system._tcp", NULL /* domain */, /*hostname*/NULL, htons(system->port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), (DNSServiceRegisterReply)dns_sd_system_callback, system)) != kDNSServiceErr_NoError) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._ipps-system._tcp': %s", system->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } if (system->geo_location && ret) { papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Registering LOC record for '%s._ipps-system._tcp' with data %02X %02X %02X %02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X", system->dns_sd_name, system->dns_sd_loc[0], system->dns_sd_loc[1], system->dns_sd_loc[2], system->dns_sd_loc[3], system->dns_sd_loc[4], system->dns_sd_loc[5], system->dns_sd_loc[6], system->dns_sd_loc[7], system->dns_sd_loc[8], system->dns_sd_loc[9], system->dns_sd_loc[10], system->dns_sd_loc[11], system->dns_sd_loc[12], system->dns_sd_loc[13], system->dns_sd_loc[14], system->dns_sd_loc[15]); if ((error = DNSServiceAddRecord(system->dns_sd_ipps_ref, &system->dns_sd_loc_ref, 0, kDNSServiceType_LOC, sizeof(system->dns_sd_loc), system->dns_sd_loc, 0)) != kDNSServiceErr_NoError) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s._ipps-system._tcp': %s", system->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } } } else system->dns_sd_ipps_ref = NULL; TXTRecordDeallocate(&txt); // Register the _http._tcp,_printer (HTTP) service type with the real port // number to advertise our web interface... if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { if (system->dns_sd_http_ref) DNSServiceRefDeallocate(system->dns_sd_http_ref); system->dns_sd_http_ref = master; if ((error = DNSServiceRegister(&system->dns_sd_http_ref, kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename, if_index, system->dns_sd_name, "_http._tcp,_printer", NULL /* domain */, /*hostname*/NULL, htons(system->port), 0 /* txtlen */, NULL /* txt */, (DNSServiceRegisterReply)dns_sd_system_callback, system)) != kDNSServiceErr_NoError) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s.%s': %s", system->dns_sd_name, "_http._tcp,_printer", _papplDNSSDStrError(error)); ret = false; } } #elif defined(HAVE_AVAHI) // Create the TXT record... txt = NULL; if (system->location) txt = avahi_string_list_add_printf(txt, "note=%s", system->location); txt = avahi_string_list_add_printf(txt, "UUID=%s", system->uuid + 9); // Register _printer._tcp (LPD) with port 0 to reserve the service name... _papplDNSSDLock(); if (system->dns_sd_ref) avahi_entry_group_free(system->dns_sd_ref); if ((system->dns_sd_ref = avahi_entry_group_new(master, (AvahiEntryGroupCallback)dns_sd_system_callback, system)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register system, is the Avahi daemon running?"); _papplDNSSDUnlock(); avahi_string_list_free(txt); return (false); } if (!(system->options & PAPPL_SOPTIONS_NO_TLS)) { if ((error = avahi_entry_group_add_service_strlst(system->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, system->dns_sd_name, "_ipps-system._tcp", NULL, /*hostname*/NULL, system->port, txt)) < 0) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register '%s._ipps-system._tcp': %s", system->dns_sd_name, _papplDNSSDStrError(error)); ret = false; } // Register the geolocation of the service... if (system->geo_location && ret) { snprintf(fullname, sizeof(fullname), "%s._ipps-system._tcp.local.", system->dns_sd_name); papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Registering LOC record for '%s' with data %02X %02X %02X %02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X", fullname, system->dns_sd_loc[0], system->dns_sd_loc[1], system->dns_sd_loc[2], system->dns_sd_loc[3], system->dns_sd_loc[4], system->dns_sd_loc[5], system->dns_sd_loc[6], system->dns_sd_loc[7], system->dns_sd_loc[8], system->dns_sd_loc[9], system->dns_sd_loc[10], system->dns_sd_loc[11], system->dns_sd_loc[12], system->dns_sd_loc[13], system->dns_sd_loc[14], system->dns_sd_loc[15]); if ((error = avahi_entry_group_add_record(system->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_LOC, 75 * 60, system->dns_sd_loc, sizeof(system->dns_sd_loc))) < 0) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to register LOC record for '%s': %s", fullname, _papplDNSSDStrError(error)); ret = false; } } } // Finally _http.tcp (HTTP) for the web interface... if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { avahi_entry_group_add_service_strlst(system->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, system->dns_sd_name, "_http._tcp", NULL, /*hostname*/NULL, system->port, NULL); avahi_entry_group_add_service_subtype(system->dns_sd_ref, if_index, AVAHI_PROTO_UNSPEC, 0, system->dns_sd_name, "_http._tcp", NULL, "_printer._sub._http._tcp"); } // Commit it... avahi_entry_group_commit(system->dns_sd_ref); _papplDNSSDUnlock(); avahi_string_list_free(txt); #endif // HAVE_MDNSRESPONDER return (ret); } // // '_papplSystemUnregisterDNSSDNoLock()' - Unregister a printer's DNS-SD service. // void _papplSystemUnregisterDNSSDNoLock( pappl_system_t *system) // I - System { #if HAVE_MDNSRESPONDER if (system->dns_sd_ipps_ref) { DNSServiceRefDeallocate(system->dns_sd_ipps_ref); system->dns_sd_ipps_ref = NULL; } if (system->dns_sd_http_ref) { DNSServiceRefDeallocate(system->dns_sd_http_ref); system->dns_sd_http_ref = NULL; } #elif defined(HAVE_AVAHI) _papplDNSSDLock(); if (system->dns_sd_ref) { avahi_entry_group_free(system->dns_sd_ref); system->dns_sd_ref = NULL; } _papplDNSSDUnlock(); #else (void)system; #endif // HAVE_MDNSRESPONDER } // // 'dns_sd_geo_to_loc()' - Convert a "geo:" URI to a DNS LOC record. // static void dns_sd_geo_to_loc(const char *geo, // I - "geo:" URI unsigned char loc[16])// O - DNS LOC record { double lat = 0.0, lon = 0.0; // Latitude and longitude in degrees double alt = 0.0; // Altitude in meters unsigned int lat_ksec, lon_ksec; // Latitude and longitude in thousandths of arc seconds, biased by 2^31 unsigned int alt_cm; // Altitude in centimeters, biased by 10,000,000cm // Pull apart the "geo:" URI and convert to the integer representation for // the LOC record... sscanf(geo, "geo:%lf,%lf,%lf", &lat, &lon, &alt); lat_ksec = (unsigned)((int)(lat * 3600000.0) + 0x40000000 + 0x40000000); lon_ksec = (unsigned)((int)(lon * 3600000.0) + 0x40000000 + 0x40000000); alt_cm = (unsigned)((int)(alt * 100.0) + 10000000); // Build the LOC record... loc[0] = 0x00; // Version loc[1] = 0x11; // Size (10cm) loc[2] = 0x11; // Horizontal precision (10cm) loc[3] = 0x11; // Vertical precision (10cm) loc[4] = (unsigned char)(lat_ksec >> 24); // Latitude (32-bit big-endian) loc[5] = (unsigned char)(lat_ksec >> 16); loc[6] = (unsigned char)(lat_ksec >> 8); loc[7] = (unsigned char)(lat_ksec); loc[8] = (unsigned char)(lon_ksec >> 24); // Latitude (32-bit big-endian) loc[9] = (unsigned char)(lon_ksec >> 16); loc[10] = (unsigned char)(lon_ksec >> 8); loc[11] = (unsigned char)(lon_ksec); loc[12] = (unsigned char)(alt_cm >> 24); // Altitude (32-bit big-endian) loc[13] = (unsigned char)(alt_cm >> 16); loc[14] = (unsigned char)(alt_cm >> 8); loc[15] = (unsigned char)(alt_cm); } #ifdef HAVE_MDNSRESPONDER // // 'dns_sd_hostname_callback()' - Track changes to the mDNS hostname... // static void DNSSD_API dns_sd_hostname_callback( DNSServiceRef ref, // I - Service reference (unused) DNSServiceFlags flags, // I - Flags (unused) uint32_t if_index, // I - Interface index (unused) DNSServiceErrorType error, // I - Error code, if any const char *fullname, // I - Search name (unused) uint16_t rrtype, // I - Record type (unused) uint16_t rrclass, // I - Record class (unused) uint16_t rdlen, // I - Record data length const void *rdata, // I - Record data uint32_t ttl, // I - Time-to-live (unused) void *context) // I - Context (unused) { uint8_t *rdataptr, // Pointer into record data lablen; // Length of current label char temp[1024], // Temporary hostname string *tempptr; // Pointer into temporary string (void)ref; (void)flags; (void)if_index; (void)fullname; (void)rrtype; (void)rrclass; (void)ttl; (void)context; // Check for errors... if (error != kDNSServiceErr_NoError) return; // Copy the hostname from the PTR record... for (rdataptr = (uint8_t *)rdata, tempptr = temp; rdlen > 0 && tempptr < (temp + sizeof(temp) - 2); rdlen -= lablen, rdataptr += lablen) { lablen = *rdataptr++; rdlen --; if (!rdlen || rdlen < lablen) break; if (tempptr > temp) *tempptr++ = '.'; if (lablen < (sizeof(temp) - (size_t)(tempptr - temp))) { memcpy(tempptr, rdataptr, lablen); tempptr += lablen; } } *tempptr = '\0'; // Ignore localhost... if (!strcmp(temp, "localhost")) return; // Look for changes to the hostname... pthread_mutex_lock(&pappl_dns_sd_hostname_mutex); if (strcmp(temp, pappl_dns_sd_hostname)) { papplCopyString(pappl_dns_sd_hostname, temp, sizeof(pappl_dns_sd_hostname)); pappl_dns_sd_hostname_changes ++; } pthread_mutex_unlock(&pappl_dns_sd_hostname_mutex); } // // 'dns_sd_printer_callback()' - Handle DNS-SD printer registration events. // static void DNSSD_API dns_sd_printer_callback( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Status flags DNSServiceErrorType errorCode, // I - Error, if any const char *name, // I - Service name const char *regtype, // I - Service type const char *domain, // I - Domain for service pappl_printer_t *printer) // I - Printer { (void)name; (void)sdRef; (void)flags; (void)domain; if (errorCode == kDNSServiceErr_NameConflict) { _papplRWLockWrite(printer->system); _papplRWLockWrite(printer); printer->dns_sd_collision = true; printer->system->dns_sd_any_collision = true; _papplRWUnlock(printer); _papplRWUnlock(printer->system); } else if (errorCode) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "DNSServiceRegister for '%s' failed with error %d (%s).", regtype, (int)errorCode, _papplDNSSDStrError(errorCode)); return; } } // // 'dns_sd_run()' - Handle DNS-SD traffic. // static void * // O - Exit status dns_sd_run(void *data) // I - System object { int err; // Status pappl_system_t *system = (pappl_system_t *)data; // System object struct pollfd pfd; // Poll data pfd.events = POLLIN | POLLERR; pfd.fd = DNSServiceRefSockFD(pappl_dns_sd_master); for (;;) { // Wait up to 1 second for new data... # if _WIN32 if (poll(&pfd, 1, 1000) < 0 && WSAGetLastError() == WSAEINTR) # else if (poll(&pfd, 1, 1000) < 0 && errno != EINTR && errno != EAGAIN) # endif // _WIN32 { papplLog(system, PAPPL_LOGLEVEL_ERROR, "DNS-SD poll failed: %s", strerror(errno)); break; } if (pfd.revents & POLLIN) { // Read DNS-SD data... if ((err = DNSServiceProcessResult(pappl_dns_sd_master)) != kDNSServiceErr_NoError) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "DNSServiceProcessResult returned %d (%s).", err, _papplDNSSDStrError(err)); break; } } else if (pfd.revents) { // Some other state, stop... break; } } return (NULL); } // // 'dns_sd_system_callback()' - Handle DNS-SD system registration events. // static void DNSSD_API dns_sd_system_callback( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Status flags DNSServiceErrorType errorCode, // I - Error, if any const char *name, // I - Service name const char *regtype, // I - Service type const char *domain, // I - Domain for service pappl_system_t *system) // I - System { (void)sdRef; (void)flags; (void)name; (void)domain; if (errorCode == kDNSServiceErr_NameConflict) { _papplRWLockWrite(system); system->dns_sd_collision = true; system->dns_sd_any_collision = true; _papplRWUnlock(system); } else if (errorCode) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "DNSServiceRegister for '%s' failed with error %d (%s).", regtype, (int)errorCode, _papplDNSSDStrError(errorCode)); return; } } #elif defined(HAVE_AVAHI) // //'dns_sd_client_cb()' - Client callback for Avahi. // // Called whenever the client or server state changes... // static void dns_sd_client_cb( AvahiClient *c, // I - Client AvahiClientState state, // I - Current state void *data) // I - Callback data (unused) { (void)data; if (!c) return; if (state == AVAHI_CLIENT_FAILURE) { if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { fputs("Avahi server crashed.\n", stderr); } } else if (state == AVAHI_CLIENT_S_RUNNING) { pthread_mutex_lock(&pappl_dns_sd_hostname_mutex); pappl_dns_sd_hostname_changes ++; pthread_mutex_unlock(&pappl_dns_sd_hostname_mutex); } } // // 'dns_sd_printer_callback()' - Handle DNS-SD printer registration events. // static void dns_sd_printer_callback( AvahiEntryGroup *srv, // I - Service AvahiEntryGroupState state, // I - Registration state pappl_printer_t *printer) // I - Printer { (void)srv; if (state == AVAHI_ENTRY_GROUP_COLLISION) { _papplRWLockWrite(printer->system); _papplRWLockWrite(printer); printer->dns_sd_collision = true; printer->system->dns_sd_any_collision = true; _papplRWUnlock(printer); _papplRWUnlock(printer->system); } } // // 'dns_sd_system_callback()' - Handle DNS-SD system registration events. // static void dns_sd_system_callback( AvahiEntryGroup *srv, // I - Service AvahiEntryGroupState state, // I - Registration state pappl_system_t *system) // I - System { (void)srv; if (state == AVAHI_ENTRY_GROUP_COLLISION) { _papplRWLockWrite(system); system->dns_sd_collision = true; system->dns_sd_any_collision = true; _papplRWUnlock(system); } } #endif // HAVE_MDNSRESPONDER pappl-1.4.9/pappl/epub.png000066400000000000000000027634431476704353100154530ustar00rootroot00000000000000PNG  IHDRxQ"UgiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*ixQkeiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image Sve IDATxڬ}$m+rvNeꞕl?+L>@ ̪?럟 xWEϿƟ?,^g1QU2<^>.5r~oן]7z^]u.㷀<'W=[,7_y}<{>1{ɿE竭ZMy׻=x{߿?=Ow,d{+|``o7x/yo%[wrww {ɳj\>]}Yܮ_m?9D/sLc?xz~GE+ kڛ7O} |/]?v~g99ysxy<:xn{5PH k"o>WFo+֐9LnaPywGcKaKO67~!E#ش?9w99HFpϖ-&;6:{ǫb᫻o0NxИ_x.ޖ'V慨7O3?zͯ}7@I~َx^cIiDl4!yֿdZ%jy5]?{?8#;^UN(p#Qҥ/K&G3ff0~tA2UOɛ8,~Rø/'>i@Xl?.Q_7,Zro6~wĺiՉtGm~3X*xX)Ļ_9n׵!N(~9|7~Nؓ>˞8{bobI;/}Sx 0䌗̶x։A)];Pr\a߼Qg604/NVr=NBA~uGDio752VSb:W:_o58|bBeu(d3s',>-s72[of:pX}Kx gϡyA? 7)||jޢƝDi\Vv~t>jk}鬳OM0T' r$67=fPɏu? Kƛ?0N O f) mCou *HYza{?.y}HmWU?۪^p̀y70 ž4LU(>9isZ&?Oв JFް ױ1(=~wCږgcoQzޓۡlo7&\2>؛ae{Zkbܦ) #n?ӧb'ψ[iX©.|t.qGq__Sq< 7Iyo[tV0?`?灄 *b~s2`?@ cI]Cqs 簤B$Q9]xxOkAy(-Tiع ٭p Aei xz[4E qq޹y'םoy7/4iī݈~Oy2s`o~0K8 N-R2+Ұ9N_cp 3q e<gЪ#O^5Y Q5m>c}z3pQW6H)Ia_[O8M~THkP ,h?8#h4~JP_Nv7w;Q{p6aeg?Sk\P<g%6<7Lilpy15|Ŧgo<#>l0F3{$Hl a=J竻=oD~L1Lx|K~6،3{qu\24\x- ƿfoz%xA_ό䨍  b^@@ EEyxv,uAλ 05iۛbM{v6a["OLEy'w'sagǹkx'P鰛>^KFƤ?Ǝv:ΰuzwCHƒyDތM؏Ӽ1\ea`'>C?w8f1)(H83 ZL7?Eק!'pF\_`wFlL ~70e?ngS,(m6ןx]o1~$dxc#:!Dv/x=~l_$5<#+j߶Y~ۛ! K Qf~cK}n]0w;gR# {lo\(>o/Z*Dట짮=Hg5j2sߴ̈m0f9б7Qy>Y?V:&OmLk? ?msBsz̳.ڞC_㋿:o' Qn:4uT\nT?tN ]e@{#{8?cs}ΐ۱Rڪ>Pt#!][ryK0@ B6hRf /B!sոr` :q`?Ya>^tS7q쯪'}DVn O%}"a%̒x40uyϛ0!E6h<po/QG#O4 ī#e{Gg9~SZȺsaԈ=\%%y짧.^ g;TIXWk&ś (M0)c?%v1w P4V|?3Nۈ~`i&e5]Yl~# 8r8 H{Ԑ\W j2^VWbBtEfpTA,k9z ٯ9!-ʘlv0 5𻂂Wm 6#xy,.(x%H`$hRC#D K\BtȂoC( LTԐs!#PU3Ac0Obh~xkoCs߈^vx7QE̙v2io`B<P{s:Wzr5 ;f?*J`DAL/KA@Y =贪 <362%@)*~yO8-fX EdI u3_Qqm}Hy췺 ɜ0{# [&p$ۃ-* +42Ѿ6X?$u5ao)D6) _'hrz} svO^Pqw;=,,\n3OAD;I$3\D pX%4]3$gIzɌ+,,lHyn/lZ yy)uE:3y)cVl'&w5Ģ׏T%5ñFUquV(Ta!*U_=3sRԇfќcnYp{}4Ia0 uZ"oy}t(Io.Tf& ڴ ϸ /ã[ cU?W64qWGŸ4NF_ EpJI &z76B}PH!mCOycRo?r\?vuC`D@-N z|ͯ1?L?3+-[sq)'GiTPQȎ Kd&zB1Ud T I+g3_4$pV"y6I~GYn37Rr7Yuj׹w#FҾB?NciUw^bnM˻h>6Dhb׫boA&GaК)$Ygd =CP }P7ZD⣚RP"/Y:%/& q땻V0 ky:0 mRKOٛR}Amb;#*]梎HTW[= I&|0hHdZ]R+Jplwb|E@*p/@bo{ Z-WQ(Q/r2a`_?"Ͽ#л&e(&)L|tДj @:S%ohӾT69[$1I, ?ϔ*3_|:X@Y$,2Y[?4 Tviym$gjyBL( 1 ϟrm%6}=փ:RRfWftnÈ TLV ~f5WZw $4j{#yۇAݺg(.Qǟ02pdׅGu\ְ -gc??"3l?Aͭ*F(-}׹Qj[\g@qJFFǫ$/ފM"y N+̵V`'tP]92ٛ^**@)k cܯ vT̗Z""pf?mA$B܅|1-hj*ɕD(L& _g{ݦ.v(FŲpDA0@߫yg* )L=!XB NہܼύW˞B. _I'6۫߄p i(6 __ASGZ! A6B܎7&V,DaX4[$~`p8{+Us0G\C5x8mw^TFia[ j(e61kLƦNd 'Hv,%!W*YC.eZ۝-9mx}3O2F ]~="h?ԒOιXs,a"~8Yq4 CRP*[c~|W %Ħ-"871iʼ}pMibDf};]:8CD B|=#;ALϧ Lx߄fh(nr`Z.~L~8U[G#b(L2@s2|'^']P ~6HeP ^#oocD?>,6b3;_bM}0 N֨A[j*)C*e&6|`k|%N(Pq#"bZ#DC0 ^ WB'5dV# e_+,{ӘXRYMRpSR}+V%KCY0vD>ii8$Rހ釆E yo%/We@]vCY?^8$1V 䓇,Yd?S:I8C1Kdːl{(8?fDŽUL{ONC *!P740-3g?s0ݖH!/>'B.{vr@ y8دC@ ΢w&$\BJv~]˼#LQmWBE?mGh=<ζ4`nևm\WcS!ɣ'b;`$lT4cщwS ( nͨΝ\"6Oq5+?Ч$/Mxpnwr2 'J>!0BIG{Mpȏ`! @l-2V8`VU:AѾC!K%5ua+ٳ_`@@2|_+/R^]J׾ 򣾽H{;AG^Ӓ_[%2dr#G-)"p 0fL⟪5zs^Km=#-K94\΁ƈ5&ᛙzճ[#oxʩ§HnPsZ_DZK6^oz&8VjeoJɈ9`7{nn4Kȯ ©4~:ߓ~^4bYb>0@zlo~^4 8X'RbTdo9? Mmُ|]N}fla 0W&f~,I|!pi\C^so_@g o -w6'2(p=GB>[ f$=K*ϏDWD {iq ;neˑzz}ǩ=GIպ~=\MZ5ՑD:^} g2?E( o㐄Vv {Ax9 "Fd1]r0V1K]_j,G?q XՃs0w^ŸBumTW@eI`԰{7h%?Ώ|l+\|/_脌e{L# dW:I1Acْ|~ VERQHm!/p\Э F*~#Bwt6qzd!7 oOQxP89RMU~@{{k5o?Qd+2*! Xz\+xV%=8]G$tԂ@ /Gz/2PE ABɵ)k2 sBLCS g;' 9;?vV>xAJpuxa/bSB>R7H_ZD8jhkyރK"yzw ,do4+΢: /4y~8?! `;̑ +bwCIYboaluw<@4R2ey#^=؎#PʿiNȝx>kLOm9=%-8V`hN4q7]̊|8~C~+q~OCt4弣5\y|'0GɼEG/'Bb *M0/)d}~p%2TϢnlOmk#eB>9kϊ{M qa.%4|t+vs'3PRGV(&  $[I-uhLd~P!1/jp]hjC,iI!iR!h(A zQG+DLW;0l߸Y7Yj?#dZP#,R%-"1) L$b?X0 ooF',DkS{7qO`JZ~ԛxe R .Ea IϩwJ?h5Bɧ !L@{Bfπ_uʰ^:p7~|zó9AⓢG9ޣu9lyAUbax{xd )B%D^utbqP32u.d^5Nui lA'_Çd>t=YkR|c?B&b?%U-@U? :=nӠ#K>yNP7()1ǎc* EO. kO)?s8 &ퟷ5nJH XI0i.A-|M="<>1R^řuEk=];lqub\0Uiʆ$.q R 8WZЊڛi< O8'~`M(L@W{ E-rp?M"e-C@rk!!iIu25Z3N!f/ ֫Du G/ԮNpeHf1XC 9K+L7oLzLrC<>+6ϼ8Iֳ@TaX` ^h<rP-/po)ǻAU;No0ٝQgROoin,l (1J Lʣ2`7ěn™X21v4C~3I#/@Pܷ s$!~ գHuDJ,6e IQ7 ^JN"]Cf~ROe=o#gGT[V8?KGȵT|y.fH,Qh %0;(>0|A6Z>lƿ39 f1?d~uD * GyV >Gl'g{^S$\#y>Mҟ$&sv"i !%&M#CuݐEΌ\qe܆i*@{~1ӏ[U:Rߴp4S_f(d2~ |Dh1@`82T:h0' CW7;N&&׬n1UzKpfonh?c@.}lr°&hJ0µ,ssp5\Rn#cq9<Ċ%OFxqM2r!xjGLd< {[ )hX9nz)yPQL9*c]r_V|g@f:Ba@L3Gmu%" uCw5?z6^ ԏ?=@v= _#^?Gے_'9r(Ao_YquaZvLhoG2:x3s!qur.h:e,#v :b\ >3  Bk<`=)#2$ wdoF6s(F]hVp mQ+LeGȧ >A"-‹~Q/nbO Txi&(a~MneE` tMtcB&/˸D|io4k(6I;'"j!yD(j?Lngb}*b+{"8ÄƔt99rj~gm# s{m 4ZhW2\U Jy֤9M@4|uN|a:x\Br"2}p-c~Ӂ)J 5g6^r q<͞7c_?OrtC~"ƫCKRx -+z2M6Ņt>*ndowuZsnci0?uNp;M_x5@M!+R".@-vwl,( y%%q(y'|1˺e3]?O.A l تT (G&be)t/=wAm5'Av|^c \=])ě^lb! .F#e(V{cc ak&I[£Z;yO('/0>d&.KD}IϑtD4q#~W5N\54K }GzۨR4@92'LH{🊔ֆvyG 1ymSUMTP !4z_#QGj>IKӅE#?HK1Ogoؓj}s:{;#>"r/˝rE4pe *-1Wn4@1\SEL2B *iK8W_8qT]"[aC!M0҅E,(eūfRr%qa1d.L~F(+ h#|9t.bϏF3kRTDƭBa_d{~ 拶|/Duf%aIAt|K& Tc6>͡+U ; 1Kq3X,Æb7 R7qDy?Jo ry u}SGHc?9ieC . t΋ ^B~ve|aowkP?`LDTp{b OG{{c MߐMi[_S)ts?vLc?f7 9#kIԺ^DSɤEk w( @oY SZBO25foVb&a8Vy=ƲBp$wPƟbP.T._\/)24SԆo<+ᛚѸ!#… bkd!<߼`Ezv6 vWаCyʽ*Y"R~xeDV7PۋnnҪm_GhU ( ||HnFA#AjCJ xO<Su/pꓲ lz}+ k?s'?DZq_MDb_`?8^=kOWe:jL|4xtވ"JDa}}XyX%t8t՘>ϳ2g: (@IuFb9&+pvHלd?t=?/x^$ א&o^U;,쇀j5E>^"yܮ {(bsX흓 2guq uLHKuVghz4;@X@*O~58sbURg`~V(r̹˒q b^|=1ٴz D D.d?΁':Dd~cQ_x!T.yangZ@ph8"'ۏB{KyiXp!?aoyyn 7/c? g? AŊ1$TH6&搃15U#G^}VZ ~ORp k\Uedh Xa>}1I?+;;o@o8P^ JNHċϋyx@1#U'P|( ?YW<!R$? n"WE"P~@{#@:nGb}+RRNzp 5 vlu]3;Z, _0%Wrt|W ŖT!wA&BbpLOׯexbl&^P!JB18,'Eј% 2_W#!y5og97GDOto~"9u % kRxdf&^@]b=3P;@b'ѥҋ_C١%co1 /loßdL}c?X>Rpiv#'z`JPWy#c(p/ -p- 3RL >ފ=  A{MPBbx{`VEs4<s< ( %ԿI[}Td?8FI3sOW]ZG!V9^%Z[Ϩ Ga[C|ˀןBu&i}ϟ-ƓM43maՇs[{(rZŮ6`$A>QuÆ+kw.I9G|{K`!eqO#YGߔ.L}Ώ$n~Iu_ C0{Ƿ<Ո &F:2Z ($/үā L>%a[UT ZL_\'*1XO_uERi6u Mj( MBWz'3F䐨T ~Ǯ)f%2 (7gŇF҈u$7VP1XNFNՍp3@ۜw/`HCyH̟%ؘ\<`N1g%]MA3? , hMxxS;{{d·팏EZ ynwKmq(ȥ;+b"~)%|-0'na?N11B'_ɏMISV!3~ q)?b5n\)W2%?(΋#qG'8&Pɯ?*<@0CkJ$+ rfFVg(h##]*b98cO<]vw}CD n3^wqR"#{\Ue b-i_ )d]8"(V`f6,>AX>"1A.n?~*d>sš2N{ >%h56ޚT P\e!d%0?&:yI5}m@k*f@Kp[ סgwMLW$j:"Tx%1d/']o d3{0x^ﭸMCc 9bu% @{iP E*GgUX&{(*w ܞ^*ޓO9 d2$PaXmtpPS$\A̅.CHjV"N!l7p^&t5t| ?4`C䈁xFXupU1N&@t `uP* 0;y:j #ATn֟s\}݄y堁 zb&~df\CQ~tϿ$ ʓ^9{ đ ½֠,cq04 3W*ƠW~u?'~(w ӟ&i@zO ɈPm!JH~8?fT|CgstƖf~må}DB#]t45_,¿S3!JE7z=sTAC@]TbyПp9H׿~(`fJXDx˅)hB7&iO'`'v|%}h6^e \ l=po?;rF\߱7-$fbC4nWҬfA|%#Aw[,ug è<{9D )J6@T %0v~%EV#P˴/"a(ĠRjUD=i~e _[5g? _́Ú&r~Z^NT-fO[ B~'`?@L,A=S :R1X4T \3%&0,_#m$³aϻŘA"Bl@@rH jo VFīe#uS+ Zj@(&܅?K3n]P.d?.ߡ8앶xlt6h?YNs~ĢT)k:4J\>kg!I˽eB-@q $?Q4càX+PyWS//U8w8)uvf?ٚGk=Y.JW3}:^#ᗻ_Z/á<}$=N&~Vu;.6pҸ=&ϰ_$)C*x"#8:{k@ GqgfI9Iɺ ճb{ذڿ%˚w S1gD3FC4v_fjd|wdB ^9әO yɏNI.HEGdUu6&',GZSOl)_jtp!/e d)b* YODz]LVe>ܯtpM+ze~Sd8!+_yFbyFQˬ*~Ք ׎~ ~\@ ~o_97D!`D'.4y 3 oc^!l42/h{Q~# K,᤾HyrjQ!փbxp՟G?<`9g7"CnSJ~8fQ;`d[?D`*oTqFe妜 cYЈTms𾷷_|b%D˵HWhQŅ*H7^(iY宰Z"5Q`/X )I1e\L]TՅ l\8 낒E)o|Q-$.%;!l?Ma Wks$_J+͑6> nKxAxFV[I^zc\pm4WyDIaZ9o7Ǽ\}2P7= {Cɳ8n2EK\mN걖k]Pֶ`.+1;0VIZq?!^mR`f/C +( kWG%p Pc@tG@}R=]u$| `Hel6+ t'Z6ItPq ABջ2yzz!y# uD{G[k"؟`B?O34)rSo7w-)ֶCj1/hoi,)CAJ1a{]R^vU'r쏥sĿ/5c*'wP6V^(2f~ 07IddˏOґ2' tރ([jl':~՚Oqť8QLa}25C "*1qīhozќ9&9?Pn·Ś.]H/b;Nr_5^-H!Xoswn?xӻetepxE^t)64&zϏ4ߡ|ǮA1RpgpOu __ίuV@$H^ /^/$`^ Q#tz=@ Q֘wLd`<ۨEe@ $.`$ ب`S&v`HW󌱽UΚB0۰M .FbjbO/(n+PƂvAQ|cp=Az`䤱7)~MAo1ch: JV@t@g(k1&FC+~y7~ Shd&bԵ|%FC ֣Pfj9WIb?cW !Y W7#^Q(ҡjSj1kJayzhW7C|7~ƕ# ٜ}㙁A2Ϥ!t췂)B6F|ϩ x/Ȗ֒A2'; TL :rxz3ܖG;i?e> F}~-_\8Cq]+dȅY#^|?ѷ{+-otUowސ}F-*Q,Ki&zJf]bUG}, &?v_TKib¥HU/׳@pP`@ꋀ2GConVMn MoT@E3F"hZ{0Jݛғt) 6casNF N`0n7g2Sս>_^Ɠ!O~I.T$qk?DRPZ2goۅHٴ@`K0%tsЍ&:h:vL)ZKc< 8Sded" \%V3gKy@%)k dn2}1&~ye\>B ]x+sٿQ>hC?4d*z`P`v UA@TT(E;.B134f(MOJ*D] DO5c\eX?kmx q@cݝ׳CAHOCCe2>2޸Z)Σl} g ,x5&jyGx5RxI GH__;l9sMa;pK3k"@cS:6?{7&Sm:Lh6?p,z܊3?OOIʸǶ|[u؎}PMAe|}!]W, j?] Rg𑌱(h߹e)Jq~rVdM5G2цe9LWOq.qj Ji 7I*.!%J? :Vjz9O̲O*,0ۯ(-J^D"h|޿Y*5,|bQ33̛` ˷ƙ[a/bB _>\m`[: L.ͅҹ\HGZrGw!w)uT)|Ԏ$|=-ˉPFebm/+iFjmhPxCzn7sKDKf^GęލN{9t&p}$N59V[%㛳L{_ 钀 G63;]~iN.s7{{wFOj@Ps&9O([# vzW{?b<%U%Sxoo PS`0I=xu+a7+s:Y<{dWhF,0Bx=@ۘ//[AJ Bl,Bmu;20\WU|D\Ǫ+ɿR C~uBڛt-m C̛$gEk0 piH1אARs8%'ɕg`-~0-x J;aAzC A=Ǭj8"nDF C6P0^ztuNNQvλ0(g R*bbohRUW~irP%aF,$ⵏ&1_(xP lb6,y_>ޝ|~w{+"[\_z'k *&-B kCIk\r'. ++!Cԝ/̮ϟ~W5u%FٴUhrs{#` x{"˼G 0"] ~w򝶷OUd?TEZ{ct!}dq @1|0^~&,6QJ(jFޑX$Dx$(, BK3{EmcR9z3qy=k#P?U~@fQ0 Ģ^/Mr_Su9-_+Z{+-tĪ:p%r FtċSj ciVR)i. Z{!v {[k%eN^Pjo~de [kh1GD(yBP h ("\xq[eA*'ULꜺ pk\+75ι04EYfn?99X~1[[<$_K@CO@}NƟZ45NU>._fƳ)ҩ(^h;F4&N0p.r*ί)3%ю;6r|0  tP2^R;jJ#Sl*9oސk B뢻p3Jp"QBḄsMjIk2I~~/#t nZaS~2ۗV f4w (O! fƒ<%BU:׳L9oBLWO-5 BDΥFA~EZѫIjgswޔ#EH l_FWR7) /jQ\?fv&:쇁F/*C?97o,a@{+ٌ*gi=OZ`}DTe^ :+PS -r!,ЗѱPW"N@57eƜZ,[)ZvGozFx҇?Zdo>%to I˾s zd?SaﯰMtWD3u+I^J=Y>fm]w"ΏO "-԰G:@ȅ5187_ G~r?_??O̾+/[Pt 7y i:;ū?3EU*p,gł[M!:^0HAy㯚L'J')0$7O(ⷧ <U "9)w+nYHdH±(tE|4u7.Q3axȪ~q}~(% ǗNX}EbA|d*]xZY+#3^&dO^"[3AO ^~כ`My)D wc/g?ϩ絽qw co ?AqSFDtl!S Eyyu^wMr=ҨOm H&c?> JqT<gqݸa?gdPQ,;oS1X&RR# < GIԜ(weˏ-lp*Eߺ(KW 12 kpROwxs|#I|~;=&KHg>3?1 c)rf$t);m)9rW/GfOϢb<&ɝ[7 z4w|BWՐ:$9!Nꂕ=d :Ȥ˥J1&WMOFOd 1ogaY.#jcp+jДđB`gGJސ8dN!;e7in}ˈ AWb:-aÙ,>X"mMP ۰7T" W#,s$>}&Q LՎ Y/g?aggy^=glo0;2ڮ :(y{EcwV'6~nxpqjN-m@@@6H% zaqʿfmRabڛh%3**g^?WYXy;E.NwfL!P)&iGd{m7J0ã@xV3R$K zi~ V?/Lq@TpP09/;C=P.Z^ !q\4XcMP*a`Qzx [ L.ĥ; :*Aܪ(z <5^MO\~D%?;#8^m[F?xc(8M_s Z̙b\ţ? BT2'Huw&hF19$rN5j( {ퟂ bJFlY_oDнAnM.A׋'kWT8g{t}`}ްΠ; |A ho5I,dMЛxA(PylFtɉBn,DFnք Ai$. 5L=׏C~ƈ']kq6ڏR Au:E/M꘬bJZDKAg`9a^r~^Pno!m?o⯂I) R-:#0ыַBp Z21mBʴeW]ETJެ;d%ZyM+7 ~0k &*[CDŏ B78 K"Jɝ@@XUapr yU? IDWLkoU&B8], ~J-\72)| l ydNSlMQʏfðOr$8#ȋʏ~D5+xՒ>Ќxf `vb&<gE4!G9.#z̜,DI,#u:2!y}׏ue`Yzȇ$CqiΩ W ii)|5 ~Tbo-'@zAGsMt"PUf!,Z.)aI>VM}jKm&&JɲVICFa>uhJ BǎPd?Շ'8~X9Cž3|knCfP{0M6i(F2-`3)HxtY|^"=<}Zj+吏/qo7ihfœ7 ahvq[ĎV9W~A4&K+ܔ>>4/ ޡFwmS+CD:qêBI ao/$`[{ͧPɏ*WTI2Uw`9qjfɄJZ-;?j ̬+##1z7h9ZPy⍟U9mঢ় j (OQiH X)l{c@"].7L& m@ ˞1 ʩ'qVo^#8W0HUк܊O1PqK82^x=G, 9`L{SX)b^]ڿ"PmDDϥl%˜ x^D( ڟvQe+6Ua5v0~ qNi{=( (1p}1ؿ?ߛ͆X&MGL9ےz'V :n5,3IsDm usp$@m_h"2*M7{i0)pb/][3WM8рhlj휳jU}ibI _Q *'yMz)cI(-_xFmYjo @!6͓~$TڴNr2}j?F&z`5l]=3zJ3g\=v5YrR Mnoz=V%N|IgtFG]LIG~6.\/XohF6/ p[<4cR/ ۭk oE:?&u_a,ޏ_conSUzI ;!o|vh@M%'g] b<#`мaiu2&*nx֖qeMq #{%J,,FHq71G2p#P/akhbCXo2#C u{P1&t`ɫJ8h#%&e~*gh@C CvNU/iR}O)>ۛO'myv4!Y dS^H juA V)< @OIm]qM8`WZx_(Pȇ-bz{H{ư|TNO|=S=.%@1\W~ ]W4n =IL#Eꇕ?wy(q 0!b-BNO@RM?WNc k>Υ! I:?:Ͽ.ChU'Ǡ:GmoX׺0D!S!ۘ[Hè2TMA4.>h3^R xK#:7oB ^yyE _>@pP,#4>-A@)-Kڋ,@ TY{|,W|ne[iޔ~Oj3? jbo!p8.C2䶤װʁoo,? I 6 tމr|>L{~FPȠЉ0sh&sGdIb 8I')@kҬg9۔ރdHA˴KryqxH$؇~FKU{2 OMf׈Kh$dqE75^T [f^.#Ɛ _!#B:Qd?E2pdkhW8CLg/Z4&(#&kf^\a6}̇o)G(# I'λb>DJ@r|7je{;h/ؙog3 [wV:~Ԭ'G|)ǡp+"e#> D *2Tg9M)jϏf8x%{7J0 !M&Љ үŕ kU.,H@dj3b 7((>ri`|HHV@) 7jQH1>v@bǫ׿>ZTVtuTTjr#Ixs˄1+_[ #ױ7 ky.7q픟jКK~E2!9,=~&E6! 1+1 {a LQ&Se9'!m9uU@Y (jx59Yw% MVҋ#b2goz:`?tZ&.Lb5IHn24 EFI:1&ijE.ci9?Z¥0% U4Gcx%ߙ5M_5-?*C!q[)/&tɶᇃ?"f]ڄgaRb7>e:h`<sC K n痓v,$ꈋζpCK&⟇|rL9E*{UxE"pƸ 0cغoHGE2&El&Q/ӪXp>xao2ɮwIM9A2޾XE-)CXג[ֵØhL?rh8*#rGHF7H&֤ vVIjY.\=1M_g`Ø' z )'*g,[1(p5&PT@& V ֒[ #.o26$78{ QW{[?g!QM*1qh`I"p K)^Ŧ{.~-M\[بՔPM3i޺+&gYxjIBӂh1>$,-A?^ӏof~m ?!6֨z R`@;|SCfLדa vIHG9I&y{|޸ x¸@_PUQgugaLYj]xPH}EOSb̨q ^{5Sqphw-~pnV p!8Ikױ咭ӿqC"()!{M:]v)68ESGnT#3՜~MdkQGbAoNTZC5: DROA*&0&c yMbopNWIgJOnz9 Y`ћpdsu9y9301Z#~'񌾗6̂>.MkMCdLYݶ2ƞgj?|#uE$H/?a7+HyKr(<_ɏBMbtޚ\F;p|g{N~#bA#L i\)=`UpWҟp4%2 B6K0A47{}C@ 믽YV|rf,!#;k>B‹,[􏛏Hew;3 aɈ<_ުƅJ Eas]1*\lqiT۽|@Nyjr?m0蔹[GIFcP"07{ CnIOFx 8Oa 6S!Db~dd0#ek)k .$ |޵<_1e0맊X?QcS!OX{$Ls~#G[# a Z,$|CbTC^SlSPw vA De(I+Ǎ/,& Xut pʂVT21\PK*RکڻmI$K,`2Ln9/ݑnbfzr՛E}JB&)(m$׷412?DX&o%^<:%CY5ضg ުY'ś'×#l~Rd^u\bO!)-q6Ђp 84O }N<⇚TSqڏgqP,ɲ/Q3@][PFzyܦtV8 oq{ cb Ezp^iZFMNǛ'5o (MͥVaxHuG;~899PJQu~9$9lr6l~Cz,2 ~;N.B!Ye[^2ʯSƏzA! 6;qpld۝_8.gw*_o#kgIvE=Ώx̏l^e[DLQuJB$̤v/5 ǖ_C}{?-EJto@jb4 O2K #tocZ&q R#I)JbF }i%8Ix%ΘGKiO6\Vli8dйm IV ml-1&~]tۭ/A+be!ˤ" v(L4-^ ol+ڬe:Fbzed+0^dJiT>jHy}ũ7b 7zzڠ޲Ag6 ?w%ؗ%jT]W-^;|v8NFB.0FFa:L{~$K]Wk$6}Zu?8AoK~Dsw)?Bo7H J|J`Z"( B8ʃ^YɕRbmL`r◿[e3_rZv->}Nr#mRC<副]B_iY}??V5e3MZ\ G~á9v;39{]~0$sEϳ?p(08 o^<TtݠYÒ<6?AGg 't8<s%Bྼ aUf!𹺏JNk?P04wVSF!A܏7+gckgGLg ٵTh`W,>~H1 !"s_!r8x *|>s\_rç ձ|\?OEiX}LGD ū'zt&GvP371GOz -f"t򣫤`5q/ ކK~|m ÿ):_1ި)?z&Sd IhERFYHI02hZ )Ԅ|9\nR؞Ɋ&j ^U+qF1J|YjbVhʊ5OR惈fʟ$S&gFLj~<2D" 8Xgi6k`Վ~J[}@&&S,8߿.8ر.Lc)IX2`l)x*GhVP#ڨ]>10Z9^wq`L߉ k ~V1#o;E_-$O2lu*L{1es/C=9+˛vJ:o펱.e^ؽp Ytje_~UUF3x$$/x \,b>1(x6UTM=H携>tAѐ#ヽp>\s JcP>h<:$)5.~s]Nǿ]I+~ h1^`C fYv(G;Aqϫ^FXwSc̙_ JL/\raQ>B7:'š}I7S"IJL2 ws;X~= m"#pc&kWc5O|::8t򺱪QGf %U(I/e^'>[Hf(#.W< ƃzݺxF3ڍ;99عX$exk )vN%vi8A0ex;Q;à!s#~s0Q P*m\Dr+J&mwEbr_* 7k??|y~Cx~ bܮ~kǸh:3kJ(!񅿡|HdkGy gdG x9>Iqsyx Ly' p /QG0/}"4$^^37^w϶Ԋ=R`O9FKPo(^ϟWI0z@ҏHjaṕ|mϔ>hF;o[zuautYO?ɘBD pͱ CBtΤH9kɏߖ.YVOuZքH¥d:gt7Oh>Ҫ6sH>DB@ cs|wr tLz5Z y%9?ƽ_^EOx &pzѽih[m7s^8>RE{#pF7>y& ;R:_FiiOi1vRϺyw~|kX7ܥQV'~02z,->ts&s78?.c=6Xh7+_@=㳑@%HTf?ReџbPnjH4xmpp)(ިN+tT !Ϗ;֖(5wGErD' >>Q;e\?;el:  ЁX '5tp ޑsT 9+b2 q F0MkQd /Il802? kwa8\Tk8t2٪k՝{Ć1 b-ƅd,}[ /MpO׷|&7],,̺ut Je?\}9'{&r&RW]6q BԶMwXn y ΑbVjffq<ƏJ1I]g&/ !vg֎_/67!/X89H\/w+QN`{'^aTr))@$Wf^^~~nڬQz{~lQ9Jx q͊+=Ig?mㇺЁv'%:-[1|(^)GUxHC/Mi,K_]m)ޢe"~ȫC , Ξ*[s}6Ƣ:[C}-=f?F!vS߃  #!w%Kgb-{[/3oG~"}K&}e+O 3$LzT"g$pi:%9H_mNB~m4 OqAAQ WCbQ1AEtJX +UGOJ,5og VL۱ʑ~g$6p&B1=qH~6Q|l3͝ނj?PkW8T~6`T0}z? 30;1EEM|@=O{,HowN,x< >Om av1~@N>=?]t >k=%-VDm>x;~Ǣ =4Xy/GEr 8?*6t$z&?N"9 \=mzuMGE,Yrg?/|'=?n=ϘGwocr,Q**ܔe< nA㯁Mv/On 6%FR EY46/ڹ Ua^Ⱥet&>~g+ˀ.smf%MVvMMڋvT RM:kXtWa!IV<O oq>>$I{mM(R(&ԛIqGp^ļ6L5v$94()x+aVJY3ζ|ixK3=PCOo ܙB--^tpŏm`a y/zoG0 㭰j2ߙ۔M/F"KmOjQ}"{ЄvaŒ%+88-#'x;4R{l\%~>7p!/)GC s)t<)<F@&x+`z^1!>Ko w8Fޕp-x+d6a1 k3e /oa϶0\'G.PD7Һ.JW2ŶVD&Gj 2|%>) [TpA@QXO ]}!9~۰#`E8%MY$j#twM|˩FJ!FzrdDޘ3ϯRqlswcwDX}Hx`9r^.^h(6ἊIK= ?M/}=YB L!~-^B;MtWȷ2$leZ~O}*;.`ʏC_m2<4Q7JImEs~UG^t:Wnʙ[@jU)¨)!)v3 &> jp@V"OaU˄bƀ0/ҶFDTA(Ja@oxT騂-et{modn'tY+޼4h$@`pQMƓE4lPw1~V C_"^3l?0sվg@N~5ކjyƛ|̴@zसih ~& }%l8Ddlp)0 5?7;w^><'SW첬ؑ12>ب,jZ rxK!;ُqMJy4*7HB|8^W 2LN\dՆzZY]q$iaDPp#mlT$S2~/Y{z~oƛ:b }V=:?ZYW1<,੯ "9 }CAJZ/";JTTa"6OX~ɏEaUg(]85zAb.|? dvw2_Gu~+5UxEK50Ӕd TU&&;Jj3:YgKEVJPȘ6ޓrd_J x?:7fdԪ 5Io$z񌕙g~4hT$3~\Y)Dg/ '/@I2^*)qzQotpYKΘmd LP2th/ݑi،HljdzýHD_"oEǚ?:Z%һ8~ {\ E>K\@pXVfD }rwٟ.?7 ?d,¬ ^70g*QtO?\:^&juͼw4Oyܤ|f-YdiV,ٜ ~xK }X-N}-J wrܪԋ[-/5#E,Go/OsAu t w~'RrL-]ZvlfpMLXbP0Mm+~*: Ɂ3pc~G~yˏLa|ǴFZQYiZΏw|{D:6E;)Z\gO/2bYtfh4RmϙHݽv5ˮt ym@\$:t 1fbF~Kt[:JFlo;)@K^ƍk2y qťً};ZWL~o.Uu vh_ >?rJۆqxSƕл_&uf k"iގBͫ O_tϟ`VEN_ Ü΄ xD`ݣ+,k*+ޫ zI;=-cy]/ 1>{G)h!x/ll^**^Dh a.(YEK+y0rEuGЉkǏnG(t/:u˃j1'g)Zb|;Z; D*vOAS،@CNIT~f:֤"~~%j-35u-_OV1ï{_o6xKfx ͏6T ׷NV]/|Bb$pz{)v: T/{h4J! >&0zGi4K~f4>aw"пΏlfȽ}KO~u |K9ś%E41`W 2_R=$w<2IC[ON~e)y/F<Q?w($@|So5 $8 '-J~},$Ct#{R8XiGdy>QS,4^ gNm(jbX|y!09i~~[/=gH#HHLKi Ձ38~9"cE/x-QEӠ,H G[j8Hn) :At]4JՔ(l6}z澞?]ޞ󊟾'5A͎=X{+5+2|p4_ݵُk xN9~ğG Sӕ7$oPcʒ>u_%~D((َ vXmM m_~*9&)pCXO}Jy(ܶeCߚCP4t&1!xt[>RA3*$6H~4~*} GLxf0]}H&̏26cc=RYS)686I yqh|s6o[T@1>f>OICS⛜4 Ldhz>S#U埄$ȷ@$b /')Ŀdjo?vN<+~-yL|̐'njLXF`.S}P}4cpO X/+j6 JNc|4;X)>?Oep?5|zn 1Nv2Aŗj1h~6̝Hq+#0XRDsq.; J_MT[~0_G||Oǂ0عG3 =?RGMi@%H?*SEO-`@cḯQqxdSzU|ky8e.Uqr<ьM6g%-+2ĖPm&fPRh4qpM}Yq0_F#Y4 m)flpY[N&rHe!Q>ipw881! 3‚ ?W/jy.>;2rYIVlZ~p..P*h)ž;Df{?-^7x[%  KW Od? F\|H:eZHϬDqC$ r8)\ց|$_wLtb:aۗ u*CI= LA'|LIPHNXJWȪ /-AjFd/i(x˯xU~ B"WVR4)|%^533޻g5\ʼn K_#6_$ʘ#q}X}B+!p$tj!k~&zFʑe[k" ~vY_]ьWQ'}-țH?<)/ffQ{Z6`^cy0q峢g<`EfRʂTQ :h?ooH2CbV̈́LV>!${iK;0ɇg C[8~EP_g04\):`$g(]>~2 ^alpG(y;-[xF[fեwtyRH,hY|hgQނ)(et~Xr`ئ}o`%8 B "]>lEoA0;%CC#9D-w&sC۷+zCcYEo=B~[3-~= 2S3.,-{t=!Ø޳㗣´dT2s8ŰS$&p(>NgСf]t4l%R$e4b{R7P| }[-!z)7į>/мX: j۷o5kl/.,alY \Z =m[+2I5 ?ȼzHoxk&yC j„Fv 6ReM{ /NaP HXqUoΣ.b j^ˋBȓG#*) Df#ނ覒RF*-F?ފxW߭~b_fjjp0xD(IL\hfX3x[ "jlxD~nηF~x3mJ7ޚI8&{#6Qr?ūʸ ?=#٠1p=?.QoW 0mGzlJd&d)R nova1wfARrvDȚahJk5?R"ز~O,9>\(C~$ܗ3= e^ܿb,:Ul@sZJ.H/Fl=A2 ckD#K|SF* .ƝF^r(=##5DZRSVɅ*r-UL b+=r4w1~A䩏VL5ʇY~hxdl oJ:cr?{cCgZz!g$l_ãytBf"4|tz%sp =|=s[ZŮ?]:^Ʒ% 5sj33:(5f\@]:BJl-&/~LB`nӱJ`P"YGh-Qڒu'1= dc?`Ot['eZFwk\@ Yw,pw x3'zzZx^ͪs?We_a \Uv%dh^崏_^%ENAuTN?G>[54~ТzѼ߯:E nZžIAExyXԱSu/Q 68r$ ۶drQGuGh0'!$O͸}OuT< `zs.T!8<`B۞-r 7:Hы( cd,LبG6(d~l,%aa4X?= IrDl6WU26hT˔QG6pOYB+f4+LgƆpU 1D<0Ԇ(y~PSL]W'B;lX£k1H^B0@1K1/`U:8'Ix,nqpʍld-.bb\QC1Ÿ^`by##^~}Y[2k^تyŲ36@LXJ{Ⱦv͕ڭ-^McUС^;˖.C*YT0u{ɘ, awdes!`w= yKuHg$ e[Gv ly@28.Y9gLoi>ǫ0_o~_XϫJ]O_ɾvDBY3||v !֬G̚%x[Sj] a?"QWr޼NUX- 5vJ c )/+* 1$K;O/ +וZfN S+^pKtg&B XiKȰ KuE]Obp鋼K$Ӯ7/dg/pǜ+)wĮYǓ\lOG9/#fuOI~dKјV$G*C$"] CpgJD>ž&BvbP ^$ߋ/=%r Aenb~~.Z%m7=Dzx+>Gni3]e WCV)`Y{\ ?Mnܤ<P=6Oso^$5T~6X "꺃<Eҷohyc.!<`oS?]x`I\󩕌pzR<!A#K&V.Nڍu?Zcpȱ8J\CW({O>oWF=[!ۨ𰝡u*& &*`FP}(OАNN?RZ! e /֡c^HjOczkPC.q.'I[;?ǁ/4us)RlhY4:iMW cRzƣ#|4y>><|QM%υWokc?Ϻ(-frη/(q  1Ĩb'5Û #PNsLÄZمbW{}w4.[)ZdyثMxc}N`8J(ϷIh=WxS)*YV&z /J^8iI6b@k 4JeUj[e(c>/~<+J5?<@/xN * ~@z@1; >y*zzǫ(7;1.?+pjch=R P"Ԇ7_.ÏW>"|KT/0Wy?S?lj(z=zە-!շqH밧2ր 3۶i2>m<.Q`(*ܙ_ @i]e_-lw _!?bK ywG): =?xoz!ZUU/InPJї;(b3E駾ou7ht)M@N1uX)g!-_L4ܔlO!{Ce֫VME}WDIYCQY=]Ɏ8VcbEqtW0Pa H QY߿1?zFwoB嬘Z('t`p_&oV4٧WM]m,pmɁwv?)K*k{4~ۤ\/J~6K "Zf(wͺ+rC|?xxHo݆e8_ - 1K29'Q9Nj8:UlJx WNmxwii}ylX>"5|ƛ0MN.W&#EC2h=״Mba~ c܎H?g pbh#?}.9ťJ֛ӶVJu,l0*3Q+r49e6>4a]G%R?[*'}P+[x׭3԰)xJJ?`1=8w#R^# %  c a8 p1abjOE7SN az)4뗙SVf<;2%~S`FC% m%RikxZVFK6m9Z5tcJ2"vb}~\b!Zjy ;bA[Ibś+[R o3xn.axCmv xs/z-Xa= 4"jpZB 9BZKS⚲mNƹ&սFdzK,i%J9#MM} yM*dtmQ)G7`u._vtI˛:wSALj) ފK*tmDE?>/'+hN,nK`kD7rT{/$}s}^l-s~R[BdL}>[k%~ǛQ[4&&9?"Q*slqm /(rU~$d~(cb#~n>бzms_=ntcOMNS#WIg%{`##:`zA]򝄢<k/ayť h֫I7 -1qPsUUe;9S*xfS[1 E!@pEz x]{}y7w4U;.}Aɒ?:nA G)#Ͻ<hY:$|'|ƺZ)5Nlrآ̲~N@R'D:CʎIyLByd_фgϣ|KhinV0pY&u,ҡp1(6ɾp'2FjoV2V ߿gWU ˸h07_ &:PAܭ_)[W?aF|%+ūIe>%`uzhW?v Bg+Pir.k~ĒyXW(*6HL1鑝) ̯ _P^&,LX8 LO9#8;|^)GoSShQ'(!ǙW_%/IͩM"uA9VvE?iSuHY @tc27)Y a'p[p`KS]at$-XncKYHY R@4 w0y&#rI{a/}]2%2Wq+~=1%[M:R]', =MB ?m /Kt^ZzTsy+iT# cc@4ǼK~g!o'Y_,yU2@G({4ެTT1&7Qqs 9}Fp&v^3~ =;{]#/^Q|ۤX9״RC/0f mx+~JU-jďWo@ 4+tS*bWu킟 od C$N)Ce|"81b }h3DeuxD-8:_-uŠ}l?{k~4 lciym䎷Mn1&ӝ6]JMBɔ1t\k3qڠ2+kGY3Ix hW27z~},pM4'\AF sU:I$}WWHBWӏCm۰Tzdk8~<3~oʚyy~$#A" @}a@jL/(*/T' 3~bvVYuymOk ϓ}S \:yb1K0n5<a"ml3c4-Dvw:N%C8+oEu#yTMo ZcXt y+e*w ?k]a.M GFەlo?Cos) 5BY%ǓJ1"Vz+~pšP2?6'_)?;5?Irq"ފDxVB] 1 ?7鸡Ǭt.%<`|~Ot6Z0~F'j)Ņec1ȫWLb%9Jġ/8Eޔ5X>~'$}}N*)+! A]|VN`+P)6aou_I۰; d/M=O.,m7&m~d RsN\1<4;qDV.t r^↤0>wP9Pn %{W@~PMK~=X5fj(ZWߧ5tda;?TKL%$%KNfY?Oh%O(ԿA;WS#tʆwGOC.;~|f,Lj 4D.Ti{m.:|_yu'oaOG”<QYTe*V;yKMǂ$ǫ"tQLzÏdW/6@$~oWn%VZhzӜ;e>:>HX v~_G=,sTlQ/wkIu:v a^= 0PUsl&Rē eONky%jPt#a!+Oh/KsvMj`KBC3LmvYvKGHvZ^$'&4c #ɵ_T ]mT>6oOJ ۆ:ͅU^:olx』J;~TX!^^Fo A33T~!6p4fv}K# S;ެȸk=[Q1}JKTVdWwm:,L r{/pI)3~7qa4 тRzXs!^+ߓs7-=><)q!'?lߝW[W4\bkn\UWdR=\LV61í|x1e5%VSoGWA-zXw)>BRx~ke¯lAo["hyC(p#r\tS29f31::<2OPπBdsMMɞIQE,|B?/nY?V? <pzF۟.eQ%'Zb@/C>xY"ɒ:ܟ>cH9 >-{Y#\́&GT0'i??C瀟) F. rA\}&:%*Ft{N57-_eVp!)~|x+;>Re ·>z O Q'U4{iܟx  /Òywf V o?"~nQI-/NXrH+]9?8#=Yzonjb3#'~sMdw_!z2;pw43S4'j\*SD+G?1H2'^e$<d2r_wG|H< H xp*=t <| w,:b?zƷr=sk`y]'E}I^XG?|GQ0fnqG󇴨;M[\~ ̈́[WH[0/x P֕6$p7AMwM,ņ+|0:2wE{vd&R"My|3m1VMU7* i>M LY/}S&KDɡ-dM_O"'8_bY:1HhC FH[A#^g^mfyʶ70il)_eC>+ƻo2YerTE<&Y>11 = o8 Ŕؙ/C2o'(V;~l2ۆ,9K64U?4(@ REmQ 3xM }@z+ޖ ma$2%,uOLzܑW(0~"7` /C:(>u\}dqX-*1 zHwV[ߝp|.~"V"mz+hHyz~&|y*h PG9}%/sb}&6$=DCK@ ȕOAxɑih`Oͽ7"9 1y"{ n tZqĜbw*ط#5(^&2 vNӤX'J_?jQXcH,vh=`4P!S9+%𸦆 J_uL?=a Km< yӃmgg&FT{h4gnY _r|pjpo^ALF#?~>4)º& WXᶹZrA]:|k UPc ʟn>Ssk!Nэ} yEs.C+Tc~F*^e ;ޢ37nፉ4Y^ oM(L& IL:'7\P>sS?4ݹ?j%PF-"tFs"1.oa/0|6l0Ex~]El ߁翬P1I;` C|l79Etgμ_'{|>Ls. Zϛwƫ# 69.B-Ek$]ycGy&.~[y;h&^nζ9%#8I1:R|jd7g/ Dȅ:l uv Ck}h5Fxy&zx 8Ew,.,,жޛۘhLe[RE2.D徧[M8(imjphc6`56D&{' C6fS6 vSY1mIooūx.m,d]UXV>>,p̰e٫U`&G *M+0 ~]+L$(aïTP}{+j15KAKiTMJ!&oLMC0amDI|DJA~f-~g=OtSy `2R,=g]?BwQ7Q]ASR;SFΎ#-iϫfS~W ߹SuZMt*Zs '_XD30L=d8BlcNo}xՍ\-D S&]"FvHI0C^tS2@Ǡ/ g2-~gƋȔr*{P}~ј8U. FQרE5F:p:7 n t6C'3tm6]>f;%..b3r /슅d=)x^9[c9No~Jf*~܄:$wNkύ7zer_ (~ #m3x|y^F!S8/8IދyE{893])xJ+~h`PyoZY7>TR 0h&ƫ&0oءM㿩B1t2 ~*'5 i|feo&is4T$agMMWy#5k= *_(.~~g h ~G'*衳4keLyWS]" f=}u ?ho)ҩ;hK*/x ƦsX|NO{cU)b{v6duq/frip(YiˠQJ/3ix1Y V ( !&l)֛ %lEFTB&]0so ibt{MSuȤ[UJ*%[o9 tx.(@:w*7>4(Td`S 3X% &.&ZA-Jfs83 x_~O5dz7*ѻ=X Lom6'izk9r?P_ 3=]m0^ƴ4a&%jAKW;as/=~^Qfu4k6bNl!ces3P+!cRU[ G % xyPJxK9*>2 |Ɂ(O;Bp*JѬT}&W!i݈bq$sНŊ}`DMѯwlmotûuߦHE)YU7J7Ě`^b]J?Bzh K1x |~E /:[,?%J H"pY*$SO6fґ1 Nt3H5Ifhg>Gk`Wnk[՟Y#sT~ߗ38IQ3&$"].љg15_Fx uwdI3 [sC^ڔ0_HIPp:G^`" ώ=I-tMI#P `V ՀYvEE&u-Nr>0:n;Yvp 1-Nz~T.mTCz' ٢fWJEW 4uo{w*q(쀈tŷL\6GxHΫ5G+J ĝ"xIQ$f_0ΎRl- R>eG)E O<#~\pvPThD}*ěLF?_QR'pcH 4Q\cmJ<Ú<4Db+ElN g7RRޞ}Tx h_ 5!)Ɨߴ2&K7r-)߸ k/,7E|ƛ Q,Aj.|BEZR 5n! ff}SxZ&$\QdAJ ok@>py o#14- `WQK~W#e |^J~ bhE$|jeB6P rIb(r@#Esm{ӡFx+׼H>^z 83\IV`%0HB8BM@OxO[}jMyd[ُF`dO|8 YN+ %7)*L|)|/*s9+y+Ilf>wLOyXmgl S`;;qDe|q U3{ /x~x2ج牜WfI}% ]Oҩ"oo#Ba`c[Q:v;~n@c _'&"@WG6^jQ|"C15x۞v6OWaq5M;Av/E"Y j;z2~LXDVS@훿ǏGK辛vMpB,7[m@`1rX##4OI>*8$Oc/x&3<%35*ѳ>E(4Vh`dS6q\;ޘ ꀜ#c|-+D'ĵZeĄۘ)2~ ɲFi2/ =iЃTp=YƨӨhQY"n3I^o|Gx^DZv?r olj;v|0$]RuJ9JH4tCtN/&qPVD|īϙǻK-ϟ"$QJdाٮc-p.U™WKJ|7&?͏?[Y&K{Rp#rFHݷm;H @Y@c!~O[w)s NgA,#Ah0JRy Rn)YϤV /i %r'*#LƵ}Md.ޢ Y;z}V ^$Pn~N&Ǟo#/:~tziɎ((OVyHBZV`j 2(ޒГHZ%.ZZHWs^āӉP_tԇ(!32H¢$P+ :^Z.YɌ6aR!xvtY93~Vv r> 1 .3k?nD^).N$&v":ܙsfޥY 58xbj=ek#pY(WeFO o\˯wBBcvHɩSժP|Q5U\[z>a))#F:eCGo*!_cV~/'yuT$v~xXˈj,㭬z^={';1^½G9|ogZ+2K~d,W/HA)i܋*Am ?־ui%E(dKVw*V[Ku2H;&@cs6L9rtJ{V ZNEmmbx{FP@8MQQъả?21 |a{9 PtL[Е4H{a5 v7pramMSrA\VLj0?+k>q&K'(Al8.\ʼcu)|ΐ@C.A_DUAq|b1/_wh mhxqto_/8)]a^;j[r睱yS_N_-x[l/1UUqx iH2j5Dοͨ'l;`)"qTȦ 4;#CL/۫ |S4o¼t}?ߟ_FqD!@ ʻ=fǩn p{auiښئZMJ ]X0ppӆFb=;iƫˉg~'_Nf^f@@Fӊ8z-,"bxI`}k~ L O~|jnff"_^$A5_8xcaHXO!eٛXx4D?;݈9kRrRK: 1[j/8p'ICEUqA\~oԳ( ܾןb@oϝx^q4Jݚ5Uaj03r,TX/)O ]H/!~{ߘFwnwG?@KěO=\۽?I~a# Ru|f8Y 9PW+B?p*Hw;X%t\ORKzoչS$澱۳[% ~KV7O6~ G߈3 w?ItzhRӏ+Fx`S=_ |*^B^P t#ԩv/m6[r&L="ԊzwD :e2i"fv9?}:귷  KG H2SZX/&h~ ] 9 )":=8!@, ~qjI:u%K\/K2l L2qwقKEST,<+xwy'O82~%aYFojG\b 11^(0䁀`S~T%$Dwws0"sSJ`LrY}GptfOD"! ^c 7p9̊l=]w܄R1Sl* !Mϔب vr7S:#/[b3)?`ʤå0cp# /dcR0[i9]?BL:q}dT$'AJ,hE\tV+Q7/)ݠ9v6 ֚ڈtwΠ֚xIdi<|ٗ^$.ǹr_D ^po˓ S?yy`Cp?'?u x兣@ 5K=CwP}Olbpvb' (; iD"nڦ* FJT@dzd~z)dY?>40o֏s!r?ws=`&Q":u? o~"&5^_ ~o$PC8r,YYo/7^BI#\o?@ǩ=?ݩq~= ^lx/g3tMS?}}yɁ^CžEe;TD傟R"Kpׯϳ# ܂<7ÛƫgzX 7TAsn+yQ4y3x,~Ni -yTTx_w<0l/3): ~2|ys9MwcWq6#D ķ|vK~L/+,3(̧f~S 3pJ!w5` 䆎fHUFG#PMn^/|UO f$H@M/4D K7,t\?rn7r-ဈ +epOUl&,M GC|q٬y4<4nCe-Ȩ88WJS 8V";@إgp޽a ?1}%D2XLL_J$ ޘK ?RU62o̲EPUie8*~f*F%T|x{ xF6 i3zWf'tPq|dJ):,tVb|MA(憟a*FhzW g}^1?$cX"z2ч tQʺLS '#Pq0@%dˆ8k@|'τ#H態߷t?8-*4/rF5G3'i <쐅w#,ȱOdyA"Ud_6 & sy!2>ūD-I\߯B|uIC_&,Z Wj*a8ѼOIL8}xp1D_H+dJغ%. !6D8ف S4 O]hkA$r [w^RhOb5(A&K+2,U<1M7? >bxܞ=霣%Za;y[^Ni(t5p%3NH(m V"3)y Y`8oIg/K݌̂M՜o` ՐeS 3P+P` Ⱦ~Wo@㒟UfT5=xa*踞JH`ZVv%x;C y(I <87fsF׏x>rb<"ȩ̳=o M2qd$?d5@퉮5(( ܄ kzt ":1_^GBB-J8p5  \6%Ie)Dak㳫ig L`k|'J|#}[oM@/n eЌS/Yp\_$:P+ssYU.gc4m Ek vہqZwd]ء)v|Je gUB| 0M Bm7Rb(`Ͱ\FxxԫEj̨[ѱN;X\.Y֩Hr/Q႑^! `kUiQaRazcDZVT#ϙr`XN'Y 1i$2 oob[H֐&e{CL֡/¼F4TT߄ꏣz.xźWQ4L@x~osϋ~謍YO_@mxp$PBΗbEgRu失UYIMCyZĄ{Ȑ`g!VHqał ?֣ kI}Gz[ޓ.[9?9#wd:n6(#T};d] wNQ%=We ie)x^xXa0[b˗/vkFuK2hbp6K?>NPj*D:[b@6wE*YՖU^"(yUvOd1$UyZQw %<&~㉧9cMcڽo[ĒbA^Ԧ QTJ;R)ܡ[X*4W*vݔȩZ%VU׋+) 0WB`*Pa~ 9[,;PƤ#%hTVG9W5Hsjz ??vop$9Ga 9J #ULAf\ MtUͮJ_j2^JUW~*XqԭMJ1)hZ.ߩɑG* 'epA%l h[+g`R- A(٠!]*VRLeJ1C"&cϏ)IA;Ͽ|FbGX.CލYWR5n-Ab~;_,6xF,G(^ Ԑ?E`x O:\Mhm cH2%?PII3m04&]aŠ&aiH7pW]`(*~،{GTa:%Fě# mg1&1Zn\'%zP YT^8S$6B4IM'[,D65 d~xc1V,N{DŽF1l7:X4:}LSnwJyKx xof̟]CjD{u,?~ǂ$DCE6׊DG#w!{Qv#E2o\~$^aK$jKM/_uy;=Ud(l*`5/~ {])zP0ȵH;xvth׭3΅ 7l.,=aS^Ώd1lG֕4KmDF  +}DŦp̫ka9A: @u4~٘k:G\/65p C@W2R] >BY$m\&ْ*:֐Pƹ–Y*T~,7[GNa{*O-D !k9pu듇EF$aM8cmu,SŹYq]Nd;S\+[R74}Ox rY7J||=$49WI?MN70WLv?G`$\X+l99+ ^o-"} r ؝ BnE"{V,35TA>o2xڬNa_voW\boS%࣋h55xh!@aSB+[|JKxi$1*4_?͏"uFJD J!D~\GӇ΋nb|Ddh=+~D y>pgNCeAOX "jXi[ӐbdP Pn{OO㷯Dop1;~ WK`Qogm6|^ʡ|#-}ҧ|_Z,5@~TLݒw ^չf !Q~l۳iw&Y"׋%č FX2YQC/6pQ¥7G^ YT%l,-/C ґjjcXFF81)Oiђ )裨IS>]G^^3mTҌiL<Mt~w|#)MQV9KcaIC) ~`.^~|~Ŕhz` 'P3f 3 |y [ïTykv Mv%"nVzh4:baηAAs07j173 $&\YV࣬o8ʌU eA ŴF oǏ,Fk m e }Ԅ -\YU F@sľ _!R9 {`bcf!EqOyf. @~r<0h(n6ՏqR_td^1>p&͙pخFG1"Q'Eʼ=Sm:n:vմ8D|9)Jù vԔsn\g:jd׻%lڅ?7t̉I^y0Sn?AU<>q>t' R\ME+8ŠcR1O2RD8fGD[X]5 w2v(ǜ~Y4E r /gHzRj~2eÚؠ~e+ ю1÷w.ױFvm2ݵZ1!LL` l֫ wxkh}~oWBŴ?A@`h5=LA_?׿w~zǫ y:Σz| sF.ʏǛMJ7j%i";U~)3oGBZ(1Usg0yg*?nF؝wyXā!f\L|I]?Y"}j0aP52[΀FUӷ3c>'~5+E$n|^4BŦt1kv%^9T[bW#aN7)U OQA s' }PDf ̷-j3?ԛ{w })]");wQMyK~4 )]2ы{ 5B&JNF٠XpwMqF1 X9O,N}aagU:q+Ob*R&ɬ":ȁdS(iEC?\D'M-uV:&t^#/bVd,9Ri[KfPg;.YI| Ne;~-FnM'D~^sC&? e~ (3vLo&,G,+cmF&#I}abv׻Ǜ+yWk4qоYt 4x u\D҄-Q o,]:THfӯ >o?oa:L ocώqMWW[8C6?FO6#Ds^'3.{fJaPї6y^ h ooN Qˀl(VK3[6|;24}M Jg7@egtx īAs# ;TTyRShV0wy k폷too &hfaЗoFMq0BPt(cY(lS5\dF@)j~^[炯$j\ PtB&>?krT 7OQC[›Նp5v_櫗1$-kSEA5>/>;#?h},4_+GfWןG+MPܞбZp|P:iؘP"T/X:% 3vn߂,#0?,]8DϝnnĂ7> rƘaLQk0ǤWr&*ae)]dOA'؞9Y]V!x&ݯbA33vZ 3fn;r B>=aN'l/g'FֻeZw Ev؝,]Sk^"CD\4G)=r%[y?EήwaH4(v%ˊEb'9 Z 渄?W.^]hTtM`iXfR^~UIFy;cÆ$q78T؆ &tȞ/#IT_z fhe?I^7ʯ8ǜE-VTrIؾK ۭ@X6,0yƊЊ^n S%Ě C!BG9a.RT巙{W1#0G#TGmK8![cUWgzi| 8{=f"%»KcKrYJ㼌 segf=K uݻZ MČ8IcXxSPҰmzd ]MT~8I4! fK;ZጒI3;_xCTp}1Y}^N44ڂLLInf-q׾WI~ ґ1b B OIcYaGNCXK! m_Ф؋eNJgcBǗ6W`1#_n]Cnb (Ucv4p̯GSh6s89/eq#U3;S{#/T#C"E &v[ٷb{S>"4<+<0I&炜rTQuic],d%l?}-blT -T)jZ|IpqkN뭙ÆsLϾvnO,7x[R\â#<1GF032bxSG#2\ܧE{8ܷar%}G;nbp>>N\'C ^cUB E_6oh } ^‡InK,@)/fp?S.RlT\{_3T :C?qzrYVY~ː9diC8%\T'Ќ"x|iv9uO,7kUX %?B#\a. ӻVe@X3g\ r Y}v?pfm+D9$Y~n9zs\OCR.J=kCiݏ? B?aln+ {wVund,ٓ(3'3;DirŸY^q,IDFeaSFWsx^dhǤ] ?*([@!x&,;ʂϳQܯ`xdbL}VbԃZ{%) ~hܥDFRŘקn$7t3"Bn?G ~7*&1lhK vxdY[e)7Yn>ޯ\9Xl鞗Qџ6 ׎0=aH m\7(.ی\N鮘~UV?Q0n@R9 d'ae(2h??г~Nc[0qhFN{o SQ,PL*\ 2zV8]1xD~e@xox$^Ʃ5㧞cBS~DEN;hb1n4Qo1NNDIJ!]qHLë:{@Np ̀Y $q[?$> DL)64lRfǀ=րLz>^H̯EXL(qұ>K &n_. BSŋdӫRx}UHf-ߛ~tKgtZ9Wjrs{|WL09[ACl/*O5Vh%0h_>!' T)QTM^TYZT#NC dЃ7Щs/#gVD-exZ 'aI7\K/آaOk@3My^1?`ݠp6Sa*=PK PMr3|b>. cHEJf+W32ϏJ瓟u⍴` S'K;|s+cۭ .+kӯ8XM좓?'g;,~vpnSJZ6!6/314V?qCۥy9͗\3 j̛ } N0511<~ ycy'q=sndu ǟEc-7ӍBm4^,y*b,o*,c\Ju?ɰ-۹;!`m):,~|+~쌌U%5^?"v1o]"Ј8':N,H|k& `~(_ ƓbΒf;q?0d_  ?/]ԏF?rlsa+ހ"[86FhGln߻ (^>"8X|y"`&^ʝm?g!>/jo[X3pIHYh8?a;s]2eC k/ >=1z;d!Ck),2ܰ.zK%aG%*` WZ28T4$HlwB)=?l{. GvŌ|LѽK,-pʲ+C@Z{qg[*}܄2e^&=:I#2 $1-Y^(_PZoPOtx"# )Kwq|3QvLliq!*NMH]/=Q,*TB$0׋6G1J0+ =RaCyBW8 @?H)ԶdW&CY' (ݳޛ0Yf⯻RϬIUC,0p`T} ϻ`Z`qy ?;80ԑD~vvX|vQ;(=t>mRYMxb(ߖ7@S2(ND$.ȝJ;tSY,9~v^GnTօܡ@ Q8sp?&o J]Tނ{4 ,QGĬK?aAɐU*F$7-U-"O-oȳZ)M}Z<7da F:B+u_0RT J-v#\Sgܷ2vo<ު^` /R %RjxOOBxҦt5BׅY0Q@i?:o{ c56fV׊s/T9̝pUT#*qTX !XcAmfqG5Vxh3@}ʋ.x ?L6TՔd@}eY:NdڋUG;C|9*3HjJMQBiI|!H_7-|w򢫘xSM#4y @/YC&kJ`n蛚q1y^+'gDl9)vHyB>IST|7KnEUbśu/ S=EF)zq9eշA1 aLoSA ;+XuZ= sA7*n㸝ct 15&i@mhk= ;?[wXPqB:~M:657F՝cD/ fQ }WmJQ$@-'rOKI @#6'HmjBy=;DaH/سiVF]'b,M$P(UD[qGFC2a pü|bWL(S[H+9~3m +4WCC Ԯ"`eRA)H!`P= >]qUol{grь,Q{jϐNם|R{Nq+k!ߛ4&T+sgcTq%6.IFbLIIM[Pi-`Q7 $˷\2' CTi0Fȉ@J.SwpRsC=J4v$k]"S% ii㎨j?H-(h(EAޒןhOÓ=.rxs&X;Z\yR*z'-@ilP\% 0_,Ɂ XiջA(=l?К&5«Ycn&/@^5tophQ|"+ԓ3ыyv [ j&%(#\=/tGq)3foݯ.<0D87i@l舷{%(%g4Ì[5%ۋt\ٶp("DVkc$Bǁ?Xp9XmRp!R'+jh5lo?!N>=ZHĈW@VWٚp&6\*)7u1~$9Z)oI6oLn 4.[MyBR֕pj@pخps bk=~ZfiYF~o5[~}+Gx*S`,K,5Nubf+bT5|K.FM;j0 ?UvQ4H)$*j] %V|,s e3Q87E(1M E32w}ŠgS}oO׏v<8nL]ITp wA(N )Py뼘QaT˥O- /vܮbC/^ 6QKSIې2u%_{xo+@T9-q7(Ir\E dz3_FtaXH4[@yɡx ɤQ<ϔMu핆+"Uo[_;#j|`%,'$+&"$0 }e)gm(.|Lw%_'|`”<\>ys#`AI?tޡBV…G4ivbC<<ޢPS p{,_TxX8DAuJQo)~ݞa X.osܲpԴ߂B(W%?͏(fdn~Nv et(L^;J%hmH=:E):P@IRw ֒4h. [%-dIRvHфݐ88 G~]#!n=lӬY9fK,d3fE%)?g5KH !\DgjƂ[nfx]o Fٛ G(X)LvPYY !*@3`d7@ fZX 2Ybў!Yo01J)s6;n8E]@ύA͂.XEW$wi^+ K>'y1=N3H3.o7<(b:b#xLۊ_I!j2Jp(&޺ .&N"KB1D1cݙ cQ Ӻ qcy'. ti ?͋9 З[/Q-i`=)gNB}aɼ!p +6BW5Kdc*z|38 P*t] f}ʅ$4+x#! xjʕt|:|,&-6/ oe%k&F?K3ĄT`O# (h?؜#3p閏TWFOM&0s6 h`2k5&IUO!\*wj~ Kk9:u)[\yBR1]2Q4aWH~V*6oh'l}аBL7Tz۝Ur)ҹ/yq6\DL:V7 ەDHT5܈ :Oq_?|2Ibo%A@6󷉟x W?PI2Yq7%a?׾~8@D !oUrQo/RǨkL]Cʶ0J$o$75Tf &}kUBΖ߳a8K{^WpKQa㭦"Ɲɿ('J֩>)b&X/6u!"9HXSǃ*+~ ϼe@ @[HF# W3'~4|HA03r>Ybl5^EAR@>T,++3F ~ uLcm=zTi5^ H5N#]h,'7G1|+&KHB\.6hB,$T{6Yvτm8royF9I5O^a,M|[XNZj!C~wI.. qpW}=%$L5if"&Q%CEAdx5Y0pIA/omcn;  $&f3z&/_Nq+f8E\d};Yڪ۬f(u4h~A.IѣaVDĢ] L:;jw~l/*›&[! qSʋlkn[=sFQHՌ#_g?+\v=\EIj',ff?_^U;LH,IzꀼM@Iڭ9 ~n |bN~pm苎~3GY9ø5 (7L= B3a0 (ڄ+R0D$)I+2_/z/!|劁' Kh#~i ۜ KS~v%p@D!Ӑ|K HkZ`̓l8S99-{Wtt$p*Ɖr{1d\! ~)rf$cf eԙ O3f-3!s_ ,HzؤTہv6?nXcʔmNfYCGMuݯxXFC#ͳÛٚp`sg ?f(vaS;_yXDzg;^'v[P#t I=[fx!ꀄQ Yf,h,mFX[ѧ24FD.(>pocHX ˷'! ?ū! i|{{}9]ÒW0]*#oNIagy|1eyJ)~"b:|Ns&ղ _ +0=)ψcym,C A*塣 ͜8k ՑMs1tqCa* 4Z_QfCU~]a ,_\7NA̠J~ZWcac5"Q?!{;;YϲJvpYnibp%DyJSzL&}2cp?נq)W)}>b8cHNFTcvcd*^k9l@=OǛ! ~ ,/x1bv[q /א+Iŏ.d0"XA>dςtiJ|t.ʲ ?QNz)@ ~&"ڵL yۄ5@k uVi Ha?;K\wf;&E{'l[( p8ZeMIg]> нۈFJ U[ĭ!}UjppW,O~{#pOW.u2+tތǷo1QzWF`moKZ"\I&)8 xfIZ\Rrc :֢.PSb;@'qTGZ)GdfΏ*K}ʈ{SXTC]`RbXRG#l\Ү*9_do:`xCt4Tj^F`X rLT Lބ|"mP_ՕM&am)>V!T/ ӇFM[y?fg.Y83׻&ܝ ҂܌>&6A>wx.6o5/%\Tw-RPX|L5p!)F~f|ǧo/rg66UIyYi8q1GH識ȪZ ӁfC_dQm }+ؗM=Xд>83o޵tVVA8Ud1~o[0%X5;s78M3qV ]īa9U%eNu~x5q[L+$߂7gKQKO~}*d..9^Y@o_n Kg {gK1/>Ʒ@D&al)u !Dz3姀,^}O% " I}}/`Q{j\?̢:m?C\;o&]ٿ۔Dh2?~% 檮tn.$;?'u 3%Պ b ij\ ql4b?'?{Dž|yp'$r4=d^ɯ YBzgdg\xId -Nՙr5>%>oFi=o,KׯJg >VaڇKQ[Zwwq"e } gorݥ Xx^ n>r^*~SH _,!*f'\.~)od GsGrŐɚhwHe<-YC؅Sr<:0+(2Qgaqt;q@?epPjB];\=~Rd!".GkyW ܱn e`tsaIot㊅p {2eLtD]ŸxΆTB4W[7OL/CEh+2 =?Tr6ƁPaE3#NϏŊc CcS6< o$"p1ZԈ 2T3GR!. 6"8Ώ$ 6[_c{S*kuaڅ꬝vp6D"CS4vd@|% t>ޮ R(Xש"1,|7ir) "ܝmlu-$BEg шoF k[M[1ӱӎ,bL) >/h:%1FXDђӈ%2c`50"et pLֱw\z*/" r_cf!vxZ0<̀t;OȀT5Cx}'1 C%C`ٓy'! ̞"; >CatҬD6B;Nq3j^c\ `>oJ(8qܡZ,'tz w;"t[z@™S/@dbO%S '  ҷvǝhoX`LILxw|ū0|p6b]o9!.gSd=&X|72-&I`L %KE zs.` Y~hfHT?ȿpt z3HUkXY8n*'LrW1،_?eWKƄPr/]amo_ίC2M%"eXl?W'XWv>BҴWu9\dt9ca_ތ]u ̤U@E9s0|#/9|4=u;d4bQo;4SFmI21ƞ(պErD1q#]Ί, K|fp)t\M%[dN>[6ߨܖx%DSZc>zK~8+6)X^V}v[ c-LC5tq_f"\$Z9 /iKSJre(/V[,H.O,ɒ|[uRW^^g]њ7 *tA}8k3gL`Э2, e%ڋDkgoiqq\ePޝǯٯ4J)<ՙȂbʉIϽ\0gJh&ȹ @+0bRp] ďh ^(;6ltEֆXֹ+2*d_|U܎ziYܹ^?8ѫ3rmO#irX1M m+"U{t:s<<*?~Ď UbWr\w4C ?W:[oVbYgN׌;hnvjvsr2EfCoM PQ"0)Y7 H X1zI < JFV$aiD|\* @Q|^SD5BvM ~_̯GsȄ- C/a~ kU:lEi(_'b0"UB1a2֞ ~䗰g^RZfIcϰ Pp/VxiC mJⓆ5>\۲zA;?Qϴ#7a2-|"h/6~{o;OKYLݵ?B:݆#ޮg88NQqqz}H[xs&9r^~G41W?3K_ֶ8t݇hfǐcod) at-{+~@~5YP5&_M Qƒ{-C;xL%Ua 9LEU:`ď7Zpe`i$poδ a,D ?O6n,yvNP~^h B)^# M*3)ҲAWɜ|LJ^n6"iʰLc5?}V:j~9:\_RUУJ]}$2TA?0#rfƴ +B%^UECxd;(`m/:DvBhw*јlr\=xuPKi*4ۜZbs3BeRyH"(9dТ%]ИФav$fI}{nO)ꉻ~.l`L{Xq38 g֑JKKo=ٜ̱`Cv#En>CYy> !0[AE#{' CYJpxxC"lx|NV6%VD]kd0 u}e#D 3oTwQӸ|T 8 MEt Ƃ3%WxErvd*Mx{ ?'y wÿ6D˽3yr2AM($_tp `eɒinGt$ qTᘠ&Uu?n^Ϟ]^Ȩ\IqnGN݃t[V` 8 Gml]I&_ސg$YQKE\BQGN;$DKaI9~. kbī hފ冻dvL#>!L)tl&ph ҭz2L ^l}z@@1" 9Lyn ['il~{Ɵcs~]n+tߨV9z |bCH񶻝`67,gj$͏+ 9^!. \5!2#gEaXpT(_8 񛄍w܅)Iy܂'-gG/Yb$dr9m!TI|*4U3[8PvДƆOC+m[󒪁sJD}Чę—  Mye)}7@i͎7Q@LG>Im br+BA kXH.xʝN?O# p2o%tCT[Y<kxgTy厷bG!s79:ݿ&49Ot@HMq*7ZX*h-q}&,n3--t|8#74Qҏ'3oj!ܝ".%C>|K4 0HRY6FlCmpMӤ dl`3Q*=/HY~D4CI ih,v0ŚՈ{oDˀWJ9P ௭86\ۭez<4&iڢq"'pa8Rȧ?m2jle(3lً'B.)Kq$T _L|3N pT ҿ_"4މ /Bu|`|CMT1ǎ.J Iq]cZq0puX/qlD-7KŬ_8YzTl:|LjYwBIDZˎ)/6`T!b19NG(I-R}Y12^"a?8gdx3h\w%NHI;pl. b Tw!F:9loX/▹:OS۶_06f]8?ܫ3@j4#dl!i- /шxX#x2T3`!2$^##"7:o<^k"fr?YrH@]j0[>g; /fzfE4x5]2HC7'1/Qq\Ob q&Dy'O"FKӒ֋oq@o^ŃX Ӆ6*h2d׻'nZGג8vso/~WYb?1!%H)\/Mpc2c_ƫ/OVM b3q5+!_?Rby I&%ˇ%OW* 0zbkȤO"@;uM"b 3|."|@Ol|HLO\?&?3 Ӵz&Ck ^r n<-s 6|^Aw"Q\L t.?l W9^n3=54)-n 7~7beڃyvMH@N  E/}~unϣZߋE`7R#x^z'$01y(xWWa!?Wnbذ{ƨ%Rˬ^05KE1|瞒CΨ0\\N+ 6%'~_?VZɫN[@#pMarJՙ234 Ctg&k#K%[{! HV.RA>?yC"ӾK]/9n(?ҥ*C;[oWUɑ‹wZzwJG;MKkf4ZU+ mn70]pC" ֔4;#a35F2⊷otgXہ<`!9PnĿ0@x]N9E:Rk 6{@QTvt 1h%cRՕ#=X?~^fi"g1RgsP `&z*6/fy}⸑ڠ0pRFpPnsMFMȗ%0ݱ| , MJ/2RB9pfWW_&K/(J9s_UY3ΗoW'4mo~y 8!cfB5YŊj 9c5/q e;c3_)P+O(fK1?ì!/_m#u @}P m YpHoo"Oj ^W)^5K~MSAС :Fxc#9?R"=8V4%t"9&#tPgА##5^)c*8.!R/C^UHezpb8q΄2Д"M4cn!3>Ĵ( rEI]zy\AO[.`Y𣍦9O pr,dY,ͼi4`^긡+p'Ke!Dm(j*>2(IzޥIxkSi0ϔQx}ngj9K[.CaT.}ŏd;ĄR3o9Z/lx+xNYi?EFjKl/~`k M0h}XbN;،"O̥{ū 1ٷ Q*}/6< OjN/cCy{$KKQ cnzǫb_Hlܢ3)G =|GXK}~4Y % B$l)]j?P b}X9EzUKJ(ͪ8#pY~ G::A'؅VFΡSb];ҦE>$97칅R`k(qbR4i_ju\7)7 }lIFeބ\\L-4 !Vc~n(QeW޴!5C2bŰpx CX8RlAܒX?#K17bS+ƛ[9EbHq eB|h_3.o[^ӈ& $3 J0toIumb5FϤ? $@V @0#\[yձaZ3v#Dj!]tfCo(D Վ x!7ܶ̃MXIYGA 7TpJ.D]B2},i-!. l F,CH.q!P\0 iI8`ykU {(TWEfb DlK(^InraS^Ld|j:Fqe6X!aD_+;)rQpwƉVZ͡8z!2 F@BavTsŢ+Mz&ojƭF2.JvJ_L$p0w]nZmLܢ.(Lj#bڦɯ5 ;8>^JgFU K{b#v6'N?l $gM,Ɇl[QԺ4 g׶(Re>Ve[rT=[̳f c"B@?_lWy، W!5ɕKcr`Udם%Wo:Crck ; !+iV Yy_\匶Ere,?6rBg? z>pI*0=< U7S@PyhW=ܖbS@"C60`ݰ6mFٛɫjΛZlk_Z{$9Q0hfE+zngXR?cϖ(t2Xą0,~s%)77Ps;w~O >>{we%X?Wyz/~Ɯ#YiFvjzv >s/-AhѮ;ֹ= SL7ӂNWy!~lA%7U>yc_$yc4, $i̳_-*B&|C2PTڍ6Y` 32x$W@|[oWI񧴐9=Y Up%\΁eV)D4`,vzHqOm 0/vNSHz;?%9]\~RPFW'>[qp(Y',[O8.K8^*yQ0d~~%ڸ択^_ɒXrIH1; Rlğ[miI_5+` EcVv;UTȂ!kSy_r_9p\"m‚E>KGb%I]CAsh1U"i33;,ɎE 5)m'jdDTAޮE:_`"("ިINYCȔU{^,S.4~wS `MC^o&7{M׽"_oh/MIF+qKl[yU"b)$y<^(5Lh`ep)!e"|)p,or97.ٸ|Dp rȃ(@=J64a"d&[ K_ ~X TcPo>;c4(@?uKuHtP,ȼ1 gxuip tkz_B>.let#*#e y囮i6D<|?hYH`< eN_8 0{BȐ#q`WuBc 0oDșTk~ `0bW1RWR.N8.$Ԁ1E?jJ7~"3fwaXӗg7S|>jN [܉=g ʷJA9/ ھ|zæ@.1 I{ё!յ{El@CT4㔰?G*"Ui Z/tC1h| 5"C+܁O,>R$R ETǡ! R J]*vZo,鸞|JEĤpJ~"ó3v`9"i=kdA,!ʈ*9 $V fR "V3M@ƇsPtڪZ)>NQ2dsdk%/N{z9Z NsvPh%vc ?SŔ$ kjMI"Lik }k/QFd@ZƉ @)^E+u] LjJ4C`*mI;ڻ*xyDzi n$[D%ǷgYeYby6[9+wVWI[?&,)@)Uw۔GR"pnc؞bv%>P_dQ+~6D]♒d=@Yb"u"Irq~[ r7𼪩,fYUF)]d^H=4#U+$s+m!&HXd\#b?4©b!uIX^i {nڵ{\cfș/ޙQR%caم&iMݼokg2:ٿLj!~4~ԫTh̄' %ocvk+:<!7 aa%E+/]a–o2~xck]^4muQcAO=/1@ȅV5%Md Vx2s>~&:`(jh;ߴJs?u:śʣmWF,Α׾{*~.h`kvǏ6rb?UL=؄Q+*' y,ۿt:iX+8S?Ŵ]Wɻc@{+{L6uT.`!'6a\=L=_ oRg(F0* a&? 6|g. j$b{ ^>a93Ad'Ah KSoD_Vp7לz~t{\ Y2.z[aĺUbfʅƜt!1A+iVkOEΕ?7ĞC\(oPt@Ok``OU9hFJK%f񔱗hXHpDM_&tZ@"H> ':-@5i_Y W<b9R "3_ͯgIv>q?T<*Ɋ.EůOPhPN(U;|BzT K]w`[ϸjIy,t'Kg +UnϬ)S/>< R!JFϽU?x ;D+Gsr)/ͪvS鶒- =?4=!KsGgA3E2> )?3'/S·&!Gm~9a6?]=0+#R@ikJtH% o͙EU^?Y*{JfB<]l bf\Exo x=t1&OzU WO@cgǫ?s +x/RQ6H[o=⟵|~Y$DV1U+ QkcG TFͺ)9!0]5 ]ot$8ĭ\{¦{`X]!xAZK<$Mp^ Q~;_e^!3DZlpdgzAQt>TzPLw/*2Q/i_iNF 6/g1Il~/;rݘz^KN@O%{{⮿n7НR>hxڟޓqqk|__?)h2BGܪ _u,,DMu_yMg^lzӇ'ȑT'`@ +`& j뻤Ȑ ˕" &LK#)pP LNI|%Mq~j5X rY;'}ͯҟKm̯ath_}ȈŸ́+Zt3K ј>sςB"5Ro%|?Yc>vq{#ʉ滨-0d9̡F|P/ ~ _jBsCCbgR8=i]hn?n`h6"s@!S({9$&_{OA?hL qdc hdϏ .: d(Mly|Ib4c Xiz}.TioP 8m7PYe?ln%N>fIN1 [zH~|1xlnO fd3~pAU\/?CQ45^MťhaIz' qS8?CÛBA/M;yw;W1!wzs'FS7M? =Qyi\!G @Kڲ&E5C+Tnexu8, jmuY~yRIm9k} 0E%?5=)-~@bqE4YxA+(wBri`Bywe"+xBAylhS+o&qW,+>}TfqbnN p;4?> =7F2rZr#u7ٯ`-#,6M!ͶqŏSI\:BH' \$U_ǡK!7~EГ! 4.&;PrWNG1Q/y`BoAaG瞍乺љӵnEx1"u&Q_*s'ρ?X<,* @7.ilnyC,U~$Nw]f spHd,, 3x9"NM/d3CZ"ʠbTb/Ǜ<^? q~!pDYbKAwM|SS\O'm[1)JxD6̝d7/X4wI`=;m:v]E6pux ^?[Ik(1/iT<kh'NG+ ̂End{i(lW7D)ݷÔ;"%5go|] x uO, o t?g'2̓m1Lo S0a-ڮ`Fx3uX4χxv-]n^k!Z"^4~tCr/1QA!" (qqBa&ԓyMب`;{WjK\j*{.x&\_3!+ފu5xUx |ͷzaſo`e{~]}ί5?_?,%_Z88'׃e>ڎ2d9iDbW]$1lV~ؠ+S_(1xx^̀~6v99CSkdX.M$3 Fȕ)IsS#pDunm\x>p,]eMH₟a#6~T1i(1^c'e<0rlfzj nj/}9Ce_t}jC4/o06|뽜LU#6MK/uBrZn2VF3ҽɸ,Q#/RbibeYy3DA{$ͅ;!n+^f<( Jg&|fr{=K<pibj{b#@?Y6ޥ7Zd_fzHZLƉ7Q4;p̣9qyueC] Ti5T qȱîO@&l_C>Ԗ9GEFzwvۇ⭂†)!ՖdGogenl *E"CzWΔ[ m+ Ԧ}+0Rj-=7daDàO%Iƫ,ܨIK3gq*Du+*Ă-xbhxür$?F'r7rB>FI=4^:A 2~zZ%2zU#.Ѧ4,蕘pI\3,m2Vj,Ғ,ƃ]Us4?6O;V丕(y@g`l:V2zTn[Dfy;Ϧ~ua1EneAM'"Юn+ ZlDohYf.-/Eɥ߭$3"用6QtCxRHOتgx^#v.w@S"'n]-?*)>gOw_Do݀+̏ W╇F!trrb ^Eu?G )},X1i;! E_t*5 >n B4`_MC16bit H9 j؜yh?+.$z{rճJmDN2?,+r/rl,k? dY ⟏lx+7 ۬g b:EZćnDGϽBbXSJN2_ Xx!S}/ p%y6*aqڟ/;%a NQb7dz2?pi6ph8? `Atr Т3Ϧ>2jme:Wa)2k9Σ, 0)NxOܟTq=Swe?~b8CR$Ty.S$LQfqI0.\\ެ n`cAhSnʯ%ߙ4{~-?/ɡ/ ?(P- fasVZP& m$dG$ԉS' KN =kM^_dp}sGz2uE\b+ ePƣvZ0t?2!pO%`9nBCvSf%s=+ \DŽ _8rח_<&>*@OY=,1%xma$G_u嚕&*x9CEg)NL zYB4423zF!^e}Jo}&3?G듷?vxPڲ ~8x&!Mx\8&e%YHe&$5 *lpz3SݞDaIYo۠?#g֋GԓȜVqiɏ8%:ɏ_vx!8 lq=͊!.Ǧ$TFrLTNdJS3/?9fAu`56 e5S VfQ&5O uEUܚAzjp؀bK`q]lIV|%ޯ! x3XgܥlA^Ɗy21>d9ٛld^  u$ ؛xA&7mޟ׷!ɸ}Wͳ܈ǼW㌆džK8|HQMġX3Pq>7SxQ+3ʜ9\5Ȑ~0v?(^ +~R1imT0C-٦s"ot2xyl?|5&x0.0wFuژĆȤz昸`>.veI|R?.HLEߢ7o7STdS"ZMY[vP|`)t0_HtXEp_%Ua8:cX"(!3J`me( $5A^ͬV\x1ʌ/`(ri)e+8ȡ(5+f(4Ms.PJʮ%! xvoɠ 41^eB zzPqnʨ`ggm!Pռ_FނF[V/,7o,mSuOarN l2L m'NWS&t^Tد9DTf4ހڴ~pT$}:ۙLF8;u!: ά۰ SNèlqj(6;ׯ*HX!EQ[8;ˀ ?{Oa7JO{apgyTJ| S}FeSThTEvg z;yAk ̄Xπ .P+C*7x t]% *W}ɏ>0_|GmAGxua~-QK~ Bx~}Og &D.+N,ɧ&aY?RPAml]Y0zH2sߒ;Zi(?@i=Qmle3rA Q pI6LN|d݌-E Kjr2$ B3Ii( Pĺa]ŨU/K0K?$uw@fr>ɯsq1ʯ/%XL6RHˊr9.f&:LZ(h\CŰ+,$(O7fMw-SF)5dV m6iYGM͙-g%o bݑ,C &t#zCbBBiX5N aT:Fci7$$0ќ>7wM x03l \mS? 1 pPƄ;7To4JgvDc znsy?t+"9^źu3SPw+ NhU.o7\#xLOO}`kGCHY*k|B7͏Q7%a OՀ&ڒ@먤n*Kp j- ̩v& !KgFnVH-L)H%]JCiGx*Ou~%?' C)Zo>hl(Sni4+kƺFb=XRx,Xs[}B]\S™uTe /# SЌ-*$|ih.E22!)Ćl]aZ8VdiuE6) e.erm \N" eBAfW31rV"7~>- detÉ`lvC tw/PNXfQ> ]&ho&(x<\N؍<6E4:xM f򆈮' ,[3{N 2 60ڑܣ$/a?$C HWe @ZzI9Y K<=$#["0eq<%qQh`Z8 6 g>DBBv <!CQR b2!\gR7ЭH;AX*P^! G?dq,멯<'UD8H1/bÊHv ^;Q2 *j:gݍK8ZE{mh縯`K -l =p26?NWu3 zCLZbBݒg A9p}_{©XzK!5xUP1(nr\ pxdW߉gXbed)T{C@;4M~)0 m0vR?[afV Y8'LHI`1@va{;u{& TiW3$^w0ItR:{k8PR͜|Y|ԋ.o7iA%~+/ͺ:0vX^(]aFB %zX8K5f.r6ZߛN&.#\S*Xo(h,>"dM=܊JH0.৓:%m:(~b -)Ӡj (?C@m  R aᙙgW-ǏwX/Əy򼂥4HxOh0D[zH[> O7 PG-3 r?a 6 ~!c\Eu>{|᭼s¶$:D 裝$#CU]K&c,#G`j iC)8S`h ȡ;qP ?9ܵIENI:J8w`q IqpeAm!U]6[k@x,gL,T/ж]vW}5lcOm579oƷKr0l[@p{+=SGJ ^KCkpˆ2)-EW"=nIy p5C{gKˏ>|c W3!(sON.ђ__x[}(fA3$_EØSA 2bxa5 v$!u1ga  !@Y9hSvp0bR'' "XBv#*}hLѱ@~% ot+~x ;]7i x}^K*|."Y.74C$JC!Ty\{_gj7!wwoxnSTЄ2X`#~t & Fuՙ|+.;u2Zv ;dҦ|c5mW͉+Jk?5?e[od<"smûCtn%גJ݅Ox6`?iK @֢5鷅suaX5h؏_$Ơnxsz.Z-f""gIJ(n^bN^/.Z|BoVE.{=JhEl{RS he=2Mi6򈒒!]vI92D;x\{q!26KH aͿ/}- $~ĽHCS[+JX3ĝJtֆX͋d\~~mDk3͛ ~>x?,v{/ /nJ"f"C㓋 "璖ry@RBV>?c5]է`=T..]j[9+8ޮt IH/^M*1Dƺ|l0_<.%xsi̿"vCjyP`Kœ0YHEoK~[ *=M E _C~m~-7}M~^ZY:k]r1DI{A;6ۏI3 -`OZAzzK%imΑ탠7|ߑQl7KRc8|?v{B&A o*g==E[=ŷ- ҉!:IY:v>s* δBpB(~jY( Hc4VmG\WXoVT&^p>wozǝY릑٥ZVVtH=l Z' qnɤpp4o-OQ4'yS^v%Vgh(͚y7{P2ifΕdϣZ )]FpK~Q1:gN+gaFj=HfWW x=Hj3D^,/˶BHVt$Ӎ@V V:%DC[/]aJ_?;%ޠTҽS z{i ΕFb`O60 ,L,ς5LˢJVz*W:Nq;m 0y"s/"YDw0 kW%^bW_J'.pB_*bߞĶWmcYɊD!׏an)k JzO&7K8\%1yK{⊷AZn=O Wx[8Wm+z?`[IKV J4yxc<]0ٶHfQ|Ii_~560$@n? `d ?_<_j 3{cHk0)'z: cL`=t6*Дk^ō[nl$`38z.R(U~jzIsb'`3G,ozF&) K's9PrmJ ;_^6`6O ;궆 a[c~d R7kQp/+#[R$MHVwt}4;Tv蠟-^o5$0_ג}_ cPqԄ*4hUֱ^9!8yڌ гO LXƖ ̦:M) L#2WW|K2Hh{,R2,Y%m6:GE;ߦ*87mefIMo\5N~;׊4Bx~2OB8Fd8bjÆmnEFaÛE;ފ(eڿ@tl5f Tqc<37>?Cӧʥ|!6c):z BjVfB͵is{!RJHf 80X|2uU? htֻatruηJ#ځv&^U?_9KZ~ūkDx~\򻼅<2v G,x#mwxHO_U,A2OIXd8$tCݴjT-Η;E"@epMXu\b;PW5a+SX } UE{}~$+oC!%;#QdMoe>},5oxAZ ;7X&ğChX|4AVQHڟJT%*c2E6 B >̯GXTpӱU/=kR k t/uX03` "ң}Y0o!_ןKHƛJŰuy4~z^,ɢ g*v*j2LTz[1T6 !@f,[H]}Q~6%iI齣CtLJYK:Ga{tݭ%Ę,GMd8)t.܅x(WkaXv.y[hr/#6sox{Ϩ(${Ai _tLIz#|;pH}?R^%S}ËYnCnp2[> [ĥF?/-Uݲ =mZY\Z^o1zX*C{&A4C=c3:W`uZ2^^c1\%L.,g[Ō*A6U.2K26 yUڃd5M3n*y%ufs⢞]NJ|L,-ν"U-)6Y5T7Y~/J_M__?ȼJ!jKsݯ_w[Wݶ2)651 rF׏~O>||A`s*14ZCfiR^g%3" ={owxS_^W$TϿ1֛K#H{0r)`U.zR_@.>ՁOњ*JcU7׻6]f9?r/k3/R . 9i \."@ wPUY<ؚ̄\'ynv$t?7۲sPӨ^"^I]M<;8p~):sGgsN G,OOCK$㭒/9yPT? nM؇ r=ix׹ 4cx(G7IRڴO>o(ǕZ>΃;G\TڴSo('z$ZtQ%l7 5YI?1!kU1?j}I'D[)I4A|ϲٟe&jrDuU1o 2a9f6( E^XƱl)Á =.tKOX:mȜ٩Oxc3Q*{.;95zz$ qn?|+zOY4@sI7x 50o,CDYRH?gp&l.~Y'^-H=0a*: ɉ&ʼn?~m*[[PtJ<:qc91X0;p+wh u6h8ނAT=jLD/ ?oawNRSZ|FؗIEpӁ#p؉Dg 4${8`=XsԬA ʐh9X -/=ܯ*S RP]PN̛,Ijvd˶>!rgb_9~ MhљC5[Gtsy6<~R-rhOJ)dUpntKFv1Gl 6ɼ^D{8?i1z&;,=H1AP4Lx+j8~^OLxC )qx%ex(8xow!y!\7Avr{^l%/O@oV",UKxyxqΘ|?53*5#/*|'U'׋5oXbAmr࣯@4_ë#˯xs0M6_vq)buQy?pBIIBwPP ńCxN:Ῐ7Npj覅u((`j˛蹎FPM3V6DRN %c Ț\f͑qggPhj wԑ| U*^8m3[ӊ F;R9K8Sc n L%-auI +?̬SpP@{Geg*/6#HW7}´_c&8 2'NVJ$GRK s6͘L\O+{tIsSט ',/JkQQ4U/ۃ›;'02n(Pryˢ ހ%"F = [4k#8lh7Jϣ[  +ǣlx0Qtӣ5Pm~^=]0_-xhZ1LX00^q {o oOdW܍SP,=WJgx,i=C+V冷O ˭v1_ϨL OuzՏ.o /R"FUNۭK@^3E[JEꋒD _ú|4kC5\wrzo D9AW kN˯!'JʯKnT9)ϯ1-B0t"璨 *ޛ&"4Ԋo*=SX@5 H=;UbITsM2/7Ę(1ms/ IuW!m5#49ŋEIeО^x)*އWX1~LM2QCKRF<[{Jax{^wq=d+ތȰ̌17@!kSo̗'ٟ41ś>`Hh6fBgc@Msśy}Sпx~#U+xgQoLJVIkZ'qXEB%fx in|;t#v>a\,?T~+W^V"a v{ݦi?%+"YCRWj?]zs,^ey o *-'l}&\R;3TմWTE5D{Ӳ'gv"N5!2~`;~4_"E[3#BeK“Wn2ӆ 쑭-@Qˆnv`<\,7{r֏&D{E-uɯ3]~#;`,`ü~McЍf z j-DP㕨1L92f->Ϥ~%8z)WQ+Lg>6P Kx QL9,lSܪ€7V%լS@0vÕ) H(V "+0HBF2{v,By_O^aί4ikx0𼶔U ς5.1p&E*&0 Rӏ"@3䫔#zC (-B|Ə"SR"SjIDj^ ^G@ '1+,r`)B1 3y]Q,>t/h22W mM7-vH;LjoJ}ׅpH(^ð4?d𖁒{"ϡ9HG"Na$0yğšɓgSbP)8$66*$]b>DL`~yN׌g& Ͱ 鶃>?$q8_SG"zД#$9S!RK<s 3EB :fxcT5lQ[pAIPY|'uyl' i{*7c)(ŸZޔC&/ la-f:Wz4د4ɬx= dS ~{ /M.(BH牏Ѧ-`-T/w**6/ 4Ѓ)f?3'JKDP) \7`Gۨo%CLԔ#aҰLQn S4bc`5AQ=pI˯xOͯ|0//C?F_:=1S,oTM46n{X =*m\^N y~RW P9Y:yÏ%3$薔WfCڝG1•({&d%u'_|C5Ps c$腗üjJmw~/>J%!Jcs>B[ l<|!!gSl׼{ FU<|wUZў4=Y]VHx~gр aQdWp8xC'AStb ob:gd.`:%5DgA' 1d3 v 8 ڤۂ 32qw/c2Y8RauM([q3|Sb$KwJ`!u_#w C2%06Zdo7Ti V @5yԷ OfU1fܬ^ߤ0f(|9&kܐ_mӂ jz~_ǖ_j G $: eJbi74x*bF5c:_ZR:8 fre %a{Owf2sz%d sonaHR.:_q;!F)LLdYY٢]&S%48G=~P'Aņ[Ґϓ?w睮_PswbXMu^5[*X އ?-}8u0KAd5 gvV0 m2^I"*Ĭpg{ 589`7KǏP'dm_T|=e7i)}$:0P:Gt6T?mܯ ["w]Ճ&~ b. )?]t 4Q/\|V$ .AD.I?zb9sIܘl2 ]-wQrrNfBzi%=L X/T/Um3o(@Jbk# t*[9 љ\&å@M%-j53Ƥ_ajGl(^?r`NNJn[~ne+(4J iq 90'QX3TלP'x(\OXg?72cR+&O#oCɏNdW"@"a\i tqVǘ $!(`JI/8 FF Bx8 x%MK6 Gf\R G/YKRD*HI9: h?\jq$Jp If>\4""֢dFŒ߸XzW)U#hxu3 I׍ɜӏa3ޠLfMWayccw:@ hĤ&@o(I&,v oj&y~{8Œy|^r7Wp `Zf)G?aZ摚\widf2=L~jiw dWCۆR‹p-UCNd#-Gr@K C&x'xs b1'ť&xv"KH`?/xU-IR_8Ɗ7h]A|Q e7R~4 o*DP5)]tsAjEq9t)n٦p̟0AxbE9mePW ;c w\̀?46I~)bqڍn Oc)`:GU>Q墴Fxe=qO0/ [i&D3Y l1pj ]Y} ׀=8S7ѠG_c`i;<{Q7. `ʯBê*kƍhəh;!uœ"$Eynw[Rʵ$$s c2?\eًU,ĥfaa6g =D]MU&"ċ$b!pC$= @^$q &H% q[aIjf30VNѼHJ7AJZgRO]!EvgKa.2/ k0'>፽`-V[Eo8% ~b/HͼHhYxJRpZ-ˆ+G0 W(-W[EK `OgXr9\HS\^%ԥ&|B𳏵h-#؈~ R{_ŞPXdxq4CR\j$=L=\d>/n \%5Z 4%"M$ -{śE[IxW :SRwG ,cKRmMT72sZ=ʭ,E ׀@7Jϛ_d7L͈cy$<8(.3S.[~4hn%4gH|bw˯?!(HLo"H$ph]ZZ#DY=Tc@AbXޝ.íD!dZʶo+,GٍHQPi8a]w>>[ۃl\,ޮ ox'vM]3sd&gZJ!t ;R+eY Boj:[=/ߨ֠ Rd!{\Y6j%_A^#U5ER8mH>DIsӈR~B}(mdj/(qo.(ǻ$)茥傦C\ >JD6Ҁ": IgCGVk<._d ou[`͵PYq+T%B7~L۪F)~~rP<ٴ Cj˴m k方YWS{!l,_-[IY $=\_`b,_XRt4D%XT%%zJevQ^Ahc #/)Xk6 "~l[UźrYقdad'g~Ϗ~U~]k~ n?~qys&[=0$kjVO瓀BF]gMl)qy]2bϡ+Q\xHP-o\H_3zsjVGjy-&cC[-r^;ϫ/qq,o0!k[/7y J_Ј@43ɑNa{.d9 Cn;~)' ~ZRV8U, ? O~=7w J?Miwi& EFk ?I"6>&/x+m/Kĉ-,DH{3tzhac`Vo=Z2Y4+k @"/M5Pz]"ԦJO~|8[a?~׀1 x&Dvꌈī ;ooeY㈑z%*wS7ܷdz4ܪ+2 vh@?CoWIvAȿwyq!&,vQqKA[U$dߓD3s|ndp-~aP24+KϡVss b`QW:nLzI~]7Il/.uАYӅĀ+,fOʎ1FXs? FM VlRi i͗R'@̨>MO! jH$zciUe,V `8W<%v 1WyFaU(~X | ߫ɪÄ_3Vk$ DHvLځ&tX]L!X"[:NMA8!*o?s"č7uЯ^<n&^fqV&FԠX'ȫ12`mZ+n'y'rKOnU~<9:؏x5Pԛa ؏|URo)c>QG]i %Y^h$dhB%Ƭڗv_ٛW 1 o{#0ǫ{Ÿd$~A l+3Qac"!)??sRBU7LCZЭq2~B4@eDw;WYTiCD,%JcG,૵`qb:,LԂly /WܑígUAXzyبМ>݅k;_sX$V#.ڏ/BT1@n_p(r igSyiMq2wn `Bpvj0O+*,/AvmoU{#ۯfmiiM 2io_d|l=NQ$(:ԝpк$d,^WA\@,-+OAUucKg[ sX윋OU)HlM1zooj2*tPyW^,|Yap4_-sW)XDpO th.暐LdOPȝi |5=}{ƀEk~́O%~^%st+(4R˯i#3:g5L (KfUw@!biT[Ox!#q? hk uhZMJwH N{WPC¡(b^*Uɍ%6$ӱR/jU:ҝָu ~l&p\tO^JNo_H\Uڄe4T=Aw'&{qE1{LOw)wc^L5gB]/XW/7qq&3+Ь噚=+gx/qn>W{324qD f;r`Jݧ~δXrv/Y~?w(ԥ?얥UƇAno~́ FWy@p{F!ɞ j2j~vG~ FwFco1~gu).haiR犨>|{xY{C/ XpVф^V>ݮ?͍ޒ.xt|Uݽ[eŽTo3(!gĈɯw~z7ؘ|Sx,G_(>01œI@Sghx5[3:t QU,T֌|O9$d,*13X{t%F|%h!хy#?QUD?ϥmAϻe_۴*8z~xgd?G6Sb'\ 3OE,f$k3)ER7!ߓB,"$L:$`Uc?ns^­b'hoEYp}eCT<%@Q@WĬhy&c%F:X rޕSZBtm;Vgqf Y?aMb֏Z=f㖽%,~N_\o>g;Q v[y#PI7d7cFѭ!Uʋ0Lj~}RFpo1: /@e'B6=Hx`5Uydo =jqcAƢC&Jvp>d`2Ln?)sp#cHV8({fڜC=Q}ʏ I tYMo1<QS_lBn&ި  Ô?9a_/^jyh*V1MIL3EkҡJ-R;S]u|8H,H :l~Dh?Ęz: gf48GxDp$C\ĉP&zfSik|Ew乀aJR5F_hlhט",#^Ġ8WQ0 ٻߖ;uFg^CNыk Q/ן݇{@e*s\@&{lNp!:xZfα~')@=~.Kpݧ ~:_ / ylo?1h#H5ICHB)'8YgXc?ު`Yc2FBgO`55OpE!7!czt^%CLM.[}ُ8NVu[u6>"7{BtG]NcLy*\S!G}|&k%-xf2Uc?iZ]I#]ɰOE`SrySDOSLP ^bu-j OJ;G3soOtnxH;3Q`0-~Ʒ~J k a$kk}S3a:8@悞 na!ޠׇ|l;jWuFsbA?l&VCy? ˆo|GsM$/׊ީۮB" 2pkt?7C&Pq^HG2nKӃ%KG^޾A7B2w`f4E^#* U-k£wf#^3Dn~Y0tG~X#D2\Œx}aW3n0]1>{_^? ~¼ t/ƫ;j(YZCMfn |3fܕHArJ׳d~y &, ":#ye`r[w8G&>,Fnd^TbkCȃ&|%^Krw (7uu) #aMlb,_;j~_'{zz.ݔP~t Jߥ(? ki}Xz:TSdH1<=UuJ&Sŵ.ѐM.N.j讐씴j}:LO/~]BxW*n(v"maЈ?nI%ppSj0tNu?؀AZ_E}rP z3ja}]#6HH8鲈Ho?A9c/31 y(/Ud?rMoؓEx04hD}HدN0kg.˸\@U%`DC@ń_8jۏ: \Zq!.&"?ΛKGp!B' ">'`p>DZ33SE!c .@7#0nǣB-ڶ< "!)^tHhV"&O?}E3.=+o@Q+~``O o#&$.r/zye !.FN=Sw05ZdI'8ߪ^ b:>j?S+'xu)>؃ UåD](ݕ|~CY;;9 s-p1uM%ш ;IUpCZ&8Aeu}EѶR!-}).)BnJ"N "2eSf!b#⃪ E]Z5?w (Q'ɯϫAҬj ՚.!8-SEcX `|jkH(CF/ k RJ[L&Skb!-Z{f)atLfԫ(Y,@FҜrR Md}S鶷,aDZյB֩ޘg> *J"V'yۏ W 8A! zoT{ hG h]5co{K9h}ŝlT`W!ōd]{fݡ7WХuBA]W0=sAt0yH ]}%R"rݽ~ux^T+]Y%K]nN_%EJOQ) h 3IyM`R?Ns&UScEN2l% (dy7y=A@/Z ^]j-$ DUբW@z(3-WH  ART+ڛ)i/ĘQٛת%X hh]3|3;NK`w""Zv֓ l}_-Q ^9E%o-'5 ZqI̮ H<HsʯL Fk{W2BG3aTaqN\(ÂR*j:>* X5聵CX \ABlW`'x'3@;K Nj/lI!LigoژzD! yeXѭjy66cd&dȓς8L99tzcj'RVL,VP,㩜y{HDtw@񊋽y)g2~\PDڳ~F4R* *[W3GRz^]酺Pˤ;qbpb(@ɔpp'[DnUlvl'ѹ * گ}wU_&3rC ?)!Ċ'k[B|ҽJ`GvOqAg`2tXvq~0|i2F35 ^fc ^Ÿsop/ҡM7D+ECbGLtH+xumhyHGC_:>u}TniZoI A E ;lK@I͠.'M&rO;bX~XU}%Y<[(@ .9\ &MpP[dǡ7+?LxEҰRx4 #G1c./.,1x;UŮ,T:)pCzU|ۈr_OueJ !zB1xޞ'M zԋvC^>`9I<|+?9XjhvwJ>4hMD=]ˉBk:CIGzMyn{mBg10;mF(a0@ʹY"$"Z 1\ 450PBL|osµ?cBc>Жya8`] '(αFD'Mkq~H E25N󇭫D^/Li<4 U; Ƿ|2SN0~ ٌqwr _ %NORfxtǛ3%o+&E_ȥ՛>&uL@~w{|K!A'1Z04&D1)٬`ZA'l@BDŽ"l<5s6;̏8_DyP}JK~'S]3Ub h^ a~- 4~FT,$SѵU6Qv2QK`i<&4t#thy%y#ROEP iue΍Fp^^t'" hr2 0V ړЭ1iY:B -yI  LX> Qn @ sq4}OUlBmx@hOPi$Hz 2Q*q0[>0D" JXw;cq頴MmqBv5:ZIl5T3^ #s'q_b\T'lv3UB0G #L=wu3*ܺQ, [؁t $ qKq"El{Rq6K%] FAtUOBqz{J牎O["<$jS[_pOrfN;,b/l;a9I~͸\we6/㕀PK97HmE'If4? C1!?6׉AqGс_0Xx\뿅IxR\ITt٥{Cpv%J_8 *aSճyTHsyT!bLPYIng]-mI"/L'U{f SDDZE% XUܞ(!s?77f,r{B܂#B˼$#$ٛ'Y;;yC&&GBAP(%~{X㉻~Ty^;šOc/QYֱ`v ?O*q)}' l&/;' uIr4y&.` WD +P`҉S"Z$%-ʥoJشO3JsCDi_j*}P_Q{ĀZOR>L`\ C =IAM]MS&r%:źY)=|` &Y-@^zy~n %|V i Zm*?Wȯ!I;P[~ [b.?r\*cNT5t n$|d[4O c?"W@h*.tr!Gg d~UK)ՁwhG%6`i&֯P\N.ŝ{l_:92t8 WۋRhTPXx(2.rЕ\K;&TA^!*)3%oj_-~rFJLHL]ep%./qIyOwPuW ~2)2DνWľiX ێ4L pBA>wm1$ Nɗ[-7( qc^= D.3ꗡ ҈٭GĞ@4 A+X,c|- yyyuh(UJ;סƦ'J?C°猼ks\D@.Cc$o<)ʺä(R]jjAwK.}9:JpUb.E{{ JFOe°C*׍brAݯcwȝXHqWͯj?SIOI#+ f~X3=p~i 1."pJk㠨ϟ Iq-sglMۏ?fO)hfAe>eV79?ٛN_⥋j]5s*; gaȸ/*h*T,-` =.M<x{? W<dc!7׮Vw8$^B9^Бj@FD Hr!Π9Y_?ep ݝۺ/x0N {EB "{}FMbeVh>B1<[+9M;YGCEpU󅀰ꋽ4W~  I28ԡءrWm~-_kG9? %$as\d>,Dy 05c@ASypɏ9'zsK*XZk9^L)I a<&(V"^DŽ Bx 9Aj(B~;Mܗ/KP[ c? i N7{Y:K1bV͚H7E/ck^_fǯTW{&1o^ڏ4d? NyE+ŔI 8cٛ7{hDѣEԟׄ(ziஉ̉b9D(&fjʍ&Q4P{J=M"x`,˴v_d^_kJ⳽D0%ȷCJA16s}IN32eE$ 2 2#ܘ5^%b庍WQf)Sq =p*/ޔp!8^[i8zHX/Kc+|=ҁS|[󝰴qR))u.?e C{ra1ū3OUj#+e,ΰ_oo&^p?|$]q̰iN_M7G .> YUc#̬ Y8 st^F6P_ -"8oz wqdfXL40c:ili ..\ 3c4`rL; ԱkjZ($5cFImS2\ uT20UR&U2*;FwD> Yۏ;(rI`F'?,_-`Ԍ͓GV#nբe!^8 x$tb?!<⯊da\qGo]'"vu'LT,pԥQj[$ԫe)>NE8f}l,:{Va^L#6~( -;̨mLݘ}bQPuu.)&hK7)(9🉎!>y8ƫ#}!Fmt)g  í(nc;^6}8ĭ<7)<YjfX 3lx|'ɿR}:OsB;|{vϞ  짩/ WW@{%%2%EZ-x{PE:B⟷T5?_ibb9dBu!!&!Hy!3y+gVfé|جt@ #Z <J qFՇen Rc 1o?&zW^˿)k{筜p(nvxYlN8VW5>R*q|5㍁/vn ᢋ GAr(JuOŢWYM꒡ 1" '{3}9 dz,ﰯR sD8;tS֏׫HȲ4Il*2._oo`g?*iA<,ji?y,,nhL|r|z] =PainN&``m/7g#-viP-.XL^#WvF$nm.7 4`H7^mg?G!}Q ׽uzdoxzC7  Gw~e6'_ÿk c t|ȯX>,pb$Qš0) dDl%="JINdz~UϾAYeWeTxS{ݝ6(ƂM׬UtLZfA{pL+9,Wl΍Wh{u*#+p=7R AGvc@&y{0itrM'c༡lx0$>#Y77@8lɢտy2 >3AGGF[{+VύF`@&o"'*__bx!A!+z'丬7z6k%&!*:+&G٠j{oqȌh'8916Rs҇>1~u-@fFV-{|"V>}$) Z~ g42/)Nqp{@S79IN Z9N~@3lxC7FeK|eƥϏb22#V:S8q)d 5!S|F8K\PWR!ygDI O&%;M 䵚Տx!ίӮ?) 5̊W9Bu^TX_ǟ#n JWwg㬞vku0tHz%wH߹dV@b:L q"߅bUaU{* q^_XF)%f/8d&E?/=Ys0=e? $F_wTz~m{#CP~֏O qss/缐ȉ~'!{ Qs-dQZ!9~\7?<\(F=A/A\.J,1|Oc&j?TӚiֹQaҼ>bq#>aS)oz2,W ByjCU#0a %PUpE{4OhjY=#UsLg +E>R#p_?=9&83*gxu,"PJRkCD\#H 1O(Z,\1yS:c2YĻ]8@=6U+p~)g?:&NyBb]6)w=lHBq|P K:PQcwgϯ/t p{\*=tl~LND,P! SDM A88(HC2FGJi2_Xo n)5@I`7* ;oY~]wĺw' E (7!?KuC e΂bw7 p5.l!_iY֡2putjf?b\c0m`>bp(PY}(;=@΄kxH/>OX|͝FboF3r!Z&UhE%ih&OR*i&)8a(Q~;ow%B˒F1hqԏ G8T#$v@|>R{cb<"/~Dӵ2wRovA[KҢ[ܝ x]Յ1Cl=@^heԶ  )#, V]Dˎt [7ڝx]8 D%Ѡr]ڿb}H@FOҋRwQN'`quA5ȗDWlo;%1q>?b`"NF&ƫ&?វ9e25?_cr_̈́iaHO[aHa:ХIG aе"7T caS;UӐHq*8t`AaТ|D}y:iƩu<9I;LP!Ma/zQw)`cʍx4i~̠J󟨣W\@D5kIޒ#T[[0c3 syj4p> bo%j>&ּ>]$SaÙ뤘շ@&ҹT<'THskb>j\`o~? IW\co),)xfX<88ML;?9Zso5'ĢFM{pxȏVVa̹ wpOyppUhL=W"jقx5>az >z>0zX<7Sq7thN46@}䖞@ O֣;~a帚?)z{օ\GKy҉bϕscH} vL_ a렦^0*CuGX`D̠yϏ+Tɲx7J#xD7;?$%F=._%׹.:P*IY6Ioœ3./qA&(G?2(YK4Q-I- ,60~ط)i5lC^Z@ \|*$):]ۊ)a@T̄.!:FV2WX5k$<34W@Ɣp4#Sn{4F(m_b?\WJ`bGX1dX|ho+z{s*< ({.-@Uoӝ[NB+ϲ輄و ~Qh`rE M!v(D }B95D48_ˈNdH)3w9f{C@(P暲 8tW€V+yL(7'dX 1} \`"ۃp!A 8/[ڇHsJ )iͽsJ" 33bMU \v.T fxN4o7e_Ci?op.n3'xՄvLCb(L~q;(%<7{~-RzzZy'>"aJwy.CK;%\|Z,A$q(7&LbK8P^s]{CEiyБ`Fo`pĺ˯4r8ߦ\0,} oAZzr4)AH;r>`uK91B_tGNvjXh&U 62kS .-Z3ؗ~}qrD|imF-LjqBIO`vU4_0!!bH&qCӸZa91 4jL9P㴫`?OfjZ!V8~(t =eԞZ"ѦX&b`]1Pw2Ԇb?hjc8HQ9;%Yn7#!*b@`l^X`, \`z!b`l) _G-f#D1Ҁ-)Av8EU:6IVN,%M8%1U̙ Ope RXA=ߑlN' ;;HB~3 wVFhp6v\\XB,coaf%u.~7u*r #(rRBx7`3(硔 ht|bNsy49؁I~7׳{I$4Wp= ;;b?aG[ٰ~,AW`E>XY Ot'NwmX9oK_f8Q\<lE{*tH'Vp԰OVEMӲ~Pyd,6c{Ne`JEh%Ӓixؔɪ 2 \w334GO蹲% ]HCǕuiRX{W<`qKv>2G To]DdH ܓԠ>;??)=Oʬ2HW+3H+HylS$ &,^Ih?)#{:q6d59͏IWr;gL5jD{X"4'$AW] aM}{s%+MeIC^,V~\:8H Zs 2Y=~ʚRyВ-gʯ:^) ɯ+ȗ:5f]&dJT?o:BF1XĘȳ7Œ:V nFCnȓ2#  ;&ҟbkTRe 7ňB&qY?˃L3(~&_C6P4I28[ ińf&KwyaXY ? ļ ?ဳ-E@C(Ph qw{cP82ft3j AsO`00g'`zUVڛ(PXR}E%Z "w`f7h[Y-"sFw߱>~kܾ`߭tsB\eG$8ǯY؏/[4.E|-iC-[` K~t(!7m-PV½~*Z%ϲh O5JՈJKP"6^X g)I,i*A .'J. h4A~!r_%%rk"HMyE U o_O9MGȽ_.8;3lkf6I6sփ^s{. 0ePb{皪O1q&NF#k?!* /%(3Fˏ.x\ (媸BXз\ @6_` c:҂%!à a"@6)9ªG@8쒍 džkg !̄O|ݼ} ($}(MB!wM/&3?Pʽ s7Q̐_烽C5Z? ̤_A.zڏ0p+l\;vqP~GM^/no~ī@tRAHwb~oѱ ggŽW'Rpځ1a^0&?j+orbpWKkWx;.?Z)7܂ J `r?ȯ_[~mFP|^n@_u1g2~k9%00 _O+X&vE 6bL8б|78$ KQ0V)і%bb?j$ !F%-K4ynG{3xfkёLHi0LHv2_{C1/ _7wQBá_ zϼ\?JVN ?>;\U"WakzNobگFE\~C\ۯȯqaddӵ,[%Hh?)0WMkq`}7vMD f[.e~T+|-ASHC$ `u cuX6Vǧp4xyZE]PZйS+[>OCD4UWzR:b &(2vⲟp6qvqQwC\p[rۏ1y~ 8jo2*R3S]ϴA4y3Elover,?s_YP@{ҊP+!nv/|:T2^H׸'|*G]8Jk%-^ U0T2kٝh?6߹~f`ī \IXS~Fu,~_mѐ:CXJ?nGTpMƛ;Άo|A%xir1FK ;eZ*ԇĮuv:wxaq]K'/x\jԓJ--^l{OxѡPC0<ՐY @P{fo-.7rEy'HZ2~AeD>b-hJPYWH΍/fy9? G Mnۛ].?`o.MK7G_v6;^G( d)Lo2`n(2k!4[k׿% M∲XJٴ:yOŲDnU8SZt3I>U`B-dH ~^^uT$J@T1#EP=tBa!8`E$4!#y}x-GYfy_QNFgQ-|l2)r␻-_%=NoXB{ir Ze&MU !Ol{1f7:/5DZWO ŏWiwDÂl?t UQB<&T{;8$ p( ㄡ+#T!FX* 2?{8y!B~{+` ԋ|"=&w>?uhI3ja:"u9؀iJZDߕbg|X:g8@ Uq~~> Q^}$b<5;/~$[>e`qF߶Rzj(`%_R@fk$_g(9KɯYMB !v & &8/1#b` ͐=|ZAooۅio@T#XAܯI,cc"J!cW( ''Tmg?E @0ߧ#f!7. YAl=+g_}n+[=tzgy01łc?)mXr߭1=N[N)S"~>^ fC{+ Rϸ?^$(O.% y$S~~TVSYWnw Y;[%3a/T:3ɇd7ԩt<]OʓT̤K!9g?Q_@~;ϩ8~jχt|{zx_,gѯYmH_z!boy?~~ޟ=#+~CE>= ]X8vyE9gmWwxvQcZ?}wU_[Tt____?g?<|럿._/7 y&?W?9w7|_i_LVNmPEF!v`% ,6%DE"/K |j+k<>9`[(<#$>99@5MKa|jzي+*!.!00~R8ߺx[KK"$i?1 g[|{uiG?aLIL cv~'=]H_G ʏ}\Q]a=dqb"#\1%^f^kS$c #I%%fS&;K!q`EfǦ*i Q<4YCtsEYJ~LFq~u~\#[e{,zHkk (ʮ=l96i'ﱃc?t^CvG0H)ށ"=ugP`AJ 0,]ݾcbxښdow03'$XQ5%63p-'KfG" ᯪ2yj;|@Iq?/q?17:(tuO6~Z =yvS1~14O_2;|^ѸnCf пM~OjE"H1Z7@o;<[%&8El#߶Wbe'y?;9?0".TawE0AJ@"7-u1a/TLdB ⵴QVte}a?£}Uio!u]#8\؛s( 8ꅕ#L$hc z P[+xD&c@ ߭kp`Dd)S ͆_x1H:++h¤*Q&@6f{ӱ:LL2PUWZza&4,_R!3Bbe`WC5A!TMw~(C5?؋J1P^ſ;fW^u ҩVώr8b2 7uCE  ~R;EP;;zkcŕU뼃Ľ- ՚"(Ml Văe&v3HS3ߖ?{2͝րqrMlarJ2ypE~ܕ=eâ(}W_Lz+q?ȿOc!tܿwbU \&?O/]/~|+=fPm A_):m~mT>Is8lTO&AehF ) y(jE3둻)*YVJ׉<ϟ'hvCGu?7 !I!\!F mf(f4()#TYho聡&D֦M%5PdoOt^pDAH1GBjm`=}d 'Өl{yڡV0EZ5!W|y:Π޾f:e=T/H8Б1eoB{|WOp, o$15l]B| W'Tu*HxnUPꂜ{\\PS|[/$IK1La0 Tb1zX㊆:D?8Nu9[Gxt [$q=74%wFhz фʔTy8ߡ] v_/1%~ٝ__ Nk'"&}ʆ(@+#>?F4ȇA$8q$DYR²H\j9촍ZBUie|rD#y(XT 9}C`Ȝջ"{o`Dco!/ï@ Xv f%OCxدe? vi&zC'\dF!P.]E=Mť'l ߷w$:tl?~zFTZ^ `Gf-3`m~u(@kQAZ4[4 j^*>Ԥ`kYx|K!RtُRzR@>8y䅵P#3DfeW((͘V3m`Z)9Ϛ.]|g@uLjǞ ؛~'|(MT4=h1Fv_у{5lxϟ?sM|??^v3l̹fR.qa5G#\΢ *6i ΃9aIؼ |\hL]+=1ǜWTh¶9 mw#k, ~;vc'AN^j`|g1)0W7~x!.fc6%y~};o’b㡥\PdN*7 Fcy<2Q{-d$rchtT z:4RxuCs R:N J~bHBs6mt&4a{p$UfHeFuk40Mv>[i~-moF{&Z?צ"nf, ^V楆I3aPWw''f+$ZXsnu^jl ',v*4]3Sk=fCba/I8!Z6>jhqmw/p_$pMQσ`?C L"pG(? {s\komEW\mQIR Õ#֔ p<@ .LW}lj?{>tӤ{"19wvI$9rb畼 _(WI(oA eW){8Q]m2~j/ ?cy对K7Ds3:#27=wwBm}2Cן8qTk*NΞAO Us+sړg#4٦8_hmY6Z~E;qPRq=D99"\TwM~d|W#/(?=䴱Ai3u=8ZFܵ>6u"-EAPKRh'1+XfT:/s+~hO%. b8ޡs,+%W>\oS2ڨhVWoxA wZBr"M +~SSI ܔUaznr+suON(c GաR+='xˤCn)u(ْ9g/\wm]6Kߕ׵1%ӮO99K9xǔ![*X6?үt (HoHGsަ(Nf}?x k0\lx= tP=_aKR2Z(FX~owy3s?.5n͏yMo[>5&U,`[|]ŻST-?F_)$14H^oopC'g>Bfğ1 #)3vaSx,/nŰF~$Q*]]翾~GI篚|LYy{ ~PNh D˔|V1 ҄V?<L]Ar=3H3YxWL ?~hO@LfW eZ5y>ǯxW#c6w.2wicY6tDo,9ׯHCeXT?5nxUT̈́M|-jGH^t/xD~E+T~W[g[yw=sA<2" uIRg^iO,r{1lM)7HA$QJD(uacb288;6v#q KД#ѳrkR ❡}|[FWi8l ԝ E!7-A:ox7|"?gmP1(:ׯR!*Ee1~%,WI{uQV{H QQ|_TSV1~p_O?mEjHr *Y67?M!yW}h\s`4ZZA&* qUGmh6Fo%Fe->0A*q#72$$sŮlav5Οեo8^?~_Um6(#NR?X֘6e=l2AŻ™< "7IΛ—FĮ; ŏqbX"ZO|iA]/`\9>GRQ=y)>N\(yxr]cS'd׿>T$1H5| V[UhBگ?YT6VvWvF/]h`7a %!sͪxe+Ox]CځUiAFeMOȴsM1|ٶ6 ,36PB ~ g}WᩬmZ?Nz '}d劇kIHt+\Vd:|񵇏ArA>פk_"khR5]#cȕy*FsϿD11g;{n'd[2uȤF%08;>2#GwXU~ lxS1b1S538GO8w0.̎>Zz#l>i|? ʌ0w_82nH٩-_IW9FS?.rHI B[*4I`m e*0g^(M6A^ s\n5Đ0i2A'TPJk̬] ynZWA/?*-l&!F`n\S> [,X-,0ux ď`Rcjb",M|)0Y42V׎oiP,:~Z'6A[;:q7ٞ-P8j>d!fnA=U \M*L{)}+ YH~>탫<_?Ж;eĻlE`'fqFx}`T4(i fCGjFL@e{zH/[ 9F 7N$qGq?!kGtre?oUG> աW?Ȁ\dcз(ߊNh.gq:C\ND045J!]ZU0Ro3{ZJ#_M}DŽvpn$Ad05`]#+#GZ.^pV[ɢ&F8v5fkΟc|zKeCY{Ѫ?tKu0h,`[*z %w~v۱o#3 x>107]^-* Dm&p?M`e䌇u7KǛ Ê|o[jg3@Ǻ=R?~cgl*7 БHi?m!H%?Hol0'r^roU(ź? [F貗QUfɴy}:sc1LZ:Ю3Uc%>op&,PG;Y By9YY C2΢.?gŢFzdM">bdiSČa4ӌDVk%İ͒w[:g69\B&'Htt$>:jy#U ɻS8p&{(ꋔ|W_J;g|FV{h2v&q Y BvSSw8;9lLmOn:u8Q@}ّSf8/.茯|?_ꊝf ְJ]Pe.9ުBf^/-]h`ٕ%/?fΨ z}Tk?oq{8}TzvtCXX|J`m{mWZtMTy+cw(<&> %0Ih4};/:.R]hQ9d|Nڹ72;EC9eJx,Ǵ#8z)P6&֝ΝSrkmmȇ;ZM~bHX!9FEXrWzJ3nr\É0\2ZA*1emP9Y4<8TϑǔJb9}֏򪰓 ûu@ D=wm)gsq*$'+Mar_kZ>LO]2հz.V7C%y̨`KQE`/0`%1#ܱzݩx0qttA$p>"S(lO(i-OEĐq3@CysFox1lu_sr(79mX"2D̽Zn%K9u%20 Kh/MUo *WAr|Fu|=9g:XʺCl>Z" Eꈯ鯫L C# JQgjWi "m\ azgVV(JmsY ڢ[$\)^qxVSr<_3hN WmF4XC>*3Ũ drOLbpgIq, 0 !rX 2VTK7&pc; ʷ32$鵄rXF[$-F!BG&|i&5A.΁@P棓t4g0_/p;n/{3C3J>aJ a$ReIuo4lx BW4uk\vBbeiKᙛxxh{d Z9N!aL0$҈9V&&B6!DhG%\1a*IaT3ČC9X!lRa|>7f>OVS*RzBn>+ݞݟ\ \<`)3FwJ/ N529Gw 'wiGbgɄg27G|@)36)E `>J "{32l̰b v 9Spx'ouu녏^ KЩ&AcHP3X~!MOZBe ^bAٶ`%Կ X%#Jz.N2b& KЕpu<[// Jk}N`h%ߙ*&ր^{Vjq[6j^KpoJ:nGlЌ*@9h*7 TZ!GAv섀 ߊx>Bh5եl[6/d?RǏZ9_ୂa]|H8[> Vq79JmQO}?z%)\*\?XC. /?=ےdOXcrrCʯy^5)F|'9ZĮ^{½nӁ6-?AC.h8p1PRK*)VvN5U"3B*Di֯~p8{D{RаVֹ:4?Yyh00 )WGBӘ)S3ީJ:j#^1cG~?$FZ6"03fR};s61z SZyڜ!GvfmAwuY KYG+3Ñ!IRLV}qZܬsTh8lu'tﯿʁ3fk %":qYƊ_庩,:vReTy%e0(>eEVk*v*j,5 93~6t%^XxH>W;Ҭ'oE)r6x M\Da~\ov$By$x3KnvBNZ"%4N;z7VHBm7~8QTClU\Oŏ[QMI(Z(/Jv/(|U[,+?99~q`o[>+F 8U0?*XF!1Mbȼۙ=0`o(;$ǀ`{>귓&J.@؞1 % e A_ !"*.3;EW%T|#XvFƕ N1޴j[gOIubdӜ8Lv+Dw*Q,~꣙Űj,9v_$Wܘ|b‹q&5E`{ٛ*>@qcq89?>j ,w ~8nP"'dB-Tcޮhn5sX{F wC5UuV@͑S:7>:_&f WXÛXTZd)04jSƏ虺ҼD#sEE1,gGIWwP| .Iv5Q%^Y$Q]Nܣ̓qݞYUYj>1L:=s(Hz )prVs La ry}KP{F՗Ŋ#~>iS QɖR5T}s_zl9 P#zDb:/jx*<ߔj5UDyfy5I?!e`mVbU[ DJxLwFqM|]_%O xxPgo3tE&k!d}J{ mz32OH L|8-ΰja 5hiIR:B P>!u xn`J}+݉~z>~ZFۆ]L/a$.ዛRJP|)aLj,Ϝْ}Mqp&(g7(Ŏsbr( **@ WY8}RՁ _ڒMb_wΟ:\3?&PLG)Bs X`e¨\e9"wZ!e5j>vi5bHL'= ν Xٔ*I[s-ڈ_0yW §^9T(fqi؈z,p$%-rѢ7?!݋q=wgHXJYzKCX CKEQ}Rd͑=YBBBpW{ʴ$& d01jo>HPp|[:! A=~8iGS/S*̜m#F;ؠ~O :j^pwgfʤ*L# Ώ)$h5_TUV*hp1JᶫDz]_Bi<Ipq-ҍ?ꙅnxk(ֹHJce @TpέBr+6fEPd z*ˌf{fZI8zak5F{Hk.;]pYE@͌}.Xղ$C)w\.]kHCMJAߺvҦ/uqI qk A0_;z?⋝Anjݿb0!TkX0} o'3}}8ěrvxu#z}z@l}y_{":W-1q[[ˁe>?R_[[cOL&@ T"=a!+G0g`U<~#.g:rTo/ ޭ|jFLj.5/R~#W.5NC~ <aM=`paE*X,&%gp d_#6lDaoBT /@@ߙ'DjP i w%M j5=h=rx~]+mA v6'+/`wQ_={N {@B k! x{ {'z0hB_.6OH?w'asְ_B;#6嬍JvƏ)Q6YZ evE:jߗtc,ƶv=bV-0nDx9&zu)204K$JY]`"#̌0r g9u;}=xW2MN+U}HƘ-H}֔A[OqFZɕO99~N\ok@[rW5BByK )ۛ6y)H5 ':ĸDnSזVj]{z fo;:^@)fM8֮jcۅu JuԐl.1 ޤXMv B!\X~oW!~4y73\G al"\F x'yN Eg-LjQ$Dj7Z=,zlV2 fDq\"H?QOI<ɨnB\4E(4H{h%[;?QJ{\ÊVC[7(mu1m>{?=]R%-QFie{h?L@䧬#55&S9QJvDx.63K: d4 Vsi'?+JfX ,R$4&5$~)] 2|MxxFj/\>-:9}ٓF]/8*&7|HObI-ijK.J"bl50--[rzW-Qx6:CX0ɕffOlsi-c7[>bB6&Q0XBh Ze.0m7ƷP/&~_xs8юxj}3[@(zYJ}G,8ɶPܸ1SN(5297hkuR/uCR(M$!U*^.y\Cv\=Z1|LKת(4i>f33&%iK-$nnR(ο2^M8qЩ!crU|/Vx.$6>z\o mAk(]tNJ(fthR(ChwOIF37Hxiq2@K 'i+?d2MOp aYM ɡR._Mή6"}_Cclhض؋/㟉Ģ7iSDARI*U <]Nz&A2Yax+Fs>_WD@ɲ_E؀tWcsyʷ|Q ش϶_Al5O|"[roZkI/5>tz950`bTlT+o7HSe>T, ht/jT70wdD kt*5~_Z|(z^ g|iGqoK z#ltFU3 uKWv P>G:3-ׯz$s}R%!!Z Ta@S[,~@_/QѤE['rx"c@32.r䩀liDiӕîR2<(N-T^ܜ!WWc2rEO Y>?0gF# ۋ0Mݦ2A߮&(ǮڢBR5YUbL8,Gs'Fk6z.5O9R !_ͦTl#~E"ƔQD tCn@V9bwM|?qB^bjglnd]Rnath6\BץM!HI2EWL@" &l T3˓)([b1xԴg 9x.j8x(W{3h4Y"t1$OgpOFϸJ'3r!x pg6.C-ŁF}Ha9S,?fIR!aNhN5\c*oU,U= 3޴Xe;7VJ^RRY kF5y75 p3,d; 5:um+BBmw.Q|F&f8B qsx1'nK'Mw,F mS$'L7٭ȷ-6r?^횬 L ˷7|j9$wh[GrrWmM*i.NTB&g) UCq;|/(nBNp8kEx]gS^U?u9+56 (RhB~;5$}c=q-R鷵?UNIX/]V 2ZEh*TZ=RJ@(l)̯UT ͥR{e",MP eͅZSx6aH\Le@~|?\m( RίҁˊO'a"@Z3B n;9_+z èfW+]ZdLq26"Fl ěVDNS^ȰL!(z`'lc~\ ̀Q&+%F2d$`hj'0o5II5o @(U$eBШGv+ڭl60/5GT Mͨh01y֙q`.?PY7%?l}5d%"-p9N 8N7M4YTAcFjh_!3*AdwtL)hf6lrQQ/깠F$vMS"s~yPY\|p0)5UUHP3E'DŽPJȰ5U c ɪdLi zE2o5:ImzUoC`@ U@-ˣњ` FɞI0dS%Aǻ 2M{L҇? |L1GHpet޷"kzqzM9a\S->%T1dwdA©!]叫40Ӱ5{ˎwgθ9ŏ\kX,:AxaՆ7+l tu$/&)FTG38Aܮv$"8=dm0 /z6_ ͐Ǟjs4[ @ws] =l."J{(A{G0`GR! я> ePYwi >Y۱IGl~h9Q\M)*sidB?{|6׃KQ:,ei+icnsK'lc _גc'MM q+V(Bkd>F3hD}(!E4lg"1FfQ[`4އ>KaYʦF^H Hnp,Hp@I:"}F(,5N}d1k0 !i$8Cw!P}xF fdsop<䙜#k.<CaEnU7Yu8Gx$$480G2:/3T gtPP]4JwY evĸE B*$S&s09'kz% x&[~?9~> %k)9xMU{Ӝ0Mi_ /P/qϔįs0olC|ʭY2@ĒHo|5ف޸:=l_Vzc ?SPZ"3?B1ӽUUb$!sk Ǖ-}d͛m&%bx0{^ i>}Š9'){|;_hkuv|]cE _q=?Dr6AwP&j" ʏ[VvOuX.7fRljwW6/ïp+ yֈK"QVX;Ls4M٫;%nYV/HexOK6.¼5?L6U ]Z317} .kzq-fQr 72ͱe˼Ao,L.`i+ުI;HKN։ :kt> .u/8O_!'ƾO?tJe霛P}=8S ?Eòz=qw@y:ΟUɚu=s< !1TOG|dIv_wiu2ruJVu#[[Q4,ٞ^ɯ_nRe0Z3)U T3XsfP]ZYp5dW9ny9ɽ^2ʗ6TDP.; b "07z /* @yuos⭴is-ܛ7e #!>BxS)3? @X=mH7|Eduq3R .am)c4W7v OC+̳6[k䕙^@񓫭N$kW!ݳXmY:M,E3~M~wwbs=s7yxHՂN$q$zT팈h J#eL$;eOa gJT\ /yks#TDDtn0N:z hj 7LxXm`%z`pF7kN z`p?#c|MqTf OAO:8PSJtZ{j" RTYpX6P":Ӛ~I0mUX:8YNj S(4F)ȶ(0VsxCecfHq6fWkρDQh'Y !%qO7 |DɖoX`JBW/a˃S `2 &dh[]0E:V Lukbd֋ brt$Y Q3h-'?TPU$E"Le>Ѯ2bp΢y۪4guaɑ 7rX)o]>-6ݨV:SgxxUi,)jƑNUbTwS^tKqqzK1 j,Ag(1yr\1@ = AJb'̧u|b7}'b) yZҫ;QS v,/0Q2ꏢ96r0/L#-l;(=Yio 2LNk__rkWՙaT[ Lwojɱ_?јFvkX+֡_` Y)A.xy0wЫddʳ~fU(X@mDptb>?s{l& W(!k v?0C=51efڻB-|&+J0wQ)78dbl;2LUYbj*1FIFп_D9>4 oM%P4' Jr5@&lsuM--QMy# NVPZC1ZrZe o派RxG3VPɂRUǶ蕠<o4hfRg:>)Yy_UmLMŴ=T(AbDGz'5`=_o-JG_͹=JM;މS%~ȷc*:1t8#WS]J{_e4uj<x{.SW+S[zN>̇nwRV2ڔ5z4V҆w&?`}2]+d)L?::R4$ISpL\ZIM8,AjP &|#N(- ڒ-j(fM3#p}lR,Lu&*ؾ lr4pB?tmo!-wY>ǒd:|[L#pfX^T@3wY1zvDCiJk YN(8ww`@dt ?Dlp_[sYw>1E :<~ !%xXF6ׇ¾M]ˌ\͇Eݿ5l{]^xYKђ9Owoqlt`do)JU&|bB |uF1g{#2,9 u~LlOHyi28\t-K1W{A!raKTaJwDIÍHT bH #N{6i>3i&3\wT*`- ֦}cBx[4l9hf#K{#A0릥=uPn E~eP,^l3[Zp^UK x?ڄj{HQ\s ?&.P'8hL:Ms,_mXg,krY7&EƒVC(mgFu8 cFٌwt5K]' c(模2f΁Yx3 D%N_1첧m. rנ e8F>@Z$Ņ;XxCA+݅d_T~S6D-"5]a9Ii`nhPWR~(qMvd_K+aOs6k}STL642bՆO9^HCè'xx2a$Ҷ6͏$*6l, #C ~23T{)Ffxg@']VSv/Bz˱fOXINGzAq`:<)QoFҜ[g|Dl{hXobIi1Rd.V@yV_졡699~m<ZE=fe`TG`2<5>3rjvH&dV}.h!X |cX$I3E c.|8z˽L7 ҀvCŦA!OP@[z vyJ.w#}ި@rq3+ZeLĢJ4\cGO y 3KufN|ɗuW:=Mgk%X:[qg,I,;TҏkX(XvV.A6%UcC^=JM)zc _U3WïīW,X(bSjm4H3Bw Q Dx;)@1}BO9dP*!oJ* ERZfY@]* o[\sU_F`ӆe]o/'w???ǒn17ɊopR4f"#zl6SlM! ڒf FzŃl]ZEocNAxp^֫XvlwOvSCwP0DJ|4 %Ԇ/x(x)f38ts|;|;uďOUwQRNZ~zXnP9jR=$_."g !@µcEV,V:Ú!}c䈢yډy^"ZDk҇柷tx^X,;W\21ގ[o5eVd*tz^=YxpU 3A@>@O|?M{kEiݥ̐i:j7~V /ozRO?pd )Z,iDْhwXڹOz">./ vZG\lADv"Z0ωxi/$˸Af1|ȴr6jMis>T$ۿ@gR7-n#Gޤ-8 / ~t}e:Ǝ8tZ~`lmV#|I>`mDd1|#?qQw~Q2=ifFS*7UĕtKh_xGvw3Ycd ?>Q4B L|G;މ>DQ)&s/FՄMN۳wAUs3{|qJbApNDg=pC$/'Ma"Yuj/aCk:LK+v{W2U[u]BTꯦXN.j-F?>k΀k.d+Wl)C)w6feq=٣1Őq&JZz2쎴1osаQ?[/̜_3v.IT(xJbx2Z[ jтLiໆKYzllfsfU3\*P'3Mx|o2\9 ce829;ԧznࣆ#j ''E&2t"¢c;շ:7|)Kf|:WWbi#e~/X/*gƌDa3HW<87 JE8[l-\(fu*" wp'L'g%P?s \2x3Z*S?nٖxr_ܗ+Dg΀ִM5nJᮼz;ٶ@;Xon>G>kH]lMQW<(zMY{Dӝ`"SX6QP㧯0PXg)YCi ꪛ+1ud˺9ݑ-|499~\!m%Țow9M;X RtY/P8$&\<<<nvbcnš؇|UAb!FcHú~Gj(&w \97e!f{< @d =NN"d0Fe36.;0βޑH7ǫ&kxwxAe5l#*F $_g¸-7z|ck"иרo=3H|*'iׯ1GSxlfQF"j&a!4WI%Z7[$YI64gjъ*QgY(KAmLБ:@.wBoz{,dle7 A?,cᰩƈY/y&$klH16C֗Y$ x)CpV[š8\VO)ec?p8<?]c-1w0 ;l@֋1j, EXjha, S8A6.v]_`$֬;6H7R%'{2b,͆Ɖ{9b+k;uX(ꙌJsc]wa`Z|;ߵܙ14`Cu@*2>_ Y[S!l_ dͤc?}nεSذz.iqk]'==Y#˲RS39>j(\iz0~Jω\J`-ٜuL G`T4N`ji"}oI~ K Q O]۵)^!+BHD9-N:Aa _78\nVHhV6EKXl( D痙uƴJD%?^rvٺ3k|Gl[H&Q&:ZJRZ.%:$a[2Y\LomQĪ:%b; \?/WzT#rJYIhZ:ny9W&'+psNVVPPkE7J_d|W5iue\Gϱka 7h'vPx8J ,k"$bJr.1īe|Sea&9'Q׼Z)v彞72SIS9ad;mzB;P$gL2v|m_W׹?ҽ-]zlWwwʾzIJ&mQ#Uld3Hn ko8 j 0l/ T$WsLesin5X R.5`yW*3Ɗr#!|.pobKc9jr e h[%2~4DP9Kno i:T|0cQ{F?8#V57\9fؽnLvalUĕ;kW$s E˴S~bgӗ% ^iYq B֓P ٗkb7O 1HN՘ؚNf]duNiL["=HjQy(o=sf֤7mcô㿚M~%@o\^8dxox49 #O,ߛ-:HEnbH:mD`vwnZ͚'9dM\b>nL㵥!Iduip:L}}˾ȧnu6.̆cײtw:IG{첞$J#hGK 2*l/4rFSri:GaKd~ 5Ejơ@G/fY՝G43XffpU3: uq.Zqiԉ:I[N ?7ZBe.ێfDEOߴC8t֡_N ޘvɆ=ZQ%,ݾ ZT*)ûv)GOJ~B;Exا4+5m:@އ&1dv'XC L1U5]ʏg]RYyɤؗTu 1-/0oEs!]$T:M3QJS)ܪt|ff4kv;i:'7Ɍv א4w[+f57ʇ&Za^/PS5݉(5f(vFҠU.sۀ޺d2KF=  ʷ6Ӕlwӏ[;{ejvJ4ED.;{p E!1|t&h5Tzg>z W 18s`GIzw+'{B%dzx3_k#uj<}S>>J^sPK)Pk!0N9UMkjO*`II徖0Q'y)4욕HxoAUtZ;tQ5_r)@5pSJ֙<=QuKRw;u)hADy"ZCk!0f|ܞҁzfٽ5o닕1)Q#]B@4]*|nݫCosDt(ZyM*xLnMW3299~!eS72Z3g3mC"lT MWa>?0vK0i,CL ۮJGEhE ^[s oWB@36Dox9v 3るєۄv?luI9_6TD|  rNKweAz*ؔ 6|?8i2 U&fsH($MFpO󢉯_#_5c:&>^1b״`\9R)9g2?.ʕ$t1˂l-QWKH'ǰ.{ڝe 8$zT竔r=i LA.1mWuBHþ@=5?\aX.xtAH&_.GoQM'DY#V.pgSeJy^ӕ&rEAL+AS={;h:m Jds<ޫ(M [=ڣ1nv oI0T O kboL=P9VgMZ4j]`"*O?uF*kliE, k*/Q\=|}!4֟99~PWE;{7{ua[=btOnѭts"oUۘh mZuAp afnl{Oi:9('nZtbG7]l.tSjVr-N,7X)QJmܘ% 8T^)Mwb:I3(-I,=;=DBPm#> jqR _K=$dGdnZ/O.|}_Xda&e>xԦ5sTÐ^}ZSƭS KGCxV'ngIxG1m,#G.b(6Zb{(NAk; =g a< &7* 섕hh'(g Ma'MMMIya2dl?͌l3 q[Tba+d_pzwcɋ9IӪe}{c ;"Klc90ߡc[:ƥ0HÚg+xz< -l=X树p ]|2M`g=>1!X+5#[駔 iM^&y7E5"6_m; $?Cd$e4N?&*8t0Mt<(!-POij M3tpsX >QbK y1oUIiw3q5F> }]2Xo+B(\.J=^R<"+b س&7QiIo (:@گ;RPw ) NLkgҩꄶD$8sn@rDaʛsXI)MOD B!So+O0UEL?1-g|Vma[Lۀ(GcǼ< op@Qdc.3 9ܵ%gKЗ7T.*q΢4TbJ#L*&>#+]z ĂEIzD2k)Y'glcAfӭ( .))ml ͅ[[>8}x?R0(n|vڄ{8,9}̦BNz B"]bl$d E'|S3G~;MVc3JDZjM x3~`e=巈g4H3=QyA)[r%K0 mxGEYC~'[ӔTH[Ga.s3Eb__;*|5ltފ-7o$R:$|h xm 6h'iRD5|T7m[+y1}Cuєkqo띚99wznWOkl$:e(Z[l߄ ai% @_:[ 8!R,R;-ތe'`TvƅiZNI# C}LZ]vԘ@T+tF\6Sxs*Q-('zC!i#a`8"32tàV! WWL{QI[Q+Yl&gL|4qdlSud)3ͪO pn!$x50-p;lTjg#3|e5U&u~xׇxWәjq^Ѥp(XC* r=FZ;iC$Lt @Pw1޺!=j2 ?qz@LЄA={pCCE >k OHOsh/`KDa8sn=~dasOiLNNLQj(,4;~C2z(ۋ4 :S6vӃ֮~ \v|ncp!OpyqOx{R:O`#: Пoπ8A G32w 0 , )Iu &ıp+ ?*4\)0 =v l,Du/C@>c O zƋ*~y Q|b6AH( j1e-0?W?Қn~W9]9NHK&Jࣳ":|4N=\5J#q*_EL<@kX|oO|$N\mr?Ӊڈw|R.dq2KS6g|p뿾&HXZy 1i"%)((RD2PmdQBS>FnlOZE A[4P<{~ĖzBsE65Phi6e8WJZG1 D>@W[ Rs5gB}J\-cZFhԱVZy,@Lo5!hʂ^^ep3VChqo1<:s_(b-:2*KV:Bhrt-%3M[wCT54IvR}9nO7~k  ^L@~1_Veu4OFmh}$EJlъ 0sKz.-d_kK@&Qj{T "ȷ̞:RpֵGуӚ@~= ȷ.v}V}\26vVjFp楆kP ZAmf]>ekU*Dx=~놛$4 r#ăZE߄8X 9&%5WK'#A9D9Ls"×k|Q.c9&?[B]Te6[bw.+hnRfcLk? yvzamxDFx0osyt5TT78hM^x[x\WHrS>U5?%ɆG@=*v?-!O{1:ə{ϜR?++fnyC -S-僆\퉃@cb#zlrxktG[Y3?H#OGzC_+.`P(ъ76߄G $3~);_H6҅G%6q_|mN_I4MOS4 ƝEʢ^b&*[IYRmH%"Yt?XJȠ.(*x}B}3t,g>ec& PЂ5(: -2^_@RW>gsc4o|,"r"-c$oEhGן^=80uy -ӔO`Ug[fmu"'p?"N'?>Mvw޶Dݭ :UIs_g߯40jUB.!' %yޥ߃,d4Gfy;LA.wj׹D3lll6N )an"n=LGSLj 5y,&va!noa*J1} 7axN W$20gu4?1 x4 @G~ũOJR3F)~GLûՁ6[yêAS xwO|;a6LE -ka@ܑ!B]̮F^=SΤՏTlJp_{Ah&+qEB _ǏK9❫pVx,1+c>?}P4z 6d*,Md']Yd5ybtf~5o);K7 wczuXз#'bUL*asX `ܟ tqy@ߏ(esD Au)Kgqiy pkxR A1Y4A׃<5MK@=Zl 0CkC볤r5`$zMiJo_{=^;g_6uwK!Bs*>Qyΰ yF#?L~ySS@IG ^x-|8s3O2ɝ]^$z&N*#vO.h%@5xhp?wҽ!,LS,T, ;Y 1ڜg.bt$}";|T'މ̐06f~2 C$$٭߀_\|G-?a*3v=ވ3;(F2r|c"Hu_زJm_t<]*2N,hhU(UC$XmTOEƟbfAt}l@(Pqr^ȥ?a@BEi6!)ҍQ0rǬTXV"vn CCez9]Yc%Vx mNٸF9`r>@ٱL2d"EVy^`C^|'Y\ ѵIi;ԏjJVC54|KC.hX%q]fO@oO-3qϣNprцz+_ ,IS06X[֗:H:th9%Չܲbѵh|?kWIghQ-|]\پ&'uw<4;m䉖㟢P*ذ'Qm8rȤ2f9}HL#3 G|. x'r!&<~#a"t4xMpiTisK;vFcDw7HÈD;YUp aoԊd/$mC *}a\ e\2 BB{ lP@W c|80_τ!| .bH,?F_;-s~^<w" 5L\PPMoGڊlng{8dd';=8 tȿ.Ԙb\9P?HpP A7z&|[|JZFgSn [Ԩ Y[pUz $e+!]MJaں]U 7r <񈩾.Xg>u|9DoQdŢ́$=E%(. ̈a~]?8oR?5; c c. j<~r}q,9Ƨ?'=:,c]Ȇ*gԐnh(}bGvzpUS 1nʻU{4kC I8?h.3FR31!0uʰOlGnŧ<"F * c>\]XWk|$?|Imh>M>U&w\>HRJ oNHI< Wh8EziH?>!?Ga3_LȹS-[t(>|$QMު&*/Xͤb{cwuT}qXӜj%4l DGPҐ_Y-}:g0Q.Qfxjd1 ei起h=.R1IP{>~Jn2΅֏qyC75K7p'}Dۛ.6D2VU(_0;, .׬?I">|Xzj,´8jQt9e x swsK F'dLDz]i;Uuʖ /dpy=%~8dKUD1k+ }}!Nj8O[=d.> 3 \GH$$SB  :9; P5gjl #Sؕikc7(<5ixW}Z )!i2vw^z0c <(ʍww^A.W"RJKI<";g|nQ!RL LkPaRju Q{O 6N 聯Ap 'N"1N'0W_uB;N|jC9ZVj{%FV8_A",Z?6lp#th6KN7A 63B+f١aI:hs01`68q"R.SSD %r^E94$ڐPzuArZGGϿqFORH6礃S͡ C\L"g>l:ao`Ƽgd'Ak(}u; ilDB953olTyЙ ,#&GOdԃ6Hzo2.6_?Q{^ ִ?DRtB41_58/{L/ujF2J5@(;44/Ozrt7SL>)eb9]^pdq~3I_jEY:.AJQA$nop%Χ ы T<*l -tIпo^CA+δx _xvQ´W4Ov7{-z^!i%mPyK_>[+2C{bfIsxg/l\l|*"4i@̫ȢpfB}C{Dpd(XKmo~oBW [s . CF%Br"ѽjlqG 7+9I^\OB8(M^ 8b\5򠻕bZzd몪\s-M-۴0y|\r_]YDQE5oj'Ӏ?ъ8|R!IIi$]=W]x?`3rLG?MC'Xx~ߥ/dP"=;վTj.rG0$.8Jz91n?WE@Ùɾ͝w)qY+i E6_4qrv/UzTzєT> WrׇZC3F7y|2S=|ȑF'n=_'Q#U9Ā0\bWz5e|=:__goUw'E; I5VҘmH1A`}](K?@mZOi*(lk1@6:4O(gAjV1a@Q?1&_+N=;mguMp 喑-&!J8]/zvO Y>h{Ir1cvȮS<_LYh7H(d5l^Bxv=O9Z-N' ٢PfL;)OD;87˓QC~AOs:(Pqb{-!˳L 1f7<1A. B%4-EU@Z`r:.[^Eni:~6666~AtCz^b[Owc?Eq]mD< IV^2_BaP:^aZodL%ۑq')I7yucvMRҵ>!fZ %Ú+*Gl $̂H l^5<+ejEpܝ&ICMU*m'wT>]x?ڢb$ɼϔ$St^8]l+"Ԡ+jX̀g۝=~Gs{cg܆]rsFZ8[fk[TFdS6 ޑ؞MxwF V.j8'^&堘BjZнx Z^sCE{UE:?{LDdS}:ҫ[C+!k$9>2m?']o[5vqB"#ڜM,F $-xTv\\U pG*O )qZJ Kf?!>C#60>=Ni1]_HI `G "`Ҽ;yQXAzWi35=ss_[.5[c)`/]ML. &`eq?.g;A.ITQE Q4q65<&;k6[!]/vRWwѣLP+Pfn= F!:RkV -j~+xjg|'=~Ih%\% Z-Ǹ!+dXЙ*C:&dDt4Zή9|sCjkF_K.YG֡YCb0AN&Z܃UaO}:,:WT3ո ~ lo鷌M&0Ȋt}?@Oiy; [=_dž.l_uSk*u|:pvI?*u(% POyV 6*v{6}1$dzjZ8sؿ06 T'nItq¨JIE C:E=k2.;rV#5y]-NFQk6666yݟW\Uz8ۨ`EoR^w7pA>쑯Ē]Q{ gf7 [vt8l&Wlsr(@|Is'd7d& -[;.uIF·uIh(TȄnR{(>d(EYGˏ0 |}, m7 ݻ J`HTrda OcJ%".p3 .k׵`Bs }_;x\k;5_uaHTrڻh3@^}̈́?6q QtݺzVt$sSA; v-p ]t@VjgҺYO(VN/U_'Ȋ~ ]Ϻ c닩^'tJ4IY&puG>]W iC ^m.WWM攄l] ,XgCndUuToԼ@*kE#*)J3+^"|ՆN7-Sc{8ߤ@&#'wEÖ /FB(+_S6uU!j?9[ড়Yt09i!ldt=TLxK\vkFЌaccch ,_~_Ny%Np» j3@I\ ]ՅM\W-ʭx|dԌYx9Lm#>T e|O0ˇs j'p {%eq/S'w92`yt{|@~_6_N#s:Lh*F3ng}ug>T~7ax#j_x穸g6x(43_.&j\>a̷'>'Vp(n}Oսy_{)rfj, j57j>G|m]((~ץZKWjQ '<떇-y^MwTàhː3O (|B*x7:C#4֧t4.o>ڷro8tAJr)"{XQ ˗ك./W˪HqJ _K)\?%ǷD@SH\Oº~386I,uv{c)*Q4el8z/)\IoB ]^>ʭi*GL*޵u9T-|l5ͽ I1,J'*&ܯ<-8qp^%,k;>֞yz)GrC9ڃuvVY|}ogD_ӷ7Xg ^A#2_jիנM #% 5~\oN%![sjȻ,gvJydN "Oz/\Ks^F }oƱ(#s}zRF]:ݡr2?!$T6@ Ӧ `QZ6An(QbvyR^wt跺U666~U\{w8*{ϫdW yz X{xΦhŴxf=h DݜNOr?Fh-Wm6-FNh6Eڵ(~_Z.IRi~۲ !{y!D\Ou/o]zl_uYD源U&Sh~{'P(hs'a-⃀e6W%h7 $Ø"CpNy萑z @ֱ$T%r{ÕPLع-#5.E!Zg+iG 3׍:!~ՄFXn}]>ʬ ᮊ<ҬYf7VѢ*b6Dϵh.ˈ{^(=,XTy:f:}v̕kv'7paєMy~ 'dži6z k8<5d@Uh RkfvUkG ouPZ ;l<}q Qjy.^Wݿ|Z_"b͓ǝƺ%a}=Udx1x~/-P-K||W!?E,B۟&z\45=񆂑IA~q:]MciǑ>Jd7elacc7]>5R r]JC2wk5= İ,Q@V v6y޹htݳxKtƦPQ7>`F'@w4r&AGzU% t/CŠ$qS ':ug;eJqC: 즙BT"}jPbp8J˯ϲ0)Jr{NiLU:"kHɬB3ևlB|&! _gO1O)mS†C(SI<5uW/@ %XiG;?ײ9hC[)(d1_NP"%0 ZEJ:.x\kppESȤP(po+W{4'=^tS۽Nn\LҴolM[ Hx{bɡR ٶ>޳ht"ˁs0%C`c x؃%C1ɀ\ ]U1eV-\+z)"Q5`Sa ̬(m=Spj#v~>yU?+';wIa{"rPW?KT~8~$LGgttJ76$ МbbwV{|7666~KIQn댪0W{O;G tgJ(ӗSc<L/6w` nks r<Њ LV1IaDgBy'9,.zϺץ^ 8%L.uCRNKRI_3p _J uOzw͌t(L(l1TUQ )\aeh%R@ըѸ!PJ*2|{\ XGN[S9 YRޝZz™g ]:Sj!C;S]u?\?Ϡ8֯V6Hctd?.LY~ofaI*j^g\eKn=O(;2JzJnSζԧ[dkO4LEE(\gje8Pe@&T8jb:KD¢FM4[h/vJ:!LG'[ q>@b\9\ 882Lk',jUnOZ+ýT6666tlP}~/?˗ InWf2wdߏ+ gH6ZxlEt跡]AYvyЃ P #g 8]a$R-zMś 2_Ovski=1Y[HGy EU>B )a` RbMPWxCoD̦E$( 'w˙vCJ"L/e-2x yA~0x ФBńDJMYO"_O|ނv!?kځw_ ը6S2dFY,{lP*fl(A8lR f=bw('^-AwEVYG.Oh7 /VL+I'pjѫӚLu4B :ԣZoTϜBJ0tq<@!]4aAQ[ͅ?li y TFkJ_@= _;dlhF⫚>>Bl~Th'<$fA?xepDZ#aDq >zCic^( `@7S$:QQ{Pm M>_!eavmacc1˒4wW#^\[h'Ցμƒ3mSp#C51i>_ >>}(?'?)1X&=E0ؠp{yS'~`ÃU*^`|rk:7X:Kl sDGJ 2)p,m0a~w>3Jg޲_Id1dW,'/dQ ;u\?)}t阤Ih+8Ax0ΞNQI7r.ʒ>O/|ueke}IєWK@a 鹿^Ϭ顥y$ŻhO- >֢lU؇effGՓ 1|]/IГIVDnhF{O=rEtw~{fm]uꎀ{gyf,jV@[Wuu$.a"t!,XI5 >z$O CĻϏ$ hSn`:#3vDTCK0,:!~5"1_O; /q[^_T!ąE}G9p7b U!К4tN4%bQl (-A(?$`Uux@mzUޫMK ^W1 M`h~ 8u3¿N:I{OtS!:0ueO+3~!mctpd7sQfYid P}`H;\4D9s=[4EeLH Q-pp~B=G][kKk70p=M,ЌLW,ZN,2:A!gԔcS$V}kMtTeW?=7WͱG3IK7666@$~ ^Vmtq5}qg0ָ'S h*2V x`\/YP5qa5Hk[hu3e1XBX)`DX,NGe't Bm L+huޫ:)CNlt:1uŘNw~bD(50}#$T|l{jn hW"pʷ/HQ,Z\}< ]FMb ,5Ky#2uې"];S|EDl'zZWh>~ן QT=SE&?"dwY3o"بbPSbi v ZK`]P`=6rb(4 |%;LݪV )~Z=˚uN]^㣲`[pH[:*aTCI3zvfO=i)ᔡRSx -y&5*Z-֔:ى J[Rg*++8BJL[ f,S4`dE<!;%ʪkҎ--M&:RdBԩ()p'"EOC^BwfY٭'ÅjA6+,KiU2nLij_Ezǿ/8*1㠇$ЙPq8.{`C N-ΰo)W !0RXbsؙl'yJԘƷa7hݤ5EَvOd.D"OTʻ*_&g}t>m31g40ՊҙQ]ͯ(?m[Ah 0~2dz1z`r&FJ~6S}vt5R (]惦d\Q=0 _x]*9Wk =In"]|׍d*3>so7UZ"n}pQ w0PWU#.J$Jpv,0<^eF E}qEi7>yXY gbFNXC&9Xof-?)N"^Β >k`3*, @Wթg׏+eZ3.| 8##_v++}+uA]8jW}yB_[tUuo_vUvT/\N԰hmk7J ى$>VǞB9\1 :fOrN0FD΁G9|"BƊlV9Eyc8_tCuv{z,!݆X ŐIq5#7xj`H/̵0^߮J !pf3ueqjyE[dPJ\yO<!H9av6 e>V I ITBDRk@ ʏJ=b+mR}k!4EQ5”:=s&TFȥBp#4Kh_,eѕnlllllllllllxD[=-_ |]#Y(ȏ:!/(~gסgmւ{yQBFdB% lhj)c$5~$RjftkɄSwRP0 [f *$y z!|jN򔩔o!^])[ LàtQ%(c]iM-.p•Qk \7`v@/'ڪ Sk3> 4 /?ܟ.e6s.#b*M y{q:jFÚOԞhW.PL>8TD4XMjZP'޾,p訽(GD1Ȍk9 2ޢzq%'uA b 8PCo_̺*rf*hWa*Q4>$&r&+  c2J˩9c-$8Ov%S j$Hhǜyfs迚׍R0)<nG|}ES| z>b7NUτZ^w}n:\0Nu4!ru\h \t5Di,g.Zڱsp1x‘c0 m'(cZzg~:A+%pJv3,eP2%?ލoEƧiGBmh*x7_WɣXW12R=pVS(6cWFŬ k+"c$T]UhG>N Gv\.:])0]7M \?D=ѰKk օd;Fꐷ _;kq P1| L#zD{f܊ q/-ec$!6< -YiZ~ cjy}EV :&hNjs@5ҽ^Ei3( +W#qM]P怼Yho征N^ׁW6K|-!_ YZEO |b'!)n_ߌ[2 (bi@p^#MV3]-ʱti(hmy!u*.h J0fP6Zbʓ_<%ʩҨ3_JYM̸ |b-accccccccccc /V*84_@?o (jN/;}GH%4 ^@HK]< Ο3PiƀbWhDl@*EAtZHo20 ŀ5>_^v_w0zD7rWQmW)Je*E14eϡo}+WH!2S&(Fkbṣ_0MTcNK'Uk+D83j5 Y񂇘8Q 4U3[ROVd"֥\{NT(Ht,9,@|" ު!yb4}|9L|z 4(W{JʡXM G~:HI38LE"?0`@-Хd<[R7qr*:: aBZ_7TpsWG/ʪ䊚 oG_!ǖ666666666666~mx*|}l,? M (D"`ZzBkO^ЫrT߼UӖ}K>t N"JBGk*]5(uD;޶EsjX+/0 :c!,lGRĊWWsf[@V3zUo4Z%N=$>q6@d@.q]} mx W a @Ct9ၯC [l2e!^N|>W0+Yn0)DRH=gÿI!i`&Jy| VѩN Ȭ'uF( [/%pqM6?U[v6/ZtEI 8 :P=@a ȳԞ]<ɏn1r/Rдn2:ł `|xL%8P(C~kԉtbccccccccccc` h0F:PV-BMQ`t@C|5 ڏ_P赥1!QSNk(RB/3զw[0y 팪Tk<'R3ܯA~yRm7B&2q,´= G r2^Md`; yb 0_?+ ?c,#^b`"@*K*^0x:- g00ñ#D)^BpRL&hCQ?VNTsIF?WAxӗ8>NO3N;|XoOׅ4@pS!/*2~nD)C-QuTf)>%Gd&]`^%(D,49d:tWYgq2_>:OE&2 =; )ʀ93llllllllllll&- P}C5 (;____JdU#^ҡ;0bLe`pp8G@_r9-qo15}@{]*ZD2]c*7Er2J<O</b^X3H1,G.7666666666666~ahLf-( Bz zk4?#)@|z׫f8.fh.6jjJgЂEi.xA'wF\?O!$phhAHsE^اΖ q[z, A-Y @_oIY]+Nr__:5j+'$b ) *@zM:5B4Z=/SG-H0o:eP"%{J]3֯5e^(uzy]ޘaccccccccccccW#LD??kO|򓊯$' _ּE jy=Qa9%ɒ&XۻӋJ;כOIQ#@3r|S <>- 85D}:UhC*y/Jz~ 5'h _f?kv2>^"'{ݟe/ A4Ӭ~VM +)NI?xMvE{X:i3!|d"U5Dа6Re,\ 3ИHYxWdNf9>S6666666666666~S pfA/d68OڈC;TP_?/0$LSJcVp.@qdTpFNjž#$2Z` ˌ).sxS#3oq <Gd<2_qiñobg|^Qm:OCO|_@YY`^"pM` Փ*}#aqo0,z.3yJfMޞ8/s$ XI %$Q'ˋC"CWeDl&p666666666666~q$K4U 68C>gV.93|P=Hf)YID)Mp]E3|=!6u(?k>xY5+^,Z 4مl}eïBDVs0PbH.7iUHs ޗSSLP,I^?2S)3. Ѱ %B_  i/g_ǟ%/}M؀YQLHl&f3 riDS1%*)Pei Jg7$& 0SYA$E QVF=EIwg&u6666666666666~c,ac O'+[_#W#> ?[/!,jrڢS@D1Q*7ugYd钳zPdY?P;RgT<#@>Tʛky^=7q(1]/accccccccccc &v2Gf'̿xݐ2wq<'v}OjPy(KF'eU⡐\d#]Pxq<&Fz#-/sx?X[N$(g8ʋQ4)=qaUOlM _oҚK_U {Ollllllllllll( p:=xp%ʁm ŧ%|m2:QT7xQc0gݚzR̄ >J<(pwZKRK\)0LLxq2ԱD S_)񘜆RLjINC+ATpk2+$ ]/F5%ۑP&OはPp/?%0^>RUh p";Q0R'8g#Ud XzD{.!L*6F4!!Md|f96ӾI(%kZ{ohF T֘G,accccccccccc7֜|b v]GP|m? >=+LLrtj@rϾx2( y8E,hG5T]? (@ hR1HQ~AA ⓄOaZP*>rx+ vsiZ9ZKj/C!v `"0re`DA?a]\CȻBHH@^8QdWD'Yn:х hjZecoǧ,f;PoTy|)n")xE(DȊ`Ԍx?Hc-V7666666666666~IP(1(;PDa?a|% -Kx"hBrPX|`X9E8i!aepZZI34uaf¡@"%v1_y@\3K۳dXzQ:&&DSV][jKDR2 3@.C#37 N]8* e|i xbG |BԗuRbp(MM(^U*' :CO^p6bQ$@O7DF).(+acNeXl"=EVL)@@u 2vkggR!_8UY Q_ c'F/@KV~!Ztj0_L(8ta& 2‚Ntp3"ZEy-,;OY 8ϩᬜ UCгOhOyX\7DV 7lNG_>et=4PwIf:'tD4qj-Pto6к G@??=n㻘X??񲇐2@D-accccccccccc _)eX$*4+p'_ۙxUxɎxnU]='Ye+,ЍDA$\Nw*]xiJ!B3(R\2J6{=WA3 NIwZ\UaaxCjU:f= mdI8A7666666666666~U+zkK9{ln9G|mO|fH ,g8(&~٘"P5kۖ# +ѢzCS"-? pcVTב KS.n:v"P7t/VǨY| %Т- /-2b 3x'61xwfr@^-6~R` [ſ|ac('?[P8!5-WπG}7R6b0tTuJUrU7ZTg#׿e\jj J~^ 2U=viKQ}l-9Y7ȍD 6 ov;nϺγZfU:E@IJeQ2 UqhkN/vht|B-E_._B hof㣅$5!a)w!]`P?ҍ_A"ݖOپ1W[n?k:l=Qj &ī'<9 XZ gMK﹀hl%WS7 ý=9v`x@f?k0!g%,d@XcT|VKkX d$"蹤Mglsua I(|o}'F"P_4ȹ,K1(!c(7|U $>6~,oh@T+M 6JGsr'L[|CCpo#";DbJ2#y8$e2a Tg#QU d1x>W.KiQn_ԇX!!BwCD,1O}!J'{ 9x d=:q޻9v, )\j1={T8 k8%p#&tOOH7-uNzD'C5 FcC<` />y"AA;@Tz*}go9ܺU-w Թ笽un3sZ"] 2}`ȁyE_wo-ӭ@">ues2ҴAAAsu1 `~Xb8_Cj<}[O'Iv+F lj̘O/3dl&~DNJA;)#հwY"4?̯FfXD ;,*8^OL v'EnGU$m"   G0`6FLB>رQK__vF1?'rqAF|Ÿ=~m̯7TX|NUnʇ^K jqA%=lGzO4;Y Nk7&ROx j],Wބx"$êTW"Hj5WAA&lSAf_wZ>C[k(%?u\oqLڌƐvVXcJ/qg֊WHڑ|NO3&f<8(1 YNQ l wp_hƒhG2V֏F@'-sz"qF8die;u"ш    W,ٖuf3g,~(vs {.ǯ7bIfpe8)gYprFPE$滑;hيB;D(q9 ^ zr`%vkJ RUrrʌ{YpPmU:   ^gpJ_gNO_' CܰG{M~F62Z |xI?y.loB/?;,֘b z<e/F]Pz2QF2#y;iq= Rm$AAAA8*םNt"0ޥ:<t4f!@Q3![$f1%4|ͯzO-VQ$g2 0u m #`i1o@^]0N$k!E}SzGk-(J0rBi($+XNGPR   Dm|Z*#_@nu hWP2$p xU^e^u ]/`97Y=sҧ8 ) Qec8n,/b^c0a1/;pko2A5?!  p.}^V;~Ea_/ņƯ3p%BFA\ U= 5w wDF7Իƨ1n"Ս7D:Bxd -29xqIWK/B3EBXQy*tSgHiGD_V^_*6l%fqAAAἀj"znK{0?P*_sSGy$j'*U Ņ] N&u0 aů7FݐV|LFă}P9qV:eL@ph^{rSA: F+ `0:Sd@2F`DsCx?r1hl?i@MܯR   &6`vPPobapt:&sp}y9C%"XXi .0uMXNIo 1pRl\WKHYr-1%Q~&5RQ)$20 Hf%h\LW!Eau i^i#-_/բ KAAA+j䤃5įarP4bF;piu1U4~]K6כ# $55t7ƼȠx+^Dxòt_yŽ=x yt6 D 킡$ ѰJ$!88hAAA8?ߢ\v`nױj\=G+mEO~9kk>ɐ܁֙%d,D= I&C$Yˈۘ3, m ýHR11aqc=UAJY&,̰wT'zNp4 o.)Oyfn*<x|rr/}顇n _[|뮻~Li"b^L_Oyc7Vɂy&.vUq__nz# L8" GTV dQDi Q3hX3H3C)aF6##Ğ c!ȑL:=T޹3f?Y aTc%Ddy rS $AAAJ,+~SӒߟmj"bG23!s"']cVkF'ހ֤ ǐA  [1m"k/S,*NyVZ JiJPi^|u`L-[5kh[30sY4b8W+ }x9u^oigr4   _c0uG`3|*uóHJyίJ8zxQ1 ksxA GOUQoe4 DCϣd{% ptB8/ hV#|PA  ^-AA THt7P"Q EĴ ,U"R?7QAAAA87,qJ0b{:愅ǚ_όיi5#1K1#P…QAOz,;DPyr_@Ndi1Id&ٓIEC2sBކN`[cVs3!i~zLi mhp҆Z) QD/`Cey   IT9 S{Ixc9+IhӘ3Y4P8,=T"ӣ̱-ZUUQטG@é4!k/k4  "xhoQpzVq8EXMߏup14['IЖreLcFURA8!L   wոɯQN3'8į :]_2P}/#`Y{E)R >c/3vғzdX,{ڊ$Wx5آ& qaA=VC&8I<%G(36tX0I)TR8ɨ q[ {g||衇n <Ș(q`5봙hEdL?%z!דnZk;̯v*0jPz#mYA{1# }~[0Ifi9^ղ(22K`ևh埻V,R88=hh%/[6cc}M K[e:`V.<SA7T=tOP8U+8| ul0wkB3770s;nԈZC:M>79PopCsej(5^%r}mJK `D3"=$tgp_uAB3Θ̀f: 4Is´3+)fL' .9$ߺ   Rf7~=ߣQN19k 0htL~mį ꁹ1Mf~IS}FX8e"`z$jVb耩s.ƨ6M" XsC02D_ҸB"Ӹ)#:w@:led$qAAAp1&da1I*N#G'g%&xA~MhC:rptOؤͬ; Dҹ 2۷`Ⱦ:`TEajb r :J<88@59幌u4~mƫՁjRpA!} |ٟCt]TfΡL/Zv5w*଱pCEJ8 = `|5v[όM2ʹAη h~|j5z/)oؽ )lͯmͯUKq_{s̯zKbL>l#xB7lԱњcxX'f5ꐘ{%*UjMUwG`E%nY@ځ[aP^ć576:=#   /0?ׂKg~] ˯6c T@ k uK%y=Y@G:0,$CLfE }N,V]A@UH sBϏJd4ZZ?V\nhC`=g+3`&:Y#F3RF- UAAA8G~SFAVC58,u[Zæ:)?M.?[Ic㳏_G#Y})"5("lI GE5Pt;)ӐD Y2vdxg05֙wȋZUCBaUOOPǣj5/|5L   R:)@s'ݫ~$UhOW G# :9np AւDGL[X,EC07`fy@g6> c*u} VYAqeJQ-==EuC#uXG _GM3!;   9<~oD uwv_#X7kS\Hx ;ED;%-`3K)kG2j^#,xǨ{ msʥ5 Ectsga-~ (JP>   96L ) MrT׸u˛ ) זcO+ËnHep4>ZbAdSAPAY ^ I}0 f2͞ iA*cL«LoA4+ Jeh򪔹$Zc5%GT&U;qtxx*s2~I̘H5יx, ڽ!f1cSݻTj#S}>wjx?jJyՋ>c)a8cg.gx1 k5$g7ϼMRr{uH2jVMU,R)p&(,A#emB8ySA7Tx"q]witOPAD@ʟf"às#6dɑ8_Wmę.HbE.PZAb>`%E3J88B^!ArK:T]|CϨveœLyJ@O:8!$,>S!0Ip^NNY dX%T;!  p^1[W|`>_6N̯*/ȯJyP?!] װF@MkfݻReTHnH k #*b1`G *u2EE5N S!P#4*W@7N-,! -,RzasEq5) !   3n'NUhiZ|aܠȹ Ȍ"gksj }i@22awgTZf&qzdK.{3egb&JM ?P2:fE^,&ҦR05]Ԡ wR80j7[ gAAA8ѶDw@{||ůyi&_6vzM,kxq@ %!⺔Ba4 i|[!h6Ь^ъ%14 %P48}4M ?!%$рV@3e |9% y LqfUgAAA8p4SQ8R j/k a~m6~`>%a9/vsnÃx Q#`7R:J%Lp2g>:9+ Ɇp0:a1*0 X@-(]S™JDp ZT-f jC:Ԉѥ [nah+tOPM74ɉBT _d>gD$q6U; vؾ|  m ʄ s2SɩGdNBdY*8EűaH(1`PщP(OٿP > x;ȍQi ^" R-ُPyzȄLMdNm DŽꫯ> {* GI9,f)pJ"ůՓs`I\"&6U0g%J5(2@1 ZKmG̃4IՕla ϠʄTbTz0ݠb̚WdEr4D[ʶxjDjh\QIM k* ss*C)AAA {: 4cͯ{=#GR_{v6Ӝo(h(6KLrخuux"qy8EEf$Is#gŴ Ѱ>T "o9Qvv4/.Xv j}G,pN) ȼjԐS>ڞ 1hAAA'z(|I᎝ΙMUۺ!#RD%ӏ`D9}t ~.y6pf&LF|GtbH̅!G x8떂^F%jR3޷/Z*//f 6mAq aPܨ3@eN믏i AAA\"Z)|~<#d_lh@ dN9)f1[= fx.3! *9'w)8.R'HtB875jH4q "O-8vS~y9 WC L-m)/@AAA8_h:}dο%bv9ZQZ0:T;R͌Z?VTGbC٦Q Cij4   k46/!k~4?QN~P[$;HiřTDY착ɯ73bJ"<iF=iHqzyqȒ29T")0kGe zUd|˰fV0Sod )%QUeRJi.(u\J ~DoҕyԎbAAAs *P,~~k`ɆSC׋W!*3pR (H!u2/*Ԋ^L H( LnDpVNdVZ '>;&Y< OO$jx@ȧ'bt@>GfCѼQy!Tñ{ۭBT {ltOuOPAD,J@!(7T;X! d#!kkuUwG5yxVԄttC=~}bpYnj9ÂAƴg,^Z9 R)5Ge\V#J++432SF/ڵRDZ?ME,B״ ;,gL9su2P{h`&|vF5pF=tC' 6AT KI7Y$Q z@O勭?q7Mn:"LMR`x2~` nKrJ+#Pİ.ׄ$ftSwQViSP6)##`F5( =aʉ ";+:^mb(ZRbcOAI*ڱC   Df5X +uכ=~mD ;f95'E@[1e) hɯ#!QR%EHHdyrOs׋ ls{"cUF2Q]lH&DX/ {XpcpyY_sJy7   p _q%Hks z@#venhǯ Sͥu"j9"`%`95g2AЎ7(x m¹ΓL u p͒-Uꅭ'j:, b5faů,~0#H@z4OE*X{]SaqGe (V*QYh[,QQ nSG]ߤ (,ڠw'OqU 5r4Nv> r˯>OV7{* £U6|O@k~JHDfPƂs`_k;_ %R脭f uz2ٯI.X."J=^<FS`am/$Mi7XՅWnia2vf+:#*/c1o~򓟬祺9W_w/}魷ުzLoRSA7T.58/DMg :/1^P! (XҒS[%TAM')?O^h<##Y57xT(%RD5$f rYk'hLUFpPgP*ڬg觱+OX(}]G|X)Hs ]R: __xk_;m  GIfkb OX:h:V:З,'9 亠_7}gbe=R`5Z׏ 3Jlo@JȚ+dWjc`"=# k2xdfxuYam< iZ^ o}뮻N[! £|ao@$n)!2ɳ E}UqoiF鏹VלpZo95VtTln61n 2F!XA#uXĜ3jP 2iYrB5 %2-AY37v54QajQ;ITEUƁR :Ԋ"$P$A.!^Oj+AAx_R3$*FN1a2ٿEbߩh+[+^L;ذLQX4f:>ymzJO PiB Jh/ruxoXpfE̙%Кۿ;dga˼D+0tM94Q'IrЌUbbZ;0*b92dJR?P/saYt"X39X pʹcr " BT p0 &~W~xBAǀ ~Z-!;k$D 1pX{׶ץ ,k v$_Ҭ] 0mZ0S$2fdm.ҘE&`)YW+\s͈i}_=kGd8#8?ꪫWCk gyf>YǍP;pO#x{_=:&=VNXil@כē:=$XEb9,ThzCi\{f%p;@ybHH ^0D'ӽ40Co0?G܉0̉Rԅ@^AV7t/GI;Oɢ,V# ¹EK\N0Eb8:E鍍jfAxd7(!hTa EܧJ9+ =j QD9 T4iY@_^:R4'`΢[D aPq53&8Xt几EŜnw+}xy*ı_U{zycHC 7<j||\>"( etOkXpw^SA7T.@EzP O误0WVup!~ [^f;>qjߌZhErdœW{e{Wڅm[8DhP_?YچTd qd"Q1;)z)2{JEdmZv >xDuO/.݇@0'Ra|_0) *\RE2PޜS¥1ez,"`U`;CX0~w8_~NEInL91ݓ <3t23 p+V1Q#TFemwJ%/(GS` 1 3!2£:+*?ȿEUƲwn`BAxu!d%h͗FS9R-*r"Hp~7/34[e}MoSfĖf$3pxwk+tO/a3wj,R`A>kfh0D6=ܣOSA7T.?{r Yԗ6i"P06Tl箄Ư"8$'P2a* яfB:>zgF3DʻHMXr#IvCPo~0:5o:H~ғ{W p)sfyNw}>Wz!|,./\^|2wx m  _=E"[>oz=uƭx$ 9 0ޠпGwO2rAA>oTDTi&7K 0UbJIaVCI )*qYm`RTd;X:lRN  ?V7֏lP6 HTGVA 1áwx _8Bǀ C&<>gH௏OW.0;4Ka;WA ғ_Wnzd -xpYJ$;.IEeVe=o~y2¸2bJUq>t=}"j%-(EoγzX멤q-p)V~\_I9dif'2p^} _XJj;rNA8 vK^E\}yk;s_/R|C8ω  GG 8?ݞRU7L3 pn~~edZ''.2QpbՃi-1ߋ.{{AP"q|tK͙xWt0P V#ެ A6k9HU()g=@{6yva^9 #K.낷A8GxS2do0J%ɰ0t!|i/~JܹDAAp];0̊CĴ9E8n2_ h@-E8t"JWC%j 7]l2A햓cKHgrLIhfUa4dRe#8?W 8 P`N_86x U}v#A A87[^җ(v;ϡ,qAAG.,%Fg˜ e^C@vFbGCLl/ɼjsڅ{W!()VN@0WT 3pRq@xK`F(7DwՐ4Qݱ=,+Y=&wC F+_oa7e#p>.,ǀn  "MepJdk}NO0E[@YϏ7hvoK.]y%R$>xj<{: cF(FEfRFEvC dy&Zh8.7:C%/`XUP2Pf, hPv|Hȇo!4cId ׃- #Dwp+_WU-0Oӟ?όCeЏcƈ{\M#tOPA$ 7 {K <"V9S*^TSXJ48@ Aیt0ĩ8-DT"! |,JI41 N+3(3H:UArS;R޲@hgPKA vJ3OP k7Z?@#xej4h(ql #Op1雾[o=(CP:>O~CVMA #RB1ASA7T.!D`8_zČ'&K?x挟ᒕ'`$ ܉ ,'uqA8` $RP1 kYXo\ Փ<|N.@ |ר^Ӡ;5J@ P3xTY bbefj梕t[ <iC\xk^--ǹ0,ބO|>$*AAXŭOI:g ; 0Ndz^8I ;=c"0 #N|U0Ņ({E(n驽3iaɂ@ǹ340s)y!Xc* ;?_dIqJ>!umAa7h>SHG* <j^,u{_|rr]Ϩބ)_5ąԨ;% pSHؑMxzѽH5?)Q2Sx1r[~VY#@-V87@soDKZOh.n2fjemTdEHhzdg=(b 2:΍!`-܋tw<0 ? ]1IOz0/|w|k_adZMFB;(zH  eh[m58Ah>/D+DY i`e o`R5rpc/FD!4C::rHtk(_r} N&8,,>J0lU ^)q#JјES2G-3)򍜳9q R-#Y\BQ 'c`cډィU[[;;_Wr'݇1a ?s( 1u/ߧtOPAx,vGړOƹi0*PBJ\+݌F92?wzEO#֒p9%"*T x6hc(F>վ1 YK魢a8E !EIU-"j\KYlySYXزRnGa c_j}a87|7_}0F!~aݎoc3aI Kшn p tz~\u Ah!+~==@-?=@ŒAŌHd8Dן{4OE{D (vJvLne(n9Q e.hVp9C[ˁ`CP, ##¶Q߷s٠T 5bp׎o'F_$G>2[F%  •5tI֌ljݴņ =) 'Ů <%O_vF''~<@TMXxȬoLkI ?{,V HR(CA'lsZ3P+dN* 8Cqv B9L7xrQ(CM ddA%/7O}S/w}ê0ąQ1   |n>%;QMO;8 .1-(bWh7R]TڃMNf2s PjV'|辨b D@?d8ܓ0Pi0L-JDf% 7J<}ʢyi@eeiI n~)???}}  [=YBu9mSj5R`x*wkMDAA앨,A<0'T;K Pk0Ie1S%0=F9$3 (J#rJR:͗Dg,'j8ra:#++r0b FXKp4R9}9ey-\|cJ`8{wy's%[`h{qx<~ Tnꫯ>xx}]ww%qu0ۏH~<~O;Kk8گ_^s57xӎqi|ڱ c+<¸8fvl܈|lܸ.mSBcǮꪃW~^׌z|Ç?,`U5acƥY;{V_|U51_OŅW? Euui`ʅǐ~99|iW? ~T]oq}lwm\8};6wv@9aǎa 㰱ckXtɋkvo^* w)m\1 9=q̸k?0k6n~֥]X.? cƎ.Gk5p֥= 0\oKs~_Ug0q/pq/'/y;3a8믪'W5ՈQ!<\Xz,=Mez} /\C@@~QܚbgB')(%f6$i-;&"ױ.jCU@9䉺\a)ICLZCD@&5}b<hl _DiX_,|mQ,ƌGހJ. ~I)p={ >73AEAAaOi~f |uTƹ|fKҀWTbE.8DRjeg) UehPBKY>ew(VӷZ+͡M8H$P rVufw`ӫC*3rüwyLTzGSN 팶δ„>x%eWe*8bQ$ַn{ߎ4I Ļg<g}o =,՜{*膞| ?r՛SQnNCOպY$oB~ep?hwم^vgf?k|s!Ҁ5Կ0[ :j}mQA fWeEcӔD~̔ Sʀ/, 8 #4-йQuga}S""٭otWp=4=0 'acHB1~G6$0 #ooSAA@}tJƯϷ3xv[-'#dQ̉ $g -©NB2M !23~Fvy:r0s/B L%6s;xDOgMozLjsw˿O~򓗔4* •(dr78ovrc|պa~mL`/I~~oRaρ`0)t4,g h j5zgu*PoR }c TKQߘ/N (QJܾ M~MT!JcG|c~«'*K#ucqP-Eހ669ap??? /0œ|Gp޵   \TCf/,O4JƯF;ɷT$;-Jbh(;iUcT\3;*.8["0+-f%L`ژ&@΃,/F \Ynn8 u9,/hn#ۙ ȷ90lgUJty[ ^wcbJ Ma;ٟ٘^1AAA`fi:6zrSb5B^ Ā'X90G s1 Lw_>+X~w\a D=bnFx;3w@ܣ[{NgR(=ԃʯWAY)3 F*q@]wR'-Skd HByՎMA8~ɟF0 }OO?Oh^AAxB6ij_@%9pZ0aG3n\=@./k"Tq*u"H~XtS_8uN#IPSa!~*IxqEfE+ D_p.T%H/-YH$Rv3[_Ӄ8832>{p׏{b-w۾ۮGڑ//Squ]p/CмE #j &g P@d^f1EjX f'5p\RLȃY }P93Qd^<<  n̍H+ {\pDsJe ޑnrSbH ;'5rhNt1ڑ8V ż % G$4R`J/ ? |~ww<npd|PIuOPAx ɞAV1lw;I2CESN%0Ş-5.Qίu#D/ibgXT˨Z g{9R7ԗ*0v(0Dv;8Ǔ(:=Rح 0#?] t|W:U͹y|bQo|//z뭏U|  _cp *sn e 83xG&A`ȠBFR`+! -/80ga(@%NVdD  kXcj4sW!i}N/#W^xT–ęLU$}1=ٚ&xc?co{۞']K>H|   PgaU#yԀ5FM$hb=ofr;E1« YoU!`ed c*d9lc@|D@V( 2E 5X6RcE5Dx!x3?'PmWOI9a8z󌁓G~d/~{7xvOAA8(|٬/A}b gU3A<N9ޣp?AyzRh 'V1J%Ь(kʵ}*%|3f%a5ͱDZE&2T˃ט i5%AJX+ LIxma1voM,:ʲm-}qJ#\0"pJ|K_  įVt1x=G8JŮ^h ,`4+aC?s }A͈A52e^8Q= lFUiHNա4tBGXx~$ŦnGuOT*s(27Dаa b[9qřXNu atX-oHw?NAA8HuW؂&H2z)b6FK2՗p_9 ;beCO̞& (`iX_P"1X$p Ro: (F!,RTg3d{K;z:̪rA"dtS! ,"4rICtL`q䐈k~B8|w}׏_L.Ha?+AAGB>w}&+%K#1It~Z)QYY54rJc{~zyѓyI͖Pa$`ҠZ'd+"8ryDpd?*x bJ*ҝ Lr@n f$hI:sFr4eRSǏp$|͏xHd_=MAAĆKs4. ˇ 6q (/^G <~Ct@Cp̴H_adFU#~AY}DD9m|KAWo~05\??/1AArʅ^z8t>~Zf%(ŞI9 dU)G8R?B~vRye٥34ӧἶh#`3J\ ;LUSYOO2  %JE_ވ.)&ECQ!0$d <;RxUc 5^~a%gT πɑ,,5RFFPAY j4k١Բ_i.p~+= UA(rx@|As{`* P sZgF`[-2;`zj 4V2SEE=߭#sҠ T¥|FɖEa|T<ԫ['aB}2V܋ @*'YB3 "\*XV(V/nf3x5NNN:==?GQ;~۔DtOPAD~C$.9n-uuEUXI y5pB3rJ%G9FS(J oj a?F 1m6aC`ColdWRͲi<034mQ4ZSy OG LO[#jm瘋 j0#U;\!7y{>]ݐW=r~j \@tOPAxV29$k~M,icN6?62T*wqdHlʐxҦ (ْ9 ܈+4ಫ (|`1HܯD&MLxJ6^ DP9&/X":Ϙ vȓpj5eoїJdh.Spկ~^{w?=ܣAA.ov4'eQ}h{ШF"֧$Rkh{gESzJ d"F0}l(c'3!Z%NT!Se0TOkY9hvܶP9yЄ1|%SVǏ]0ViO{xFqR  `d~=^xy[͚_w ;t ǔD#(*@Q%zKngJ 'sKdJ,r4bܚ#\U˦Q$\O.TF@Z$3#opv~f"6Y) ^ Y1Dqo4Gݤ`ʖm[ Wx+.P6qQ G{ֳuhſۿ :Laci\abLf >_VF ?*|LGC#9ߠEfpC#T< a*h4o#3v1i07ߢ9:Oy<:,埓rGP@$*=6畏8.<1~R 4y #Oᑀ!Ir”~1RDelK hMA>aGĈ2‹^pM7::O~Rq \9SdG',|ŐY5QDDfL'u#vE+8\C)iHlu^NjnPR `f}@dҚu魨njPLYxДN>``#.[0bq&ijf%凪,˅TSҘ \~xssC߯]Ah 4뮻+_eA3oDrZՈ8ʶN*EH Ki7ax BkC8긘νXG5e֌|>!L2M 5gY)ӗR@`b_tP|m6Ld)4,9aX XYYDjd3(lO(8ϻ]= 0H2S 4qA1 c nA8*){?BR|1xBI_Óيj#_{Sp?DWGFh0w,#B7`qā~diU@ Dha//"wciQv̏hkFGCg4TUaa+KHCd:D,1-3Hs R 3$*b)lذȦ #ҴS !.04azd!pt>+R+I<,27Q쒈dZcU ht=LL-aFMe8$*zrgaGb  a4|VVs dIҎ掚Vp( jHH 8UCwQBk;f~LDpceA%q^5u6Ȣ+Qr4 p)gFgFA|6 ܛ)ψ'>e$+̀SYȼ:~\m2(>LaxɚFF9$I-I1HXY3Or"C3s(2s?P6pFV'd^7@ W*6Zr4%hAxb0ԞgeaQr|*R+Im$(o=ro~vKw+tD@qh}OIs#?'< UA}lc:*p \~AI8ɀ>nSK002x) s˲"-hHT}Oo a [,O3p|o;@(o|ݧJ0#IDs0<̚"bx 5f@Uy`8A})0KP+R&h1csHW2:GiRShH7<`"[Rpym^cψ9]p4WAAʂ •/to&|~>oZB)ĠhhbMٻջ@k=q so+ '2TF#WcXeFRbz 3x^~ 3:wX(@ AQU,,TBP_$ݬT*J!>#*}e^ I A) RA19B6ȚqS1Np-X 45C^a0.9 Nv8b[dP$)rLAu8 -52XAd7ZVa#sZ̈́q\mz>:+!ςK`.pDvӠ N2;#, o( RAʂ D|"qL6jj`97Q 3@U.1c!OY 9%cL `8 ||/V0;9." R(b fq\2#-s4@awU@`WfuMF`j ~դjbE(A.:vA) RA'@t=m nT%n"0$1fTETd": I./`LIwϧ,FM'_: nOVṴ̈̌zaTb8£>:Wr;@ !Y!3xoC[N 0!`:yhQCQFC`e ?V \e 9Aee/{m&eAH~~chulĎnO?"ObU0f3d,!"߀I 7,!ԊOze@O5` Yʌv|P-Ewu r5/_~XHpdA!.(}TU hAʂA+^ eaglfV724M ^ݐVkgFNgHQln_9tO쒨X RfXC,z xL_XbuXz.tγ_@8%>1F CCaxWXbBHam\Ht ?{$]Ut$BPD|`"j@KTPP W`XZ-PQJ?">/ 2@H @ In'L^{==sL^P7s9tZgJk( ,P( cPEѭ{5B( N75nDjS4+ bOǑ50c@{OSY_S9})q84o?`"}h#<#5JP(x:XLrցaOw˨2b ]ts+d|UYwXzI+G̱k.o^q Z(.~+ 9Q_Gu1s2?5є1&JaQ.HčCfub\}[nX^Wą.5íZ'.h&t< Et OuTUiUXe^ۙS3h)}O9 MMŰ&#`8AwEeAfRH&Hx8wJE^ID?2݉  b Ԕ SZDpu*3xWM.(Jh( ;,4Y PY , Ba>d L'r?| ֡2NPnlQqF&흖TnL'SI&A_0%EeF6>"]nX61I)P}F3*qzy{ՕHюdc9xbTaW5N\/"fBCsGwK<]N8oB Ba, B߁$jT ngmxB=ȁr_aU0ꈹ(vH 01D70UL11@JL.Dӂ c漋0A$?03j)Fit:N™tqRB~xxh$vSQܸQJC(ˬ_ òyd4R(P(#]Y(eP( ! },ab(:m#{G5u%O,ҩL5f"!<12)A=$JRǷE \`tII t8X? rC~V$8 ]v_tKȆbbHЅ^S5df}Ѿ5݇RFY7i2--0$/-ALo Z &ejBXJ<opBY\0GM5>0!+Ɍui ONuJbB@E)Rā#a g N  ~ZX?]x"($RGS@"K PD%$fc3F !' RIkO>65oӫz]/hS:묦) 9s1솅>‰'؎nhŖ^5 Z(̽A&*K825 65hoqLR)6dX,|v2|XbB`|u8йSDb TNVMw EP!Y{5$,P,S"BF pr3Y- p[I, j<ϔSTSgm %4 ,\q_BP(짏sKD)c3k/kU!>Ϟd~IA룴2Jd7=._O#2yoGAM81>!mFPƇ1Naf2@GCOTBywz ?,0r(M͘ |cu0;hMNJh( , B'>s$ȫauqzhQ+p E%GFApzHzYAt Ի$ecC 8  \i. `kD jId3$ A0j/ D(NȢd*ǮT)/)?{Hc͠_u2>"#DB B) PY, B>f'7pm{ޑ5"=McxA'|Yz.|恧$5z:V 5C"#qh‰s"0 p;9xxO!Ƈd]pIƗВb|$!`&7gV#j)Bfٍ=anQOKD+;3u?fCDB],gP( m@\C0!9 b_ W~li1p7U؀CD P7:K*qI / $?r#kf= ذ+V-ǣ5Ҥ-Ec@d?A HюPd 3yqTdy.4z 5 , BV~'\'yt;Ce@kdj|i|E ')Nf?gbyF4 wļ@,Wn^V(Z 2PXE<{j?@VVl"fr#IqIU ra OY_ pI* 8qg:uM  ZNᦛnju]ڮkZ Z(&t>֝ຍ^@~WIp9TȄ#)O@_f5A$.$>Nt`4%!iVb Cj%8@&P1v mb/i@AO j',fQHzԍFBOd+i)"BQ-1OzJFvD-K vah"F{hx̫SЄtkLi k%Z״nVկu_z{MZ״PP8HaK%|OKC/[njOSSRHL`ku&f~=5<"PaCLAxgvw[x{!2#1 3 ;>@w:Ѐ>wvyeWHґ_52?St}I(H(Qe*Ѳ9si0SVtY(ͧ'ʃ]XW@Yk/nU( ½#3让xb "s7eR"D1U,.:^B,kza>+ѓ܉-(^Lɽ4ၗk iC0%LsW%M5P%C9~Lz2 I%XŸ>C,x!-uxj#Msf& $)q&F9=0J@Ae _?Q)Q9>`~/3O(8rFY)Ih(PB) BP( %O(oJzh|“ 2 bl? qMq bh3#VM2΄Of~fX?P|Q3Y/%UW^_2 |#PڼI`twԛi.hpXO@Ja5t!}$BbÈ;M̯eį]?M -,sF=%|">{Kv허bK8qk_QɊ1*Pwyph@끈P`C" %PtG%!/bxB DReĻKo k2HMv=^WP( Ba۟}_g^퉌7Pu}dDDD0݆8 ~š. Hdpo a 0 Q;'U`df"pC,`6$A\!&E^ aҔ%r1ՉYSD`²8}%Y 0TZZLc3B ~,.BP(SB(\P#+: Ex/kcnͯ#R>zPh]ʯ'p4H<4^%ihqHHŌ=2IaO!]h|seC}[YB^駟=?!93?ov6P88#q:]wy뭷tM뮾+.K__(q?i A?)$gH N.#~Q:#n/02!x] ;(tu:5&B Se5J)st$G SKa opOfB"&B1*@0]CFd7ZrPYQ~w~tDppG>O6rꩧ6"WP(37̣|O; 53'?-:x` 6ϓtz60D膺.8aįP w8lȯ}` HOD8UZ g<, I # 4J.}. NtI 0 iށΣr/Tc r0FGPX{\L4?95c|cJ'GlP[!BaщfXxֳ'<xP( 9;u_j\/oMu~ RN s'dxRdD4Au7Ә% +hLINp7mQewBO+PTk,XPwICS?O:b>觰Q4'\\Jd< .N_8wXޤ0D3i(Jhm2/|a/4! BP{hmE/zQ OЇ>+lur ˜J~Z bJhCTrчi58a'Srp#DQP yJŸ:cP!4ۤ, T@ HR"LȤń$ptI/QM^a. *4>RB ӟm-pP(]4hr^cX3S(&ŧ]8F%9,#$mmxurujc@*!H~w*!榋 JRvߒT8 ,p- TˁsSoMeH|Kc{a#>4B B"Mv@PiiDFgfr.(TGϽy|t; #qC䱪X35GL[h ^6%tζP( {Guh9~?n{騝tTس0#t!=E&ʹE~m vw{ڏT, H4_r GܫOxan"xIae a i (ˀ z棁4tN%"S8A EѠ u\1^?-īCDt^_Xt: ͥy3yI'( }=a+=|_r=APˈsc2a%LՁ-nίu ~G@#6]hM%@-WThOm2`|akk\H#0wGUZ~ͲLBNrUKt .@\[H- n!h($}n32 :ՅBPA_g<o{Z|Í7XP:lx‰m{:7Tw7c*iTLWsh:E0+6zLD İr9 y%fHȐQQ"eQK=!>+tޓDBSy3&Bȉ1xfGtGͼtև,f#7J6'|۾/YgUYBP%xkk7D모sR(C zÜMsVT?M~[kxJ;tGD O-R$jI4c.-ST`"URs7X3HB3T {GyGxc  Baᑏ|k_+&) W8Qb 3fE$% Fů'S&xWKCCR evzDgBݘb\ymiVDrHq$Arj)F#yބ(T1@6T~yAUO\EO@3}VE;L|BPi1bRʗgq=5u7_wu]vWK/}ꪫڀ-~@݋׺yʛvǟx-ٶ<̇vIa-1r)x V|Oڋ86FDG0˜&c Ok9į})' STNVb-fŝ@w8|2dBI,,X(F:1@#j3,<2[-+_)C™ۣ{Ri.E0} ?ۓBaҘJ%I:g`f%2_h{W{{[^O>5;kԧ>u2}rM +^%1Gˮѿ6[[G?o':4oo]jd%d-ĵ=x5ꫯ^ pyGwCz +5k3$ #$([,̯!o@OeԐ< RBKANN"π&&,ĊPa__n3KP Mt@pA,D`A@`[#6H_FRI'Ǩd~x=S5-׾9<)}g~G5_oznMdo|;;'5cz +_~''O&oodDN2R $5O/HB粠 m4 `P-#X,ev.45G2RRKeނK1X0*(O X7MXV.tؠӉWu28ffBa_Ke/n_#}>|ByvgO}5s!y9w~w/]؟kΟ(=O~ӟ+pD &" n Rr"g0߽c4d:)Uċ$pW s;'F/n|uAgbaQjaAՐ,wh^N!HT>J5?iΤ[>鼱R"Rs'PINrOPVq q Ҥv̠YB qD^q~x_>psLzz)|l6Mա??y)yzիK.뮻m#'K_R={H9w~wUK3)gQ;v5ߴ6?O=>w '1 k>7齅6vE_'|N;j:m!9TS7F(:mD' HkpfY;^i阙0ra%n<*=>wTz2F @a41yg̃Z5^Ka>sԝX? z#*$I޽^ia 0R?QBQqB$`K]nG"Cdي.}jC ehGf #4OOۜh?s?&ըyG-؏ط7]GBAGeP㨀@^agO_~mRLr4*D7-xį76aJ*-@DFۏ9J, Rf&u>r'(LS 1"7JDφ-RD$<[`!* IBeDjf3jtS5j@\"){B͢f[hq 7ԙ/VMckٟm&6ysZ>v#8RТQz _RZL h\>`XpA1'j$~mp"j};7aݑ$Dl- =*z/c!1/C1X1@h WpOXYSp4tyfL@32~|Ao"= 15&.R (X9쀮ʙ0g)(O?+GGlZ[ _~+_)GtM7>84?tz+7G*ڻ??|eXBa( ?fng@c@pfM:nvY%bNA72dDv y(1)GD#"<]sD,3#w6}4A )>gQYX\N=.> N͕,Da"R- y E!H"P(a6آkp78C`K^6IxkmG*7; .a;>*w> ) ˜_ hiuYr4X#hm팹ͻJ|k_kZ zƎ>\tE'ej9~I}_l{5;N]uMޤub0o8TDN`$27U^WةNST1KTu!fQ1(!^-Oz@ _ϵNi Q0Fgy MI1-ȁN \qAng@`&R4H4$2&\*qE+?Q87$hGu &2LءFc:dnﴱ-lwwUD]z.׼5[nrg?mPgޤ*zƅRߕ`m _K g Rȃc#ɯ'X2rةqN] &$@ 4$I[Ď8Aѭ)t h|,0Kh^J sA5Rj nhGQ^p JJ\luuF32)W7 BfZ*(FV1oO5.)Az`O40~C+2C҉Ar.BpSlȷ--e;Nkl9^(GK ęb(W7z"$AHP?{޼O2Z(l̯n8rT*H-:g&@dI1]?R5@"ܒa)|b0#h*Х@%]xD;F-EeSӍ t5$aA*R~8j: -2s /{˚i.};o}-9R|3٘.ϯkZz-[>Ƅ<<,gY%X晸ݻ%橃SDm+~IU4X)=|qB$`eD(g1D D<p9S@W'B;PcxIPU`EGw'Z5 y,DZFgW0 aۣ~Bd`'q/#O%OJ( Ճ4Oh̒=,h8PXG4 KKZ_~[}hhNgFQ7Χ?_|qkUkߘӞO 2:k"GnL {zP5#!l&G z0uƌ!ѯ`+ y~:-Tz :fHiK&&PX7-۴0e\g<\wZ -9=IOjR_;6g7fl0+޳~7W_}u >*ݖC)$8]}~='CpB4 9 a)Z_O 7hb SBM B=)5M9nvJ, ě0*{q "G,zO0Io <0VH.(. b,GsPh([,HEE#.JO֫\DJє h(+lww .;vjm87MLԬ~a<Mn?fShKE+fxsX'p4 WqJS"Irhq4t;*Mz6()%7|;''- MO~w0 /|bYWhNKV(P_0N5A~A.B?:ΗyM>} 16$P–zƩtמUGYPKC6-EX;,|H0'Xԏzg4TD-O:e"59cU*w\djḨ\',Hd Ph׼5;8Wgy~+6W??ox;[o]ͳ[(PЅF뷳| P zN'iw*d~Mx8aS~=v2yÒ<#І1A$wlk@E{?B s*-e" Nty"LA5t2AX ړOgLDf~a CV^3X!Pc{AVm׿W]uN`5/C83 v%/yI )_C~+-GtB 3GWaoX~-hbt9a)A"a`V"L@+!Y)&LHh q;:z!FcH:$()&&'AXDԽhգ.hJT^Le ]G_>vm;-7~7N?]5瞻Sy ^z׮݌m~/݃> Z(l5xQˆj ~).CXC ;NaS~-2ד()<1QvB"zOXP@^"&BI#pKBd2FiCʾ~ ;xc'1 [LY qX?OIwџ 73"׽uo՗>R mPO>Z@kܼ袋V6q{\kUol?xW5ݣ6>Oo"<]!GҾįb9!qįe91Hbu!6!l:R`,nà6I qDTrR7pe#Q x{%#%K@gd"B|5HG"Ba?}{_+) iO{ZGˆc9fG?<)vZM >*ȀBo3j|X¯ @i^_J~-[Q5rB)O\x$r()D@>qވ*'BSt1>k`V9a1gs6ҟ1I$R1D, F5"R uAZ#RuD-|_z {nM#m{{ڽ-lg/8p`F< pq=!yԣ=l:޾\W|}Sچ=إChD`wLQBa>SR@>4g Ln($N{ _ (U(*ԒoЊT#X) YF0aHdY }4Bag?KG[F|7eo{kAG>>PфִO|Ľo+W[{ZJ\(;ejhZE5\b-SOABG~@08a C) Օ26̯m3?*_O,!^iѰ`M5H@AQKain$Dht̽sqD#u}|P"%I.: ,S%'&jH޺=X[Vs/1eW5`ԖZb&4};Ȧ|_!=1iC[Z3 z k:LC1JU$RtB"o;ڐz8׺%ײ_ODYWP?& 15@5xR]/f ={?}"2yT"> )ufOeX?B""`a*D4R7<pᢢduIs>{YywN/Er-m~+Xq}h{TCUV)8yעvN8quz\ӽ> Z(l%1(Yb!:vA (lVkHل_kJrE~=YXtJ ꒇy }E,͐x>rAo@i~Jj E~M=6,h0ݓ ƿJҬY<*a шAK_@RwwM7T|0boQإ2cV p[t+..;l> e;GuA %(V" *kYrN2~JA,&iMF&0nK}cqU4EPk` *SG##Ɇ~Ǿ?0b SY߳|InQh<2TAǩ!1̷ PLI5|Ba`/>xῢl?ǚ(h3\rɊF[XKk}y?,wPBa|9ez@ ۈ_GNL~݃u~- ZX>LNaW*č&qcIa>aI#0y8aߌ0m=PB^B3qFhuJct {`w{ty„ InIDo:+F ReenZXwo}Fj?^s܊{Mag?BÙg Wvgy. z 3tJH_o|z[JJwt}̯m)v_Vڶ= Rz ,Lr$e~d< wc{APN@ IUc!Fl[}#mbp:G'M 4" TKMSj: fz-М'[.ez`k^zi ;/SN9egs^}]tѭ޺A*}T(7@/TO̯3_~k ); T e-aOPI@dַR2e@.ԑ:ۗ4+xyfEehCnaqA$(G_@?}ƒM\PuSP=+`>Id&OZ5Ƨ>U60:V  _~_ n&,>;B tz2z>r8&z F0V__ hx Zkh^ RAE:vl5cI`JC%~7a8DUۏ@P^1,.~ K~0Ŭ($Oɍ1Z?#_FJ$# P+&9?[.^nu~4͑F6#Hc- >*Qчb_yr&F|\oȨN2kY:B&}\)Agf>]dH(#8`Ѯ#. Y~y ͟( EJx oJ!\A"/";2}EX@5r F%fT匐4:B =-''|78 5\2W9FflPBa?z7~w*.!Zu e,6أǯ8I$VK  V`} RZ0z&Z,< #J!ȚqK.$ʭ2 >RˈOBU-9`Fc䳉#B;JaU/ Xf7~7"HB 5F$pG2~-~O _[tw4 CBXRY"!Tk 5}NâɓpF /ؗD B)r"> ΈFgTz 02}:p~Y]V3 (//NSW4 QE- ؿ UP(uPgun|˴GuA EkK:4Vke~-uX_&j}O}fh0c0WQAc 0B@hTMqPDX g4=>Gf#T.„JbQ~~fSđ\5v<>CP`Q/BaOK_Ri[QGuA 8qۤ LH|A%qşh`X¯-2o55{D&÷d# ~DZZ|Ɓ)ze?[]&aJ@ Pk ` Bn H~?a Q"H- RP(,1zM`(e~v !gUB8,DaOcCm/ ^_ 7:3::QB 5{wGl K5qV,f:8?8hQ,]I~ ls!.xd"굞ΖGȧLDk:рèb nT{) 3!xFo_ ij&NDc C0"<¨scH k'4a:Kzحygy5^^(PXcpc'7zEB<=$~$n⦻,kD\.ErPb).WozdPtY!DNC< "F}1J]"ر=Dw(~4Z/aJ>=A>獶.wPX/뮫$Ba=pW~ L5w#Hu z t8} rn_ _K3:V/kWooj)BvP~s< Cyze_衏3;SNN20Ua.$k7JR#Aթq-S8gi& w/J;%5_RGV^, kQBUW]UOzk]1uꩧ8A'?xi ;\Š&4kN=Ik n_˘_{o|XokoHC CTЎh~'[(!?0WD yGь8 Z(l8 e~#_w@bp"|s e!7?PDw&ir0.&JBȜ`ch,w9%h"ˁn ?X? l#KoE4%!"4C't&z>֐G+xJ»'̧a*1c#ZBC8p_gPQH7AM<@g q}{k"下SCDiLh܀vb T(Ң… :g^H`xb)9+)1j'.b&Œ%)Xz $/GJ~xigĦY)bJwktPXZo;R >*^'"f2&~̯}`!ޜ_wO(2]ם/h(qO5SvA$F9"Rq^Gp#I0b@GꒆbPĠx$UW~R >գ&3-BZN|DE;|9,!%bXcȉ4ZfOFC|a 5i$;5JP)_<^Q()l[?h kj|k?,V(PHZܠr%ZV2~~Q aW8(xɦ:'0!DU9M"g s' '*1 Ũcↁkv48J3 Մ ݙBx`)-3) ~~^`] zL%ȇ&$AX,jacɴ.JBs6wܱڰpկnu vv  >*^1 JR? ~-)s NW_3!_ou~=Z8TY}s~mhD*ⲋAS!^!C1N#"D%zèiC 29'e1…(3bLElC$¥iQKAID-OICɫrN25"n&[OToo:WZ~BGzC) Ncubz)@D:2ܿ.7=%Dob¥Cצ %3s%B17ʮ!' vg.  ExB"}aˀ-f4{)="HC#%>d*^@4Y:ּH׋ +/CaP>6CBac} z 7R=BgDOMnЗS0АE(R$$}A ǒBa=|nP( BP ~-8|&~-:׺%XPOc*b?饓>Ҹi;8aRzb91>هb{T4bTg@aQCz|%nF UVM$l Ie0^!a+|Mw]s f#L,0׏S !h8% ;pP( BP( onҳ&h G6'`L-&{dD$%Bqp ]'B!C%%.*礁DF 7pl, ½o~5--#Tt# z'hψ/1AD:u[v,2ꃃOdlhȉX0T4xz?nK%4D %RXx"zK%b%/rcM:?1џjCIшLM2x8`fصϛT4xE8A7bZŤDl:BP?x uM uA k!2PHba,G\ ?@(HD$^*14\9= tM.4 Q;0~#l -8 f/FYB !{r1Hp5 F!lE d6Aۍ >N x!,b>5b4b3)*prbXP( BP( Q(T|&r7^@ckbClP@4! ᆑ=ՕZuL[?,5 tlx%@MIhtr(&hI#%J=e!TEࡈD04Xjts _a_͡ tv_HfJ&5,>QP( BP(v $5;*L(NTS-c ayt߈.H"̯!XEQ;JzNfhFCO⏐&r/Q1iA2 pq('GPA i ^yhʡ xxR-0)9"b7XCs馛nף>clƸ뮻83~'tt:ebͭzAmv'.}؆믿=8z 'qK7;@#O9mٶ_c_ƣCkkX́y҇m/vh$Stvڵ_6'|f.+~ꩧmLif7|3buQw5o3vqPhkv;Cޕwy'~궟K7nOh:3OѶ ~ G^~o???Om~2\mٖ~gxY3^cKF/>gx]CiO{뮻άlk,\QF1 }|OuD.(LG(Tb:vAz6-zȢvK fAQKkLXPTa~޾'pƂ.PJɿx4MZ#j!#B 3<5-B|qεOoZBP( iFe5. W=`PC: T \ʯ t 'F"dg :R4yb CUQᅸߕ%9)baX[daFyA" 4C3aɂ'Y9^@#H Bhx'?y;[66v@ӧ͍} :zv'm\LW1VobrUuabd9|?F>CE[5\^;:C00oppm<=jvܸ*0:C-⚎^?pHhu~?}:gávu~/ /3,A!tƧg% 2j0nˁ8Н =ߡD;$AFe_CO.k1piTLTrm ڟHKbPRdJ,Z!O!YHx>KO> >2dqY ?`$,$z/Ȥ󮛽0Wzu^\h\P( BP(v/Tbz0'ٙ_;Ę~ݕ4_zUL`&2d!́`\虃N9!Zn6"~?*l Fѓ\PĨFH#${ɱ @׍K5VrAhOw$'dJi$x BP( Bak ZČ :10ab{ 8Xt `?!0HREp  ts ~=Q}B%Qp 1>`T)ޔI/fN|6t L 'XuK-}oIDsFH-49Б\4.ttGT5ՄRBP( BP(bX-f6. QB'$g)υ$W(t2k>xp݃@*ݓ{FݙtMA$7A`I:t  @$Z3ijjpR3e{⒲bQi$#¸p#zMC`3'~c~H@?ih HLhkx۷QM%udJ2 gި80 !pPfvb'DDK@L]#2\8KIZ g B^$5--&`DQE`ɜO&߳ST}`Po# y !~zwCLK+>z%,^I{ УZ sNoKjyHɱtښ MZ%sdB*]hoB㌌ˉUFh%4 BP( ®Er;I#N#5bٽw2 01h\įc "^BPu|@C|cz-2D*oS 6qO[8h(YY$) BP( nR&[46M>0#p;iЃ@_ˡk2V ]e@ "J94Z>60INP>!(%b!t[tK itƝ b L'b D?/f#',e 'fLb,:I#1ye& BPأ?: BPXWᓻߣLa)*h; JݡD|AP9$R"7b~%]jTC:e~>($$ePUfJ XA(4E@3%Dٞۇma=)HEUIOht0"arPҐ|SZ~ĩzO&:BP( '|rt4NT"r2lU*H{M1{.;QP( BP(v9e/@2wɑ#~ ^=/mo@D9,M5kpv?D:hv :P+bt 5aLp祎$8fG3^` atn;JeeJuF~tR <F= R! =<kCI BP( Be1xe -u~C |_ ֥zFDnQ빣RBFWC#¯qObƓj)XgǛ1: /aXp:-퐮8}fa: ~8Jp2OI,_( BP( ]0&hd\¯.Өh\䢲 Om_KhYA~=I(XT<@.{JF̄x;]=‹)(w:bx4Mض@ׄzd)sհб6Zz`C?a='P( BP( g%~)}mk!k(qv"@Q5"^vO B*{5WFv@sT]`"K54Ktc*,N%˄I,#I'.,DBƧ1wmjxD/0ТAǒR g+Ah( BP( ]t:BB>@Aͯeyȟ F-Kv"YNB)vrGx.՝e ՠ{@b@ё#YxBQo%+ &k6 ]*U`! *h^?b&C7Լ~EEi^P( BP(v 1x_ϷHyFV76L *3_2*+5` 4  DN}{dp BOD<K %ίp*WzYs@5 \A? ?{l[zUϹNC7Aɋ Ba !HPVmUZ"Uj*KR@I yNwIoo>\{ӷ;F9箽Ϲw5:#+2]A?X7ZJ,QyİGMhH 3^]wm&Zq.pݎ[AU׼5o/kv|?kqnp.k_=y˲\y+T+Z躉^ ؓy_waTckN&7"oiEʤac_E@FVāg`:ސh   8@@#@d&2,8`?_ dSud;uztZ"Z7Ml[#Ǎl1]b)&83\EJj;pkZB;aj`Ⅵӂ$!Ma=c}S%`` .AAAY HH9-g1*b2ADXπ_Eki9+ eb b8>+*WUBN$-Px/&k" ЃGվ[ك+ Hwf9XX{ ШG-IKpi]Z&nVA\\3ה%'he|]^7p<]PQ0ĺ ˯K8_Cc=Ad2#X_6&?lAÿT +I4MVvF"kJ C/G]HGNcx w DCg*IAr^;(٣բ)5LiT:QJUb`+7t-rufJA\x㍷z+W GYTm{%_=6n-~-'k"TPanj >ILm"3ádLpHqJ9mG V-~9}S.cof*әO(VTQDCDZO!=Luk    _/A3ݸn`uuVN>뎆MLq~m[~-ȯe˯1Yzњ3jntiH&b$#5跟&WL,x_3d[T &`EYa *(MY1yڨE-;0 IZ-PErWĊ6   8[FFuGd~>HBOv ־HnOr J|h { |x:YL}`ZlsњtE[n%h =TY*r7kr%GS(iCp2,$ "\   8ZQ5 `j E[+I[A[ c<"f}PS9\1@9@:EDQ$ɾIV184_B#|CϾXS>s4n{TMdx%:fn j/kpd{vǭ4r.GϷ2ŔZTr@!-ų L;Ť%T[?   34~-y4n'VK!y:j@f @DY M,| Q~)J, 'Ŋ>߸ "::V m!fWBE?=V8%#¯!a(a )O8grlHe42*C,k7W %   8ZRdȯWu0dUĸr*C~]! VV4oce(*~St~^?;\n9i/Pi*KE f9,3,DBPNt–K=0Y\,3;܁ PX=>PF mKbS01kJX]ЇrJ£+A G>ߊ.w~-rĠk=¯$~am5jA;\ ..7dL 8CV D40@Tr 0(?!zYŞh?GAP;)i^T3WRhPR(DhP.7趇t3~Ғ[;ޯ%ZnT^nAĥ}M5%xA BHAkunۼ98v׸6rxS'H }A7&PdL ,Fk,$2#)0%Zd'ǡ}"JIDX4m잌*ʼJyD kE2fSE).xRt%TֆE2A#3eV 0_AAAgPÃ(b(_X\;)\CNm#~6C0-zdqE0ZgM Na?(QPFbl'5sf?!lQf3Ĵ3% QPS xaBa{Q. l4Q&?Ac]8ޥURўۨ>:xhu:5oD?aov*hZ&֏aŒsk*A%KkJ9eh"V50heSZ l9 Ɖ|%ݚP^2A+2{k#!"QE!RDmv+A ~w_1LJLX&jrCQJp R ;X H5XThȩ:,,=3d *(   ."kI~m=U`g4JR =7! >{TN6z -!+/~YoS"&%2D k}X@s!j YIA 2Tpc[H7l>UK@vTJрn/ AAAq,ZF Q,k,kT`oZgi5S(Y#p $U, !`~7~GmN?#E1E;WrDng8_BC7uӺY9on 0'$l@ "7O4S@Mkh8GCk(Fsޤr7t7 Wȃ( @zu A#\wu87B)h% v~F@|_'_nGV"^mBo]tz¤Y9egx ~ݎ#dWڑdEUdOه zAX/=`)f P5涹d-JeSEceƄTHlk)#'Pfi^iq+qp-pz nQ:O~a AFt덪 -/58[83dV^y*6׋bmN jsAjɑL Y(r463;̰W?r0A ^I;^{zmrRP*(KmlܾR5v4aT6U!T A\ 馛Nx8=AAo FO] f%B6GMMjx 7dX(}zpLXF6s#x5+ʉ z0a@4s& CKXD3!T *lp7*.H̞C<#=O@OzғN>O\G(Y7T!mb &x@oڽe*0YJi˩'D/B7rL|5 KPSH(Ĺ]wE >? 'wO}DAcYFg1y ɿ^WL`KaCT,S /"Pt\R 0)@3BNQY;S1mǐ?Mafḷ 0[6SRȺT/ T([HH_,OD6 "U)o1II\nD _E_D  ?I>F 82Yq;u )`|&c{A"'GD+l܊_gcŎ%jVXwMq/tuhֈR8.<Y;xJ: AY8B#[5 ѻ!0Ѡ[y(_qa0 v QYY$v5b"x;!Tz(A/|ٗ}o_ĕg>Ch8Oj 98 N 0o/(-4&1u 3_ZNOjH[X`?6#(؉́ः(6{ӲfB8Z"`0tA6PI+ 3bdBȝ<ϨJ񝵽Wc7?b92Ao<r}<)J\>OE>Ͻ[Nr4'?@ |;Wg7~Qݨ C_Ϻƈ{k~[b>` 0QPES]T+n  %{( "[N@(X0h ],g7ÆȈ}vIwrh o#vu?`MxA+EHQVq]+KJ-zAqq^dJ<\()jiN88Ac|W~e75}ݧ ?O(qp{~˻K:CAq ]*H4BZ;Ӏyj7ϓmFpCדƸD7|6p?HaMAH'dKEW$e.CZ]R7z(甇H[h!xx8BqLBް[=OB1O+SM؉_<~랓"%zkjORm %/y)xOakys$A\..{ _‘vKK? Aƀ.p߂zy>Y)@T1Z{vw$k~epP[&2a ;/[-VJP\Qgԋ3(t]@inj͍+A"FCzC aLsЂWN4~`> &>W"_.yCC./i~Zq__E_ty'?̺P}Kg<__|{%]w5 oƓx>*'(4AW_{@yQ˖'0vȯ7thH"_/~!!;tΠ*ء< 0\P%6=AR DhIGO#`}.suv||A!=L; \0_k?XZURoЪVR eB`Y?AWe/;\/?|;CB\B?o'Ñt1ct4AWҰ6@1gaa !h_\ V :̯ AOE䃆/qĄQ R$ MD>CZ bBUDR`o=c&t!9~0i\ 2]ˆ.yŴE3aGlL);(הy XU6jK_1}=y)MMOd*ݿ{9qtbX-^"4?] JM2; -kg-E2t:#shu`ƪpqA0 2Tö)ڈzp x9r9a~`80R Hd̅fJ-7X@*?5yn]%lm& 4Po8wуG=Xi|\ޤ7 ՍvW{8CA<g=YOZIo?}wF /^ qH9ULXFY08Dfà7:D 8~}*A?cXwThD|+!+"Ra {?lN3Zi I {ybʹGk-elfXcumBfVJh;*zN"bPCvEe"HBAW;տo|77^%8oo1v>{yy¨o!1Neo!4\61tgt ≄&!q455$aM֮UYml~-uo}˯SCh=kzŠX?Q,|ą:pfHB0M%R}bAPbٛUׁEȱعT3TPdvhX2)!2k< 7A-l{P%!`RE;mNB=>[,Wp*t^Vt^fCVvXo0'|u=`>]9#,#Qsdí3HR3qh?=*bc55dPN]f4O/ oo[/~'~mo{'(?_F;[wqwz[2hg  B |A(dA9,ލUyȯu˯J)_'>d^gXu( -Vkxhg4O L")_  (D$-w2Y˴Y]<.L87 ;|))E*I^T` W2,\̘'ʏ$ajگ˘0~{ q1"u 3_5 <9Ō__'?EA\%igX-42>I7+k~-[~ *aecِ}0T(E9McH\$ Izyӌލ]>ChSpoEuE;!3(pH(~MŨ` |ܺpoohNaTp||;X6q׏F//8GuD|c;S#c=łA\q5%3%=Ry~VހPC wOv2 :=P^ P:oF0$/6^gbM*f0d'8bffugΜDTDF ##b5)SmX_?TOǹua7?/6O.zQ?SezD4ngM}WFH:*=wWjS2aLO|wG>^ }k~Se\7~7>'0?Lj/^ה%Tlz]x,v-sh$~'pNqȯ!"ؿ ML@8;pS'8lbG~G~~?>AU$3tʜΊ';]CvF(s$#<E$TfSFledhʶ(%GL= ::p!F`49H~L#n(Ǫ+c҉0 >qT "a=(ϓi8tNylNLJbYrb!X18Lo5j5\wܟ!_^^/øWzrqѾI ȮhE"-͠';X:$$KLS5R0a/iUXʩlϔXP;N%hg, ADK|ڼH$W5󑱙կY;iF V)@MKBN$0u!ߜVx-RWSSqqu /Equ#=bؿ_k}gjԜ0?;;22LʯS2 ~p#CA\XTg=1\"AaɯE0qYAqg*j&Á) n^Z69133:)YW_jWWt#1Sh[5 qHp(n dK Y}Vhm2ϥW+#3+%])U2a.Rߜ#{0uα7M_u_7f:F *?c?v=/#H唡43?3?/AqUA5Swߜ>Oxȯцp22`#=F9}4'>Chz#0LAxBbH(42B(:jzL*"B96)Eo~q.' yCnwqc+cW|W_[n<V{s Z8~ x_Dj_'qߟ|1J ,>4֪ ye,uU7nkw#Oe!ː}dLR!j 9JbLDl>s2P#YO YDgDA{b$__=#[׿mAnR^Pȁc=>3?C"y衇cADIY{S:xZ 傺}~^߇VHk= 5yQnIv, 2ne:xHŖcghcB߯P,X?;ίqk;Ư~Ka(,mǜզ=4[,f*XX PVu{hΊTUUD{ҳHW6Ɲo؎We$C\/馛N9ld@e$Ao4<U :wO˞DefYYOC$DNe&U9Dld)1j&! 6MaO2!vyqaƏ~S?>v1cNanv^SrQ_YyM5) J\Jο@H 5a%KO~&WIBJW`8>5#g6-Qc SY:2`EzBOS?sYڒkR_^Քd,hY7E+TL8"`jV  #?]@f6T&(-e@APQڄ@{OmL!Drj?4%BVYZiGEgX}x{}}_U_ԟ%! Wxœ$=/eّٟ1qe,o\Sr^S^P⊐Qt0J\BmJB4Dž( 49h܉K|j {qAB砱_^X N5%#ҳlyMG/nx']$bNcm=,;Cytk@`9+kJ"g%eOIJ$={r TpVS3I sPD3N05ÞP^j?;(vř<ÐZ^Lz[:nb~7|7|w|m#K/Co!4٥Uw?C?4Ik 8D\sZ05|wcN[Yb2~cz??oBAH8k q ,n{E1}htX~CNxH[R% B5G;.".nGr~ˌ8X/񔞰~2NНFPz#Cf# 2#;sVCFjI{%I]zYKPIAZ2#*+.SX_pEst"E]FEg |w}]u1r/yK___ 3|7}F9gm4G% 8Qkd{,~:4(ǰ?Aă"sKf6'BG/9kH!aə[0h ,:b2!dO!Z0Q~-ɯC.,b[s" )ƀ!Ⱦy̐XCT\ =zej`MQ4&hwtl5D;م)E  _ʈ==sc9!ۏi5%xA?3y/a zIO<)kJ' Nǥ&%|tIr5Gpq\b*K*QX20^r%>rpX]".׾fBdJFdE-q p VqϜn͌ƌilҬ&t?L[2A!߆+H8L?|aQQInZ&i5lȁ81ь\<```FqO~{g?bF{>C/o/=r~~{Rnk:B>75%I6OYX6}QCG̣,>R Ճ\ h1Pfn, xiD+s3lѻaVTx" VzluGG3 !ؚ. uhcH8ɘ4 2N>T1$3Vk~h ]I[f&A?27|GFOwͭ#^{+_ʑяCbx^я~?AqҠ 3c#29-'$)Eи);@<4$kqB&՝h Xdbc TǢi,G-;D|q@dxd\ P{.dAFrJ*6dAS$ʈ6 'SNa29""bR"|s}n 1 Ϳ77pbn~7~㘡YGyGK5y͗}ٗxs/>! Ach$ $ M̼$$V#w!!!g@ 2j2ԓ_~\.᪨ǭsNKKg#H1b ].;~LMLX2 Rjg%<Ҧ`>)9E!8s2qbc|;ZlxRV!u_r"HUwYpd_fKpJ:@$nͪxYH ʌ8Ej ݿw_=nrqaz.2 '?ALA<6uo+#y1x 5ɨ?|PG5strHWwuo0jS+dǒѠ $t|.9ʯ[&)^@6 0 }%.P9)N=4W|[XNS߮IܹıAWᡇ 9k~GEOOxGQ/ AEu#%s$9Rه+izH.h܄9PE"DZHwN= |+Q] 0t0eœ X"SXDǮvjxIZ=a-ѓ cp;Cv\N!J+K7;Cldeظďp@NyĊKLNJt .-m-Qv=3"kc&2Fl\3A?2'ğx;cxo}8Zq^?ǬŇGw AG΢adM6Z*3H,2|/NBL0E4/{JWb(VX Y*1.tQ*qw[k=_G ~R6ȠUymqHB \:X/lj!OϐI%wk1go5`53?yȆ;; "2۾ǭ׋ CVWUysWPF?m$ .ra EdE4i',!٬(%Xh5u1m\B vaY^70-H׾.|`Zizmz$"oc)' a4l0_ >Nroa Zq l/X/gPHWB>I>ZH++1lP!@q֐ T6F{q1:/_C;x39F$.^nooֆy裏r3O}S_>?O~I bIB7d #gZA"YI+]2o`K儌B0:CaQj5E w1 ."$`@޿1\cGg G$21] IhAh MW{̿ v6 5 !5 ] "4T0%PPa/zS=f)|] e|Ÿ\8x{_o-뮻Wx׻76jؿՃ<)7e__Uӿ,v! >8[G,,1,-zA"^ us P5KL$tC&2!yK1l>_.+Z0`ED a|MPZK4uhkX],r/StgD8ieiA12 )%ͼ}o?r7O@QLq}:̭[omou~}_՟_>F_%_x ,>rnB,^S^PJF0T` yQY1d蠑E;"v`)vIĀD/Ve%rf"5L$)cunsLe'8* }??C?4?gg|o)+{||>&>G[1. %)H/v0~[niCY뮻`X\H[4.RePBUP)r ,jZ;p4zB3A2 H +!): 5nfa~tMtL%Ⱚ R?#*uJ )p0b8Q{=JѤ}l-B~'^gALHx嘮d!8"aKuu Lnʬ0,ARr"9q92, ScW[:<`5 s۬&1@\. y?#yafA$~W~?7aSAHg;7K&*CBKf8bz+E+rJp4@~w$%Hx9P0-:*'1&Rr̠^  CE -XJ,AJTʁ//daͥ+h9aqp `g<)VݖI32dnFsv1(1kLB>|Zˣ5č78>>܊?s?7կ~$"1KH_HxkJf857ְ&(&{線Rke=ty.s!?FH aTY<1Č:wUH O 츀e//[*Zg,l @u`CH"u}Ň|Z (JKaGk>LO@d%rTN}H+uSy^53Budb%o5Prk݄ƸIJNB 9{Q#K.dEy7*F$0bsCueI-z"mbѤr^HE6f X%l[ Nz,SYLDFwN#79qS(I5STh洒~ /xs~o{^6-qCu!hBAK7V32K(j#=Orgi:0 /|/yKnnn AȪǽo<, G!A%*jKWާ$5,GD,H%l($CX9( 7feY,8/ YE`t*RAcTn{ Ǣ΃:uGU'.0WHnɤG ;^XȑK Sn*տވiV.;:8>AO/ό!|#4$Aœ_i.ʠp(9ocH^]|:!!2o[k'" ,l =|wvXO+YӇ ]\((XMc).#` < IUZ%'!`4yWJ&8J6GT {w*#'____<)OyCPx׻5* ϘAZT.F ۋ8b9-BVbFz PFU*Jҗ`5(Қ_,R>(#'G|]X)#mbia `ůkr(&W`Cu "z30Ws@r%>@Uka e̒;",f:6/00f "裏sň_|x3O}w#jD^$*Xg#x ܻЇ>kkwp 33$o|w d F侷rK `bv;`Ѡ X;ًnC^vC=璘ƄePzmpDUV5;.q5~{DWЄQ,|¿F#w駭/@*d4|`BAADjN;i]ElrPk cVc9Z1f|^P  0wX05PU'@A8?U 4/*mRR Ò}KSHy#|ġ~} kM#C0-6RbJ{vA8YC#kÓI>n~ Fj$G%Twd̃OO gBrAvX1sUڜEd=`i%8t`䨈;2v)8BAAAMan1 L2iPi.dMf $1``@Q#[ loH9`;)/'.PrP &3l23ܑ1mJA>JD4Rl Fk;!Z CEsaK)`fQ*è|GB%&w~C {[$" gcRN܈SH\ uE¥ G۶NZ>)^qo>DZB̆WDյ4hkdX_JO-ű+:)_fS*!":/55>.HLVf"T+5%xAK￟kJN+\Zߡ+ 4D0y/`~'b@ )WQh\d^>z)Va(/P"K:AXD橂Le" ,+iRa*.c u_'   δ7# , {^ = UP! MΨHN<*57a ~Bb]Xa@l5L4FLSvR o&X 7(Z`mcH}d=Ư? K#4JouH3huD4D2 ctD%BDIAAq3 Er;U?Hfl|0Iux)7_Do:a6|9[~]5oGe2=Jpcn{RxHu[?dRzMCkTF:[ QP#mHH`?b)AAAq6u-PY Ts2ҎĻj)E@h9kzD?G1rs~H 핚MY t4Ǐk9_CdC"vqXݐlY1pvʕck2FE#c0sBԜ9@AAqmqWeRl0 Ot:ae$n䬄F΢ 譔̱ =ȱ]Yř֜9уF K(e-\0R>)kJg]mPQP4xEXcԲ5Z01g ˱ @wuSZ|a` OI">J>I-_'+>AL;O[~]>aJ*N㭟FA!R\k!$Mebڟ!:5)ĵ(QD[?x   "z ~Azs2h1OGipsL*_$Y'ab0-*ݫS[D2HoJLOak=B̷N?_K&gS\.n,aC(Bbt B13e '1RQT0, Q8 WWCg43#=3   δ X}<6n#$|ˎ '/` 6,mqtNJaa~xyJOBWN&/>ʯ%aïKM| t . O3O#+4$TM)0m~? AAAWVBc8d< ($4#4M0쨱l77]]0Opj`d4kJe!kWU;H?ɸe z#5q(rjRK;acd-vg?u% AAAg~^:0uUK G_TZ;AK 4A +$|$/ ER,џ%4HA#AF~fFځ@Ai vIL J+<F%BAAA1h5TBa6 wՂi8LzvrC{tOc55 ů5PlsE) _;70)h,zAeïUYP!)f0b `IΨ<OEBn9tql,bizAAAęj2,%R{솨hd0۹]4AX`;*(3| V#G#1Xٟi=.j FP(vLBLN@fKfGIP~NR Ašgbj񹃑XoIAAq6w#aQ(_X|Tǐs~3^WcsB20#JE$xe["]nU"):u;daQ\YR(Ng(DpwD.s9# R氋AufGNVm^e f#vDTԜx`0H^Sx<ה%.!Mq;9E   䮕CaELEҹa?ZF A)R *(R$ jiL;L =<d o>"nmBAďk(~- 'vaCȥFix sDtG5CFb`0&?MKOIe *@iS`^:A    *G#hLH2vNBx !h up)<*%\)܀ P`OpQNc!.%CESIsT"YːQ8(8C'eSb< =5J>!`4R56rJlR5hn4Pf)BUT!Q$Fn3~CN4,gvJ-rm-­5%xAKni\ .p+xM ^PR vY'X "wD<u0J|D )(7VT""pRm5m.`˯_cF_ǹiS9 A=r#IH[`(pEtCL[ԇц/J##D$F 6l8P   .]QTբ 3(d- ՔE: { B!! ΗPT54Cq\iFv6k"'25s"r_Kk-uW72 5"EJs&tC&a +7(Oɤ#:3PiScC@2Pzl%hg   2sv`|mM0 C46[-0YSdCׇ_X9Gltïɗ{+W`GU S/"`e(f8LJrx Z[W   7Thh}.gAH*PYy*(25$ LjdaSXį{#I(_Sj0OmF%OzјYS2ԋB ,FO4 -}/`%^mG!Wo[G/AAAI"ňe,0Si4&~H®*<:m-"q5/Й\>L" 1#<#8j`cZP=!;N$<1K+!FLDeDbRlP Rhl?UB'qiPQT9jwTJAUHF34o   LC.GA2ҺYDPI,#!fR)f=ESQ J 突 %5Ih D;Gyow~-ZNE/ʎ _ME%vwB^( ?wB4Pj]mkEאs;PÂo0S2$xT B\znʂvrnB6@AAqMvٞ."f(L&a;Qti}o ~  AbD`!k;¯%:_ِRKT[f%0ѯ) Q85"lAR=BL",mu<,gQo2   좘xb%24& P[tF*"L#$Ĉ~ ,h!SHizvh oASV{bMl.-,ZՇyl#B&TV DzD#*K0Pk PV/(kJ+a iKl7U3`=͝&HEVZUKsZ9्q3 +0v~'kR |=_>IIgJĈDPpኃMe$ bɥ'dbDh 6>&<ö;h] 'lLbtynڎ+s7ה%.%^n) J\z!&\ g'>a‚4C@9# ,@(0$5|V}>1.G0J$$tׯEsẑ Z},_!Crj |(VmE y1   bA`,S .v5$)P0V0S/Nsu~]=e ut~-'$ƛ%c Dnu.*@W a>˫dIQSHcF} e +H#I>F5QcN`    6`=Q4b~:kVQ>hnw NKDD) W:RMXٮrXq~3Cy_ˆ_ Z3h_QI؅dDgSBJ@_@#)n)9{)q C~fo!ުJy$۫B}Fe!4~ x!aVYz!o IDB!kla?u@dcel``,'Ry9֊@=E*уKFWn[}5%xAK[ne\,`'xM ^PRΛ$`b- tJ(ɰ5bݿnOH2Y;6-'0NrNrx|+H\*!-}6k[BZg(;U=ѿ.轝  :/Ai†nHfJXP\ٺr:[Kq…뮻)kJs]  ?.LL='&` 52h˳B}(S$;%NreïçȯjA a@CD=gmPeKh "r|\NPBSД8'^,TǓ"emWsJAAAg1l`Iv5k rxeLm^(T9zDge~x~-~}@}_o3DY6fҧƝ?E})&8R/&`㮔&-B_-   @5$,D ۖ5 P1'iDiʈu!${ -.GYnȯ8."|) R%aXqx@3#2sg%dTEJVZe4LQs&Հ"%zbqLHA+PfN|NOBAAAA{=)-{%˷*rˌ) KӄA`zjJ>=q__(#d=F[hOu Esȥ}jF} n5;)5#`rTAAAAYh.lY R2ɇIj+Jx r6"b#P,?_Kk& =' !j t0$>*7ל+!ؙY?HSkbAق$UB0 #q :84}4l h AAAqVU >؄,n)03#=zv:G Z?2#͉iFVɯ&Kכlب Y3f e,$֫ "8O֏Bk>= /˦&J)FW\1oPZ1|   05KVE#<2ޜX~rE~yur-GvlSç0*k_cnvl\ӯw1_w8ӱc\sG}x衇믿o>7;693qI6v9{;vx<)biOzK>=i w}7>g>l=6Nӎgwy7x7I6\7c _wxO=x6v3j3݇ccp{j|;k;\!6޷c g#<^}So~ߐG0Wo3積K0~O:'诪fS;0jX8qE>"0NjIO3\̫:Ko\|q ycƕ=ۼN꒽/8ν ړ/ F`yjlk X4Hdd>!H$ yw *Y6a _'vY*1V?ͰTX⁖؂$ Aa嚻lv6H&U ig%$w\"=kJ8:AAAqVenZXj`f4(Dh^28G0iW΂!m5Y$#JsN5*@ǍпLF|Ij <;KA&4Q Em'^ #!F3|<6C |,5]Ot7C] Yv7$~kp뮻N~߇?aAAL}w5y.ɲdǑ@)\BP%PZ{R`> {c.3.?a7q/3C܄jxjႯ~= vow]VxF|Ź# } L(w?:$zǤB'a5,(%?u(_/Hs+TïOC" - SŐivj_SC.F?bYk3l6."ѨKb1.sq}:̐T0^G范yesBPu64}-Ёn%M%j/vOA{*hC=_gel5|zľSBup_2G5YZSN~ֈSڠmi['Z+ZGxL~|.abW-?=Kt9:H cS"r\Y )<^V0$̯1NQv: /yT]o|@0IR+D\jLfc}8^QzټrSƆ   O-5PDՌٿv(j8+pO!+҇>/_ ;GΙpGMpFYX򜒨Ϩ C"i):6~]*n#0lkhz]( J/8)Ic1d@bHJAAAɛlgn3 ,6DݓDhI[Qh)#1[1R__ӵ+8^םIv_HdI}a.&e4z.Bsx^ b0:)N ֵxS$]]   pgb!󻣹g/d$-I@gc̮.h,&2g.\8\DPC죥7RB.fTzšt85J7~MM+&Frhy$? ͩ;)~㰫IjEb'&HdE%{`d_-wAAA`5nV#8L5x@]u ٤gx$0sv*p*%x 3fb ֋gBįiHK}|)A|lC8K \?i!US9%paY/iŦ;EܯJ.AAAgM:PLC% V?Ce@=ՏSsl C}?e~m]bW dO@[ɡ NWf u:<U$% H;2ǀQ xN* C5(ƒ.0C ўjOmW4nK0;"%|_=@["E1P:axtf0 #5q%(rsC@I6W5'_2.v];~|S!E|%0<'{3eLڰ! VSd<'z6q444oTІ SA{*hC6E#ɂ@lW>IC}&&OWeO+T`đ91Ø_Ljc`R& $F/aBibn {ɒєx_('MdS/N(#Q   *b:Z'(r(3=) <%.R(k m?oODuk_3 x2Jе w~x6 b@Y7l6k2-Phf7R.R   "9㚐8|'؉y`Xę?D8 )%ǽZ"ȣЧ!_\#F>6~/ů#x}XKID"ֱV}A^vh)Ά\y`[gT[0A AAAX$kvp7D ͧ ܷ,a KݷT8aKZ$_؇&btԄ}1CQi8kS +D4Fc#^aΟ'Rډq`>:ێ9%іUCb{D"&IU_Sy@=G}t8SA*|Pw5?tXf_^,-sbN41S+}pVdCE%;jP _HbH^RkXN xl~;`p>LTpfvtDyV' g@<ĨҥKAx37yS=TО Я3^V)hw\t7frZ$ L'it%񈚲k!v*|>RP'ݡS.O1:vױkP[΍HeqBDlgqBz [0gH9[oSsm#,.lLm^\AAA';M0 *8w$\ 4>nc nh;K(| P{=O7A1%1$!l#__Ư_5I.A\⌜0^0#ɿ=xd?ި>4%@j3Hӕ   x8 1An|[8s089 &?!01"[8 =VςY_į=l,~+fPg<5n\C4!l?- 7%˘^̍iV0GydiAAAxZPb }qm VPaSHuip;YnLI"_ hDdùl̗:^*1ĝJyF S@C]}XFmVչ zGvϠ7Ece>=u&HR:B   ,50C$9f;?7g(}&Cw}HbSf%ok׃3&^uh_۫Oz4XDpdћY h+A! ;TL It3j2뽗4ǟB(gAAAx~~vFc0>b6|4s= AI{L1R F,E6_hШdGTW")qɏڞʓ_<;`ϐp*1>KK֑%-߮V|/\)AAA'5=?kz|\"{ n]+Oæy kcG_ca!7Ĭ F0=F .<%"ʦrD-Tdۚ5AAAEgWAdb~:D>N7x%Lbo.%.`"8!兠o{jx_+8'~:Nz_z4H p1 ߈YF]c;5P'oUu){;ƕ<9d*;A c~N<+M~nZ >؞RhOm!+m7EF~GX0xƙltc8g@5r$H}tvUfI~ʹKyk%'X*3)'T%bxGI*Sz)|hDY>sbN9rDTޣ@xȄ'h6To~EО P#kDzW"4ÄC XoEm{Dx6V^J7)1$8_]_{u16~5a[qF>~y8F@ Ĉ;zrt>jŧIF   3+ .wC^c%}N(B? n)KNI'+ya_ 1#4zI a?Ya**fίKYY 'If[Xio%ͯ+ML/ X 7bU`qCurٻVF<*[ph{Ou8;FhNt?In AAA'EdC܃b(CPB_;S#̶) }b>/uʯ{k$^RIֵw CbwdEȩAђW4Rf !ܽBo   ZC}6,4:1`@?.-̄_/ȬT@BAQzJbmY@ϣ,2Ih YݰHS>_@2O] ^PMūy@CW%&_Ӣ=^2rhEQ.Q~Yȩ"y c#y޿::Gbz9FVʼnFXُK ǂ3`|iAE֊NIdF;&õW}   σs^k< / CaYT*agE\n?x:56F/Cf.I塡ː9#2֬D 16ί̘[ i] [,MPt#6;Oq ]3*inqb3| U7yݴSA*|w?YK=‡r4DŽ~$mwt0,#sTꎘH9G[ kMg~]bL)Y)%+P Dfa -m@#2)wJ% 6 dc;k W]2iq?~;ud[D<%+Y'7?OZ TІ~u4# 22?bT=dZ$"UT'BG G"l(~j\l!^Pq yYeY3u%8jn5׿Xsqڿ/M0t8 Ĝװ _0bfPZwkֳ:jAAAxjs/;ٲm>.|ט?sBl #1¦>rɯ-`a@c Œ +~~h˴r)a$DCbyiu7Y'44/rTTd"Ieh"/VAA)c >, P~fF'̆#mpGb>H-Ӣ?$0?ں_۪(FN@N*pi˭1- \C2BlEKv"mV(E`H1p|ږlJd =QC&   <#_W U/ǬD;΄*((|Y ._CG0n oS#9 !73i3d >w}ʴמ PჂ>lhS>zp1,IO}?#씼`U|Ưu~]Y 4@ٓ.颢)Hzu`}q~Nv E#}GBK*͙ AyBHɩgD;ЂsR5)P"Z-WAAY1r{F0G#2gqw!?5Cg&9e#ފIO+̯pCu-Ic xqhh"YP"c&7~} c 5I6ImdO2r!PV=|a~O{gNqAAASe rwgpg_yW_L~3=w#h_ Ѱ&L}+6&XzY@Ry$s=-CW]AAAҋA;)-auNlsW"Et DY q%GOG)KL#j8"Ve~z_9uh;C ~is-~]HÅgjbmވ8c{T-rA#:€q>+FԩQ Sol AAAY"!xӢ 0{Fɀ}1,_[{11 A:8,p`B]p5:   Chh ҃mn@ش ŋA?ɳ?n]l~ALak||5>sNIϺT2AFnm\:YE}ʘ#".#1 !}|?gGb&gr)p2G9   ʝ,2[gFˠ-": 2bE!h5 W mUBI: `dw Jo+׿k8ܸ`N:Uet=buqhuXzhR?R7 Y%jKɪGTР M:hOm=6k.1iozG֡lQ*7c-* 41,AbwnkH~ST Ipd#19LQvͯZ_Kl_ b3VGdJthk.X1CK"XNFl!_ԇvJ +YzHDB-&S6_J=‡'|EО PC,HvT DدId—۸}|,D^`HVĊ^|_wEO xXv`Naߴt4LW*,F{ #=G'+*9aZ4A`0@%UE,J   (CY(lC36LIl2Pq%=7㔉]Rh!X+~mL= "ru^ɼ,۬@7͖-,V6Gj02))A y@CFj\N|\pH   /7P_>`3NI3{#d=m'9$;,#ӟu*L915~mQk^^Tz<˱Z1:Ѧ,b,48&6"hp|:^!ExE*, :F BA>   s* ὿X"6a#d8U q;)ClLkY]PBs3 "僰U%sXڃE}_ӂ4+\ zv#z֝<΋IJly#+tWzol6߲h𫰇l\mN+7 TІ  {zB{*hC TF>sQ O`{C/x>O\15> DSsΚ ~}Ycolzvߧ_V*1_ku|)~m'}`vz{] HEb} z *=sM\H`u%dmf[RAxk7wwOTІ SA{*hCVpث9}2v;x+=z"*ArmNXp!V9e~ WFdhBY3cHB+rT ~ƍӐ̯{7PeƯG%T;Ǟ@=a9$CϨY.ҲWRLKSyq y r4>#   <#sG=N/Gmnwxႇq5ͦ}SKtRcš.xdL8!) 7M X )cIǯW5|TxpEqlO;Fwa'.ZڡPS+VAyRa抶Xxa|AbO cyXD Ѣ   $]Ͽڐ C?"> DNox`~mxY1Xe" ~  c##:Ϛ(O V f;/_cs"qxCnPف(fmpjyA}|]ٜ'#všhfT$e"FeHrj   OT6L`t4\=Ӎi?D컯`㧠):T%fa%Xj,;МR(a^_{mةhM~˛S~!6K<2+=j X~le['1%aSm3 ҘJ*%G   › 8χZ3s6Pűt'cJ}( =/)2ABd0ׁqɯ} N-"9asrëQ" 5#,a!K'u[%9=-1N{`x' d4BBFvRhOm8TІ -0ӶAmOnZڹaqُ҉pZ?P56]J:ΡkZ:&6?{dkJ2?l vטyp8F;1@txgi@08h"6h8Rɫs&u@2H88T9!q#hOm?Q=_NB d-[ Ick$>$ۿ@r dg(B:Dы-ÿ@ 05M\k:r+_rC&    <;#:T*1f VT(1:yJD`y ט) \HV`rHmǞ:>6~mㅶŅXdl4.8d4DGs M<J@S^?^TCg0_Ձ~~Mi6~;ƪ6@TJ'F2)ۃH{(ol?2upu6a>"?j A#'ƹ?; E"=uО PA{*hOmM.vKH ttb-<8/z+ -wb>.E6Bv!F)ٚXQ=#D~;W~`J8 Q6#sPML <1g+UiFfL6t1 og2q^(M*WrԵԋ43!| ?G+k)6T0w{S >('p ̿%2C 0#IJʉzFգP_F'vL`"e%X^ Nu 5Lko~\IJyڒȰi@PTtdv|F96 Af/I}TB7)MQ-'l/'GI#}bL   L pzKd` ܳ>)1葁~o#'Q/id$DE^ђXfw`M,lFchkAp- qKo;%3g2ϊXʒii1 nScCAAAxJŋ%z<$ H|AFfyQQq 6 ?t}k/5akz!,e1*w(ϺDYJ7}|da 6ΑWTGo8%!D pJ@y   OCKDA0 AMl11E!AO^/lNGl Cpi-Հε93+9į9Ln5ug3Dy.HRoli8 ye/9 E̚Ɋ;Ayn1 <稷/   OP?i('F&/LBWL9zUYCz4tؒ/}1=Q79q׳!("U`CkzXY;0ۀ<`v M*JL +aKo xQ1 }̠GAE5~mk *l~% ~mGVYH;biBxpzMq#ID'YЄ }hFvl] q 1p|5itBAAyOD>価7I9,xxMPdw* ;d堧>ip"x_#OsVI+5*@9Jw@3>w&o\Z]7 XN_0mfqa;lr/D+ >TA sAAA(J5X5^d2HjRqdcZuueSG6"/zJlث7 P|kNv~Fq}KH χ'IV0!i`h A '7h(NM21Y^ }|L_C \l3vQAAAY#岗1h'LͯcFҡrLi*'y28:CiqD$gEz9֟GP&'MX3:@eI`IiSُoa=?t-Pj&ɿm#Q TІ~Ox3~FQh?i;57H.Rlɯa׭r_W0*&)91>)Zi3stc01"2EC !6{p⥏+Q$vO"4!* ?WUAA- &w`U 蔀_f?8F h&rdWdup~GDl^g!èZ ʚk<{D:wT =N7@KAAA)eK~5k̴jo/|v`_Rmb!B1KPOQ#%Qu4]/[? zayV0;P) "G$NCH0 ]:.(6~ 1 =\ 2Z!JD)'_*2 붍!l8-w$XLz9L hAAAxr^N K%_Pu=EvufaL~:l _ ؼVkl |.L|7Pl [&J*l=K#18:3WC|,<(D<,D} `dOgOAAAxZno~o4P8i<)`&!qJhHSES;' l    A ;+garq#J# D1C,4xGHob ~ݢίgMPQ%$p[u~|u([ gQAjc% ig &BΝM{=O]rV(xVOWp#]էVAAA S!\Pѐ$Q\R }# $fgfXΆ8kDO1+`Oφ#/8ќ7&x.>&D ]TF𞍋;x+բH6jO3EFt(ՄH   &D{d,xF9J;1>/ZżE̩_0@<˯qEB*psdRpKe/GpYh Q3",I\(z5i+:6.j`䡇.QN:"c|g)!Ņ8oJ'AAA[a(Y 4ƹ>2 ;a}-+$B0*J6l,v= ǃ/{y&6~m_f3D`n>" &81ſ쳗nZ >؞~S >0^z^3fd,qˏL(fVCl|hr (BA}k6ΰ{\F8z+B +itb].A Sq.N2;Z8Y_p)|aN9+ :3V+3񁖀24/e -1@O?"hOm!V=‡GhLx[9Zk(+jGHyNXQ3rNIDWC@ >{NK=F@!9x׀- D*-i4Ep'eu=x>ϐYGpF4D@," =)tZ'w~ ee3Fۼ   T*FK/Vhbrv?:1C `b&D0AUЕ"6GBS5|~w5GpN%;;ȟо bxdD?`Vo̩h;(8b.U'|ytxP?M+_9fiuugD笄:'AAA9weTqe='*">z>?pV/`Qr'(ם< PܣGL0_D?BFO& lJσ+!Sj- $Ik==&.F$#$V6WAAAUH2G Pˣ1fwXF`,bO8& X?h5Q:НF?:e>tP3O Q+a::9("cҚ_xMu=G@C_0.x_*9>b.zvx]@3k%;+rN|̡xYbZCL8C/Q*2o+b^\^   L"C8La>Vah;C1]h:k׳$9g<I ʀ'_;I Qldɘ}'~_Wϡ-)׀n8juՀWh.):&j#XJ q6fLDN@\`p!E@oV:#?L{\AAA'ŋwa= ? |}9Zex9K<(\@CɅ1#=`h/brd0(ҌOyɯtt 9N ap+JًH=AJAyXDɽ8/ Mn%PBGaUb|AAAgr4jgSZ/xK_qKJhBf>0=Zgke??F_OkQ"Im:ĖkI%C0#݄ DÙ oH;28~LĦE g4EV(3h17\b܎   JCSX/# KD\p4]n;wrV }1r3'lfx>S019nԒaE&#LjF8F;h{<7nsV6kW }B# sV Jb z"ZEg/t eʨI8R7^z O?yiGAoR|VWḅxxd:(.%ّэY5X<<E#ŀGm BsY̚hu&;Q\Z!9FThA*T~scz;{F%_K898AxK  G_{!q2 \t:G-]~w^kB8:8W0"2&=l餹d1MNxWd ;J$Q h pEr \3q_)r7#T Q|[ߺ?o|~О P=ī=}f?|6Tڀ xl;;KG|vc@&uGBTatb]?4cR1og}!ڳE 2Ed B$Fb9c$3[7APe俛5>6yɉCehIrHtZbr-0~*TIӌB.}HN647^^Քt%.{( Ą<2Ɯyh fWߦB]f2EVNvfT&%\5rPTNQQ~΀Q|AAAVbxam~ip$"5zό6p~1 ,w~ݍ ?tm81 !Qquՠ A>#9T ?6PwRB6z#Ziη=#x<<`p4ҘN;AZY@FtRo AAAr/(Nn\AW(Zi(8q,Va h p7Se@&f­6P[q]$9_ޏgC2. ,<%bs< _?o3gWdWRɊvXS47C][&n+?$ j}XAx?3TІ SA{*hC ~w3C`QA4 [oxʝ~QT1)r xeq~{2mVTAMԟ\8CsB|S_1lĥχdфLZ|7䅭{3j\#P#(s^& JVO0aQWɏ|u,DWUŸ~AxEО PCO?"hOmWODh<# /.Gځ~[hh/{C}Y.N@<}oI,R"J͝Y\ [b;1g_\͟ i=v1ׂ]C%!%+t$Q&ʐhgIK^ )^uxvF   O ^q"g 4ښjz?(~5Fׁg똘`;Hز.u&NMoj(½Pxr K$[$״!{+ce|DjJ\VudpVRK$(u+@wdektBAAI# Go<',ZDѢؐi<"M{ST>~1 0rzu@W5i`6"7Km sVD85kTB,ӌax|;rx2-hAAAxZGE ":3ki>|+,` hc&{r"s1 )oŀ1#bAiYpbظ+t4ipaagNw΁v-OZD 0޷f:FZv\K) Q|TІ  wHF{*hC>c(Q 'a8 B[Հ*4/( ^Vq&< 5Ut9g-km4"`{łJ_5~FTQg]aT?zٖ6nuGFenPF7(Tc34[ ֩$3   <3.D Hwv$gCڈ]  @bV%z<$oAퟎR sEE 83nDD4(F"|Hpq$x,i0ԙN8Hsd84JBh9#Jq1* >z/3XRz4:!  \V`cym3#2,ŊA ='l vXV3 ssc=\1ɵ3d@j$pD=8q>up1PW- dG-GCa7ǰH mV1Yje',:/ƌ ԁ>WEI+UcY-Jd @   3* `x{;ܝ\ xr4q Μ 4Z:hmE1#v$TEX0Wye(TܣWC %*G=H e0@ yPWDC؉ ncTՒUzZ#k!)(SJdg=˓08 X$vʉ0['H@AZ  ocF >釕ꪌ@3GQHu@ef"e*l>pDpqZBl̙\>X|w'ͰHeAAAxVu(~L"]|+zRrN)uevpt ~]u qWĄsLEԐkʥ H5 s0$GjfYH%|=u 'q 9iQWAAAw$bT3qSY"WWrA߭S0m!7мZl*0Sl:x^4GeSkU)(6fbnψyYH1/#JD'h^ǜ1x4^j.}hF!Qb F-Rs.);   P 2hD(m N9 sxfGYŖkѥ@/tE1)6{[ lܘٗD8)&h Տp^vrȣèBFF]1ֻĂE@%Jp`L&Sx TZ'2v =uО PA{*hOm噟ϼdx{I#ႦY,zɉK.)d"tUct(ڟg[IQ&&:҂O-e_ `?6˼.k(.JXbBx8'M%UK1K+`KQ #JR<U5'J# ki< @GyV0t[   Zu<砬ۥ(Ɍ^b`69&;2峃bs Qko^Bt7_DwD1qb/h*G6[bzkC(EPfoE#bvK&CY9a=)hAAA)e=`aLQ݌8G,OޭNy f3j(`q`-1 ݦXl{:Guf9&1b4`a E 3V%) mr:bd,#=>&|Hwg:uKR2S) XO鋔AAA9x&?ꝴ`6pQBHMݫP|wϴ&_CT*ѱ 6<QԖΕTC &kV O)1x QPތ1[,EWWˏcPS-^$y$ͬ Y*zgPXJU2 C^~hs+FR~駟ķַo_Oo~./a_/y?9p#.ӟ'x>G?Ï<ۭ߽ O3ڭ|W3v<~g\ׁ~oW| Jvޯ{fȿ_o~ÿ!O{y c~kһv߂n?U2pk0b|k]G=>w7u_n/ ?/> }/p1ߐs+v]^:>Koo~ FQ  DG(Q"uAw XiNzߡE'f }x 9)0v!?<'ۛ0b0"rɏ!7P^8<S>؋@fPbY(n"8 n,$!V?NYKZjOӄF'AAAh/|]> $v/hD QG ??'b H?ͮ 1(v4-#"P6w2aaNu1"ꅫv"$Y#p-001ф߫KR52_C DBS_lA ۧeVgPQ9;X=YJ ֒KBPvoV/ow?A{*hC-SО P $=8A~}?2a yz" /]_21/ 0&^B ESnG  HBѕх50K(4c,UG?ֶ sx-}BۈԶ@(5X1`j(CD2H4&&@"$6Joh P( ]g9s}λ?.;s]k>sc1h,gUCgbTR *Z!SxdZq͙ AAASgy{Qc ߼rzT2SH}1~H=[4;nna;^ja8*pe$EG=J5%b0|]c0|DQj% }Y&)2͌ hDTci+뷼~+  pUN3*\!F8/9D[xR Q`Zu]ԫe `i P@x_UdjJhc@}gdpME kE7k#| &G"(kq( R p*`l%nm#bNк5vx8O}L h<*o%P   D-"pgv@݁~8"FY)> gW/" ?BX{<`bb8( F}t1DE@&A6$Fz= K ndA} t'64c a9HɘhqzBDLCS|s}cD ]낧uО P{]ti)6T}p1::hp83D/tA% ~]h}"{/QBbc߇9Sc^r[P@8HYdK Fץ`Cƺr 0[tnX3UR JC:!JP8B-(d@F%1A* No60Qi   p3~ގ*6vN4= 02#@HIm%pD%CVx"$8!bs""˜t r &)1#.U]aY .LF!'3##ZVB@i e%hd͹%#-LuZN[0Ѳ^FO   |(#S+f$ޘZ4~o uSɥx"Nb8i ,&uG/ 0 [(h^LS,9* WZtcnWwe.3 / h@8>Pu>,)   \Uxbs~EmZhc¡E16-@R  v1TaabR@sYO1d0/LҨ҉Yϗp 4@u.: \ A쐀Xi@ jO^~ff1H\P1tAAAJbFFKV|~b2J8Ի"21 bL#*Mh3ݓnT!d@:xqHF]+YՎD$at5;\ V~UG0@-p2D^ ,"Z"!] 1\R:T!4o_AAA@AA"`帾 ;M8}1h-(%b1f"Ș:_PPYy AW뭥NCpL;@tsbS>!sV)BN9A zq.ưCtAs%)S82Tr+?EcY>Ŭ"XeІLuLJ>~О PG>TІ *CIE|ѕP`A-aES`ɫ AW`lFZ 满2Iw?{OzFӡ>NopAE@e3*ePwO}>:3. l@DPz?G$YPDo z5=~ݖ, W8`L7O~ 5>-TІ >A{*hC?23_a TU9CAT+qX1T`pNB~ jov8! 2 ( P DI-3r}D&n /.yuV` ?hkJZ$u!3:XR1-R2H,aCsuG`t.kYAAA:B1r.S@.Úk |M8(wgԋ SC_z XpfT2qT61]m1ABOA#-PDs}|Y` ~pAAAƐDo壻ہ΁tBftsՇG|38*@D>$́ @$Ș$ 6GMDhcWz`8I9Ւ -2cPp_@wS:q4v\xJ ;4šb #"U谺 ??dTVSHHנAAAp4c|QpiAɊN:J%j2-SM8 8z6(v[/j}KQ :a(Xs Z:$Mnjfb99&,fY2w&\id*%[%(Q"n&IeLB9U!a6TО SAz-dþ[GGD\$nq|.j\uٗQM HW8&̀bAh'efq +=bxH:%}jKs)4a<(Xdv1tdxTang]`bdGϡ(SjaJ̩:RoAS WpMg=>vB{*hCۃg>˞i)6T*&דvtG4EcFElhhCN:& +E +vDcZ #=卺H&`' FxJc]]KxOLk@~,H,0]U]aΙ  O'fǛQAAAʁr.UIc@فO62 a{'Lro16rCi"V] tAm] uygEb>C6!ߵ}%=3b%ꛝ>('40&f1US Ðľ    WKcfIK+*_zs[J1LM4}NY@&W B2;Q?6ΫO)'+j lw*/l50AZDb!n1B ޛMљe;Hmũ4(ijE`"D{FFЉ^z3 8BAAAZpوU ahn<;g8J=%PXK ^2E, 9.0$bK"`.0LIԬ?|b'HĨ7Z hcd!18g&BzOEOݓNʶ[n,w7D.8jk1adH9b{Q}v,&FJ:*r}aYY yȑx*;SSePƧ};Mz5JM;m[1AAA+GfC2_ bv;Z" *xNr(|x0!gQR =e!c ;J,ɼ{J0&̇6Ǩ+ 4`cK4 /[?!fքG\i\q5-!x:q p y_($HK P*l":+ c]]t3m&p.{-TІ ?c=О Pv 6Rè/J@y 6i8+(H*Xe ; k@JAp!̷ЏaZ zE0h4x{71NMI >8Xpǂ!x'A;,e#1jҡ_- yT-7 W[ y9AAA+7G~;/lv 0/< Yx| ٯ^qх ^M0'zͶg!WctIb䜘ٛb#*q GmBd%oW6 r>-ù{t niѽe<^w&>}kR!yT AAA"A2+c*L Xe ͬTy 5^GGOl('6:H"#`̩G(-i. K'HᾩCL-poo#uBӳ   WSb(Mwh8<7km*Phq`8*GTDoƧ~L[)qhd#!11aafAѾ # \:8-Ԉ*vF)!:b2j"0Е$JrFTa 3xЖ w l*8*k{:hOmppw/{SA*6F&{;4YDp"&2*+ `ُja\,bׄETt_tyA;z ҩ 7.MUrQVWx ZN ä6"Y#0>%*[Ѝ. hٞvAHeW=T{*hC41\ >*xr@ZD8XEkL6rLQø >3 KѹN i[nX`ҁ #5b +4H;, % |A)3byr$*F!5]$ޱ^1#*(AAA᪢F|`0DbNK>ȰEʐ<F PHTl`~$ůd ~PSA|jhH`Oup4AЉAN~tƤAbht|ɜIq1㝼!~_:wpdj4-O{xĺVEjUV=ȷN%#mDXu^ 5PhC4   UEF.F!aQE:=E(1:9<(y/* $mh$#H8&Tc4 D IiLJכ ;a!0Ka9FSݛ YP<Erb9if(>84vNAAA᪢ {vV`DFA:39Evy i,< EUbJ>EA080%핫;;s.Bu:>%~įo:躙s{UP8+F PE8ueR%h hm%C!*AS>}   UZ[7a׬D;c4~P,,mOOai(`훫/~TڸUr(X?f"Z!F$SSe(_۟uR(9k" iD>CM:5c4;!\c(AAA+~dA7LUL@"*(B=_ 'e<\O4*^$>[;4O0 JL~m>"5TsID5&$^c%)2*2!9aDEƉ5Il qHcd%b AAAF&G>p)sD^ bܙwD1<7zG,VأJ"-M*/A8;ak{<~aNwrؙwEGઠS̺PZ?ywC_;+qi ^߃ &]WF-k:(`QZ3812 2&+DbWV[LKu2>C|++5ϹJH1 (1GO޹+   \AxȾ_@%x8xhac﫵IKt8']H{Siԁ0s,PNbq$I~z^nB-S0|RWE"TŨ{6hCpp%dJ3=llAA^3u AAAtR=NApp4>\ I%}:{>! ]U5i^Y)>z OtA΃30lqlv_C 9ȯa/ Y߳~3S4)3`UX9 oɨ5//HtpCC)Poƹb&R"z-ȍcAAAX "k,c UtCd@7eX9JP1vLf'}<f`~Z7*!&}-=j.7u _Q˜0^K Aww%P"pkCV2o\q%M~*vߏtAAAasLf4<ތ‡q}j4h^&c(6p`2T_da# K)prm:|WM.&x1.@` 77t'¯7~ %sˏgjE4VxlJTtv%y98!mvqy*zZBV   WSn"%s M\wUt(CǨ ၤ "j8QL "[SD2$QGbe9L%U͈_GϯGZ?*K{U\fP0ic5&ڌ5>R*qH4R}(o4UЪ ֋˾ AAA b $)G< V9̊阕(oClotϣG|C8Énz #}Cpe_QK1M> :EZq:!6?%#0Ѭi@:N Žk 4?:"ə 0TgQ̘AAAљRqω/ݚ01X 1+17g'v+H#COp槸}p*vv9I*ͯD%'bc븐_uE:G+W`5HY[AR128O i؈4b*6ӧaq2w4u@(8p#,{-TІ _?h)6TmxP$шJ;1&?= YĎ:kRH~ZxZ'\=?uz]_xe!D WAS[~6.MDFl.%pkɧ]8D\8ò<4aQݤ06!dž=,vw9v;$:&|}@ LT#>j6TО SAzH|V}H鐼5lk̭[9sFGP9s ^tbU=RPAxG8qy~$H_<|5n= k t(U=߅u*aب2/軋:n8Yp[*N׈#B\НBi",MB΃6iFPG7Wre=l=Wٸ3e(!0ye1fi'd   peHX $*Cɬ'7Gg:HzE?.u$2jԸM1 :T:##/0#uAD_ըA^ڦ;sPR C#>{Xh 8 |&ͺ \S<TІ SA{*hCo0 U<~zg? s~Gmwr a64H ~M{Td2#~:ޮ,/ҖR̃qJ<0X/2ӱ'bq FJBTZAc'IcDS8]7xŭMg(AxӞg.Ťi8d{VIDNjRր-Ҏ_vapVVeɪIN;ԣ#YsuC,Q56O 1"jXP4   \ip$pa"YΉ:B# j؅؜[~ί52ap3܉(3/Ec(9"\&BT>' ~1ᇨHZfFoOˌX.ybz'Jw5/  xAOOE] )w=Y@}-qD?Ht+DP)au"@>V5_8 nìbOkxIk_%E졕X@DDZ2 QZdžC ͑]!Ռb AB%$ Šs?hk}sOytIX נAՕt>k"!9,Ix p4AGU u` o;CBB"XCEtq?*?@Cw}K4&3NCN]P$a|l2^c"I{8:s1IA?|JAXh԰h{ ;ʛ:VuTdhgJi~Wz3X8SpE|w 6 !26)ƸDXG|S1NK\(b-K|p>ҝpGvt`b06u̶ 8YoV}4"U>K K'AaŽ޻x.~zK^!xA*TEO# {Nd!IGtxl2-kV܎ny$l'WLHխ@*uY \at$on5%쑎>c"m;?Nwe_";$[;kCF~KUt;gOC*hO's%<͞ RAdEpѨ1`GUG="0?1`_8Gǎ)p޼~7J7\X;"zOmhdDUYM"rFwXؓ+̃f# A7pWn&7H$m(h4֚dg+!wzg= wΞTx+g> {nv~Ho`< A2X$:#a6 ܡ 뉻Q#J2#tϥGỉuk(4|mp_#_ y_S܃j%[#$e\辏UPh~ %l&^ E)1miDLjýJ%8=fzd&?`?aZy ikiwn-p>Z<0# T#|%KƖ[ !>`㇅H-L0Z@;e/BD)6^]=С@]RĦr8wOzXJ,pZ `@dj8~ N;KAaŧ|ʧ<)Ow[Bp=EA !l?H!Lf"W |7s0:(8ڐC fƓڛ_ãm`ɲ9bï+z_9!"X>qx+m=9я+ E JF4 j)vflVTMpX1O7C#*L I>\g'N7_yIޖ Wx;.Iz _xɣAAiiw}EAu= wvQCQzzv"Y {?*G>uTb opk1pH^QE1ɳ2.^ ¿'vG$ոuc7F`P1Qk3GHDMD%8^/Ȑ4u)qpۿ}а^-6ћy~HkfSUjO,0ȷKå6T^Jb0" ڠ ZѢo:;!?uTK^M0qwP`8s}sI/f'5CXs~^DH\ȯuFTHD6xz/͓9I#gX,F3E)XiXc;GoEcfEF K\G_}2d}r/Oq@P"StgeJ $6lˎ1khD6xpַSg~gjzBA^-BEJRFs&])iM  0J$@<}IrQCm S~zP%p_ ~mkR"3D w)ѥ̯ag ;@RDj+C fO+H u|XO: ad'tf&abpVPhg!B+__?|e/[J E|GO_|ӹ4a3 ДtV:=O™9ha0jMC[@1P9f~_E[7N-b}lp]#؉̊Trj(s5zf;Q5P;; 6%#0[ցLb@,nYe`aJ ~.I~AdK%8$4E܊.a>:O5FD&YUO? ga槗k}W^FA p̯u;Qvͯİ,D)YY:Q"RlO,AZ[HÅIy9)&HwQq0O WC~AA.3|xަ  #:W1y^(1'NxДf‘"f850+__έpՍsk늽>ښ\e4+0m̻huV͊ͤId6` CB/-0MB'_K>3>/x'A;}s$ȧ>++K億 ;~Gr!՛A3c:@䨮U9:0 |_o2j//*pC͸!'sp4a`!\LmDPK|vƦY1bʀmC#ODfS`y mW|ZaLA6/K/K% 7ΰr4 I5>96n1o@QD"rk;?wKWDSM6]ޭ%-GH `+GvMLTYUcM#DEc˯s `Ebz !qމp>R&b31ˣ+*dudeq, 3 ^:!/%~T ggg|+/򖷼︤(Z*\}tr}CMil6P4Bp"ݎ$fb}0ٱ EMSl5T]z 8LKtpJA0A\}7H@h9h`~ۥȨRs#m;4z{1F (?NKI!b! K"֏ VSAx;7]bjXS苾Z'5܁{RAFО~X?=Н`g F=MI}AcB̸ ̯xN8(J:Z38 4E|m8)|ÅߚZ"i)s_ :"hbJɯcڹ11"h4%<17`^ H+!Pw ̈́dk:vNu(7f]Z¹4#5OO]錄ޫA(,Ãys.3, G?s?w E?wtFPG"iB5A^\I2I&>!P+YW<8.ߚpDxWLtcF=_gjCJuzF9r'ɐ-},k;tY)};An$: +lDTop?t|jHe:x|_?rGYL DB//B\ w>s?/~%;y'M7 :d{Tس[®tLQ l% TS{F3ZK }g@nOsb3bO6Qmufk0J-(27WBB%TąqDgY=m(I$TTFls­E؋TZ: %Yz%O0n*~x׽uIPDcT?ubZtIRhOQ''_W|}# H?q1͛i:X.m 1hqbɗx8"!oFD+ `F E&pZIϟAF2ANm=E< B 7__O~E, ??@j"57X0Lxp0 ˕@ t,zCm8(}QH;N/"xN)D[~'5#Gp묠OO9$;:D^H톳JF>R){1Kq)'b,;-6AtB  c7 {.9f,=An*5lbpTUh@CF@ h<)󏤏 QI[`/:`W$!PLkn OםΐlG$.뛗рGe6 d y=v:O«(c}@h.b䛆S""7{[-02''\g~7|2@An׿/x .% \wFAqyN㳊:FwR Js@ڟz Bw#ocïW_{1X97W Ѐw{@: ~]-NpG+4ZW>'RIoI,ƐϢ:rR=;;kbWoEp9}}coM5P 7}k_W\o|bgs?:&lءYpb;rVF_m+!.~_k5.X| hX13n}Vh8;Ƙ ~ @) 9N%\AR M8CsBfbxefZyai_>]r24P,YYZ.A/Ri]244M~a-pCGw:B:8h Į`,x+}r/~ ^ PU(_G˯  D1~]H'XjX^a$1:7H&豒l<P_A?!~ΏS:UR\ gxp4OT~A2E363(ҢRe Vb0XԂFkMx'd|o։4#RP,-ry  \ ,"_v?㋣VLQ1X2e@F;`g ع 920*Vl[U"_R(j\Ge.C9 u;&u$FgLIX4dmϜ_Dzo'aujnn(̨ :b|BCetJBBh]nBNSA7OkvI* A5qkk {%w)RrCsz>t1`9 >"H0#o48~l#ȿ}[: 1ɤ_G'c^ʯ_{>q$F9}@9!gSXdpk#xI=)ɰ+ûGj)X݅87j ceԒV kx=y|ſ:\~|,O{*hC=в埲ė~^r2W;;wnł?_ ~H==xk^g>Is?s>6T:umǘzu6j"'E8 hפxO_P+B1+Wj~ڎCA+"O1%q.Ũσ P 5$+ezEj90nDGMGkxZg86#x-OK(7??ӗ7P,s}7}3 pmW~W.B2x7~臖dVRéP~  Y@@(W>(Ѯ{"Jv8pm_įJzH!{+鏆S.V5x_;N~MԓY22,(zi5J:@[)Yn $ zJ]TSf4i|tmN \c,}x\ۿە  \ , __׽qUE_|f FxKfGGߢMIOҞ Pԧ>unО~q۷}b{܉°@.#<6T?7)1e',Y৔Ho3k*O OC"(ޖ}I˅_mï(! :&:1\tޱ㝃B3vy"]aMg<"TyFEKR\l K>\#3K" U\ ˃oSUCڡ_Q{*hCJ]_ѫ_˛,W?Md` (a`ϕÖay1Dg+)ϙϙ#aKdA(mF* މ*x_N׎8I;Q5d^pevGlIpG2:76^̊wȇhUd_v>BPɜòRwn ! p.0FG~GP>I^X:/?>{{ SAn׾K2X$7 H&cO&5\繦KLGd?3Y>yIpUY8IשVG|.|g zį7;kO"_D.c!<a9.`t 0JI4r"Kn2+>R.s<%tL%c,co_ą÷DViR&wտWoAЗ/3K//v[A#+_[kwC*p~Q{Sb曵 ~jP |>G_S WnQnyg iG8Z@|~o_{1Pc&oA4Ȩ"y*p@%>k-' {l:RER* NpM̮lU(櫊ĠD4-#Ha˃y{ȋdebetBZ=A6c15Y U #~oYN+ sR*7DP?"F$2"& Н$&8g6 rރ֘p,8,]ʯ_i~Mdw0Fm0뙎@˦a 3a(>mshƍmtT5 ٝ8ђ|SWg;K'Uױ_ XP,XR!X//{߯Anur_, _(ڱ^t7 82L8e!B)cLe,aG/(^82aWhݧ=cZLAcs///o` w~GJ w ŏcSGqn#uwowGB"5!a% ew͗-áj'S)_+kz~̯/*)1%*"rc2̯7QS!)ɻ-z杯iwEɋZ $s#@R%dF_bx} 4.MZou \C RKx[[?g̭O.X2_{oo?~'ryOܚkOC*\=О>!a;h0bo~뻾kUI!##Q{?tOa\39sR#5:a45x;Ob-R]:⡇"<__,/˿hOC*\qhJ{zxֳ'ğX//OWfK/Ғ:P؃`J 0@3Ba%;Y3dNbtc?J>Ɂ(}2 1l[׳r\m`ܺb ɐPCtwlT&&U: ̄ EruTyCD5~PmU2R>~vjV%?wS/+A l,??C?h ^Fd?yK 4m8o;w\c۝=mq-’E,s/^/iKw?Ň4營ح~~60ca-t?P;z82pa 1į[ uWZdyri eg@%#!} T.Z ΜD22/ u|q\- tFO+۶P,#<ӖyJ/;֡$#; .rGR?+_vVUAH ?9p4$Ԇm!jHTxﳮ@̽0hVia~R/LN*uasJ(!( Nk֡ 3Akp(Y2tA!lffrh] m`r!Zu($8pBfuu+2LE^U;!wX7 ozӛ~Pj  |L-"` $%\]٧XBz@\sz_ه$a‡+m䞊\ɯrprD `pߞqn )!]<7A F-p9=Cua$ ,R`2~ r(e%5΀LHדUfX~7.UV;_cdZi-Ǟȋ'.V=/?A(,Ɛ7җ˾˾Kdy*eA>A?/??#hAqd8$=R(eBÁ+Ax1dS bz6a:1Ȓ P8sS`VKAv_\hZ"l^=Yzf_,iq=Qz0}AE %bRA:WUpwkYA ]-oy[w,ZA5PB;w+C ;o^ dL0dt לQDmu\ȯgk427K~ .@u^8Kp.?cAX,o~2$>.ZAx:p;4GiíPtF"N@ZDtU_R$JNu)Pu _gd];$!x)LZ8;;Kqfa0$XGS ah}zEAt+vĈԨuJօ14h8}(/F[n~p{} _?Q>S?~3xSU3 |ϖae};1s^`HvXma>O<mx>L 46v]k_S#fhX:@qO;~"0K~a}GcԅA"Oߎ ­cy0>KB01ІA4y, B}8gf]Ɇ.킼~] _: ~_hđ WLO;%p}hAIߩ5ķ?[AAA`=SnQHCa-wAcEڈ,}-G!`BR([_5h"xfDU_uLwï+o|?Ftv>op_ sj:vk9lQA #:uݜύyAP. q$}T1GԊwxLr˳4&J 5>;Wk)6T=xG_[{*hC?a IEV+ w'1ױ&]M^KWi]f䵔C4_u1ªD\¯&BLreߟy]mMADjPJPbO׼/N͘#ƄHGyA| 8°uj%h961%) ehh3“64+Ѳ ,sB>i6TО SAzQǹhqï_ K{8?7ܯSY"656^.5?;u_W|+@lKJjH>% A~rxR/Tlfd":d^e \J,GbL 5h6TmxNK=EE*j\]p mŠoZGl1 q7U bĨtUnr -eDcE};Dه=_k(~_;%&Rt*e(3P@YgWjVb%@o&PtDWWQ svwh +У%qK_LA u==MjOmpԧ>OT{*hC p?h~|0_A&0nA(ֆz "3v*+P؁|ީ!k;Vc+x2ץA4QСNbpV)x7_.MĈxJJkpZ @sr   pn9#Խ}>mwb}V`|ŽmcȱLا#T*eZfi_>p!Fp`~=2\Lmpv"XG?n2)_;/ri01JD88HN[% ΒpM! LDhTogtic5x¢KBR   ev$T0Ph^ʌ#r˯)Et ޛY]a{|9ԜU] 4$I%))2BeC9#Ya!}8R#$ -&2-:DA$H*3+r|w{}z/B!e}{{{-'C9h~=b` -ԉ5APFb(J{Z-`i %"*[>BQWX &S]w;q":8"5M&ݞACi"4q|h*( ,0۔7UNFd[ O!TFw-iW#=#oq1lX 2YL FG`t֭[9 \qbss3'!4 8A.Z?eL6M(_ct#DK:QY@)'1yf+~PKnfX*"+T.3XJ0"1B mp DK*r PWquCB|50,Ҿ憐!qHZߧ@6{ nȢLLLDs Ĝ1'bl D"H$D"1MhzW0yz!8& 7`mR_c!3e :5eR& 2;h!f75ί $q{@4&FKu+W17|HS iq$ a6~;A QE5 D"H$D"Hxs>s,ɠnE(}ܹ#nh^R䶸@L%*tX~ }-Cgh! 2*kPkrQPr2 ~]g :9aZ0>"*nƎZ.]k-];tֽy͘N{cUϟNtug[떠{uk3UսaU7cxkh[;^CwS<uk/ /uۭ;In(RA9ͯ"FyB0 zdb%J *BQ$"C{qC7D|Eerx {&5C׹xķC}KWҖ LVktZ}bv()(GşƋC@Q;k#[UQP[H$ǃz"H$f(5qz_= w7~g?dw54~Alf9}t%T v-%0mo[xФ>/MB:L 58קf =6Y2LJA;0 V.%HdZ!&ET7Ѹ!*1 tp?(+ 81T!Ra"3R bRa-c?cm=q"4 ~`7k=|+_j"|9Cs? PEs68z S-0ulk5dFPyLxGaɄ=xxDq=@C/Sex TM'R+0BөƳYJ -üIg[vҜx?MSz(DKVwP,BC@^*ɳ))s\A QD~ ;Gd5%&$Ҩ(Hǐs\D"H$D"1Zt 羒)4[\ڜnɯK@ $MİgJ (,ϓ%HR4 t4ģ,,x~)m!o;1с#H T A"P*_v_ZQCR - TXoDDa#ۏja q ֥I&D"H$Db[,,ѹPGi֨Pɂױ/d1,<(/1>}& "Z/VajD" RI&v S B+"}AB@@1Ϛ9T}qDoRSP&t}OQ7ވd[)QAHJ=2wП~IunL1//L$a\!H$D"H$-ԃM/dށ)~=4}ddDo;>|)ʜLK*` hH#0T(# YYQhA`DB͇|gGGx;3 ^tb~ M_cR`h ZҝlAŁX8lm0 P c`C]0 zQM1dWD"H$D"1š( g4з4 `!RoZvOLS ޝ0j+}Tpz#LudPDxB}gd$*C"V]|KS@D% X>&Yg6up*M[l6Zj45=(Ti:=+xoG/ Zh"Bw+fī@̬$AzUkh3t-Y"H$D"H̫0af'@0 (1GB$T2B6oP>k ʌ JQOFzV Tb[ 5ANAAǠ{dB#iJXT"H~o+ͤLkSrQ- 5h0iI). EW4(QnD9)*K(Hzk /:I;CK5$D"H$ļ ,Aɥ kB|:$P}S0Ł=rgf}lsq_gnP#LO/GHRDC ïB2Xv-{%D"ÏnP^i}R:ŒRRJ ^Y57tv-UX/_-%P|N.O|i1 Q? \?rև`Бs?SޞNkMv\DbFޕW3W Z6edvD|lʁA?rt0+,',9Kd|bWI)cJ+N . WhKĖhr6iip&9L"4 86$&rA+Ne]`:M߀_E#ࢮR9O8N[86"1ETJcpd!xцB."# &pr_ <!$U^r` $pPKB\JyA (͔ [-w(MI(oOe WqxEj!Q? 2$D"H$ļb„}@[L[UzA13H%~""Qkb *,ג"RT1Gxģb&$ @GC19|%2/(bM{7 M1h=DU\^ʪD"H$D"GB۷Nm޳wù,EK@rEOk"gCE 5㌧G~)1?0 z:3p8TD@󏨞HhNfY?Ln5\6b80N*Oa5Ĝ4&IFPi8 ͑] B QO=4ĘVZQ JJZ} {-p8ZP g MzppSkM&rMS~ozM8x卬NMP=|%2tIadr_M,|n[XG6p ߈ís ܰ;~ |rY&i5V+!X0YDN¤\J6K"VXhxw\ P\+<]/4p_OQ^ gʅ)jWMdhK ˫Ma"\1ŋݚ&5M&F%| zn3}{<ͯFQ 6k1CHLD8 =x ^v`U#*Dlj jSRI 1閏Aő'8]p=HzeEjHdOb5f֌hh̘%g ٤Bq^ֱ[ZU<}DhwVΙ XnL՚DD"H$D"1:C, ɋ/Xeg`(WN{9z%̗AǨ l D ȢjC7"='h{Xo]rƼw鱏æhE0 ki5xZ\<p`KhtL.>/s(O/zDZ2BG}h$E D"H$D"1hZķa߆c)yM> 6Ei},Kl _<[ "X{.BF2t ?›+TP`3`3y5O>,zv%uW~aŜ45Q"7YX݆x5)DY^y &CLEKZST$GL7i^4iH$D"H$ K!2ݲ$#*ί$H rq #iOy1pb|DũE"C)O:#qf˔ӃO/W B|{7Z`jZyBƫ'&ѵo]`hRf+KMC5'k5-*0֌D"H$D"H'zjB)i(cȋtG ](R!8@4}q3M F qSJ0 T!/8B_h☊´%z(7pFmCɃ+ qNі/M !]+}3'1GS ǯ. lѕZ1m9rv b`a`ސ:eTh)G_/19QJ0YYIGsM\Di"4qFPJti^5Ѯyq~-GkC0#.y !P 1epgI}C;aZ>xd^FpG/u+́b_*Cj-"_a˳R >*U;`zf)E \;, SDfsf%DEے+!Ѿy!Q>aV’D"H$D"1Jhc,^~tG]g4-TR{JwB: {d/@aL! sq:-σ4a)Cg ";ة?:Tl"E}D '$^CoMB8nhLsjB0{OXuE4@aD"H$D"H̫m?.؞ N!gŭE-ͯE N9*!1_j _ڇ#n#>:;Ju~C 0:Xѡ9W_^`l 5}k7s&<> mE\(2Lo*_jKAMỴ 4kʐbTz$bJA(] YH&q bwl3D"H$D"1?`>vv 3"ߓ_;}׽F1NίʼnNq0!R{]nNac Ye}b/(1žfAvg2ܸvb]Ih(UBY+J̄}8G?ѵbI;nt`aUQ"nspGCi"4ql8|ME&rAwڗÕOkwa03_[8.&_2 >Dg``~<peq@ZEC]MIT^mlST^(JžRJPi4ΰwXJH1Qw8;XZZZYY_\Di"4 8xY,1V<2̃-TFxbQ >E(|e[ҡ bl0CP41* Pc--nڣ<=|n ;Flo5;i6`c !o; HWk@? RDK/9oPmpũh&D"H$| T LU . Ab"Yvشh_+u~mm aYuw($zd^vSèo@MerzH(I؃.kbٍ{!(HMUv o ~ A2au-.hZn\t aPPPǯ!1j[gk.sv5"fӀѧo/|g:`.5S3/A^x'_~}e|p̳=ZO?WReMwhcxw gԭGo]<8\Yjs`{`o߿|qk4D *ؖN3\( =eg\ U !&u# &wфQD;Id qKp`_9b\iK|h4Pό)G H&j #8!9RznBoyQb!h1 fCI`"6!IBb"DH8B9?koThť+7Fknt_ }!R,P9!_* DU}΋0LL(v^/Ļ>@&/J[)RvÇgTӥSDB / p<>]ھ8qA1֝ӆUАHaV Ws=hgv>^ګZM+aGttU__A?8V b^nّnMqH"oYa@䦅aպ^PxFs5!JȄC3<1c|W֖nR0f"6:^K)p@+XT0|bPɃq3D 39|JMDG=8T&0D#v^s"Gr`҅Q\= 2:%b,~zNBdEVN©FouV׶67 O#[wwuOذ\={?zGw0(sN\H"oę{==ރyiت _kPxCi*~M5&BĚ_T皲"V (;;&V@GZ0q=;$|pg9PR #6 xj:KDc L֩UDb^˯_Ͼʹ}x\U>qi<AV۞\;_yk{}"D"qjPe3"HMq'NGkz= !A>jн 4&O`6wÕVeS ʎEAN_ 6M ˙Qw<={>MQ1FSDJDz$1~s8>%,T!8q}o}syy(3߹@޹g+c_ܸ0w"D"q (p~ͦ90~-ί~ΒnK8ͯ+~V49CADs>i-V1&gP82roN=٢Uz`y31G cWpM =0 bxv N+ q&~1粞U|tso~ŗ|inZ׮/\_&=Kxos/> 6sMmE|&z &۲}Wj~̸^rMD~-Gkt(y:DBB]0;>`2$B2lUE9luGL"k961qwUI DP]F<,*HapBB6 N /FsȒ3Ю^}G'?Js/l6|nmSO§o/&=cl|W\t4Ɋ$&M1@@kr$Y1.['YDA6Lk55-X2CϯU"3)ٹT}#VȀ _KAL/Ɉ,gd8[{A qi`v S$T"4,UψM2/ #<=lB7"^ +"<)G7oϼ[kݾ=8xݎ/wu4+H$sh]zghgQ"Ѱz(Py=TUf4fUtW ئh D5 crDU$}()Tv3i) hR Y#BU&E 8 >~s!lB@=K!T$0 u"86w_0>kZ{vv?y{Qq$@.Kxytw/mH"H#~EŏtУ+#@34k(\`_3>x-e.S7fOĨ 8:cIra ،NDFYzlL X]me`BE$kZ>~JH6n@ ī&pޟTgVd\D"q/?Ŏr'Ҷ7c<98Cӯ=\s%I$9U8xc)ThsȯMqAV )M ߐ7rGmf(Tp1 BV̨͈KEǁX" vE 2ne>:abדXӇG>g"Uyi SL^ ̞(AJA ._V4$oWO;WX6|a.${jsk1 ϙƏ~;߳GKH"H6}lUPx`S['a5|8&U&-QFvUT@BP3\"[H$=Ո_%VmJrkAʣp n8)`UvG(D pA&|t%VKĩ[毼3Q'lñu=q[vs.rEDb~cp=G?@a녈A*|OH pӝE`(3vm爛X OWAT"TO!"==Q-0$ 52\h0O'H&fܟӝ0|2WkmW(Y9 (@ Vp|$DhE9A3ߠ0Zi_VEР,dx&7xQ W6 ęg߾SN~`vX|ARhx0=$$rED5ߐ5`TDj{krBt|+ zDX3R)5?5~=RF }Zy]:[ w 3}$ -=ɵׄ0 Dc27͐VT/pOG?"#Ŧ"dMH"Vb-}E r GdX},qV&z(ѕ /_!O'^Onܺ| \Wݚڷ[D"ߤ!F>g<q8u £ ,_C{7`APސ uȓ пB@`HU00V}#T*F A/$\Cstp  ƫ!٦; JQSu0URb4Ȍ* 0~]VAڛ7?qk=}~#Ͼ ̵M;7iKk:o+H4qp/~MFZ[fQ 1x- z8mx# e-~Gub-_ ?:GD$ PX{R?GJˀ+_#Zv"dXr$Pz"wHUa ϵTpOd@a1P핱%鱳IC"q}ᑽS@[7{!Ͻ.d~H"H$yF~g_ $k秵?+y_{sDpf) &n"pHxdQ~cX9 Ck"'LyF&j燎P ,\M3ό+2$&P"&;VO!8ӯwε"asϢ?zf'zH"H  F?-5Ah*(-kJ#aH'֘?$zE9a1r_h !( 2g-g%oT(A Lf<?Bᗮ )G8CPB;D])\ `.2Z~%HM|s wWNV|>$8ȍW﵅ܭi49]s"DIg h|qLH T uQ*(WZok&ʁ#FL < A8mLQ!0܀[X y}S'C-#pja  LPb  1=C p~!ᤰu.d *#MA… 4g^{~ؘs>G_]^~l/|soSܫ_&tV$7i{?+~ *>rͯi`^@۾.E mKma3_T H-@If`,2`z2"z$P.ҟu!*a$Vѕa_Բ"% ,y"' `` ##1[O"@<AdXBH$xa믐X.v:cky]u`.) _r;鏾y%.YȿYs>?vh-쏿깕E9+ڹo\D"/`a['?0Š!˯T`R-`ܹQ3)~2ee|Nl|n.A 0FuvNI6IG̸}#TZ#l.$_Vi;2d̮RSDR#Va0%|;`ts)쟠s9DhkqGn,-JĞ?}w?t7>pwh7- <;fe ,^[7nZMW·֝޽syy'ףoZZ{gqyߺ|I$S }`o\Pj>5-n!OD>kvr$q.b2I:J ev*p5t8FN[*- O 5Py6..n\D"8y/7)_Cnk`t8z*ĬC.Ay  ,ځVSׂ7 {P=&؏䁙N$<)z ?|ɼ'X1I|L4?Ex'yld>SO0[jx́?F BBOR:s9L$N=w '~>z$ K~nͭYM˻ K/_8w0E%8_nzee}ѧ?_{]kMl>w'66/aH"HO^cہ_X&p$zK0N㩁{rdxWyAe%X~f_&~M]飵ZDI(fn+..)P5~\:n$hNfޛ+Q^ $L`BZ0WWߡ)*@H{?WGq>2k7g+K-W I77εc;w_=՝'7n]?ߙ"D"qG,p/~-Ɨ:О/ 8͊_mC*IX>!HBV1)k'5"JH(2 _Ǔu}H/eh5 Am]g$+MN7F*|0hAH9YΐHu_SnFy'\9&]] s;/ԊÃ#{{ZLsxߛ]ウBz$ı+ @nT0]4:f u8' edY8=6b,4ј񍚥i[(!$3:zsG,!aW[0 <+#UWOR,2x jt#QL" H$ {}ͥc{yxL&T\`+&{Ow8w=?dGq6{f{>Wt{ki^'>7<^޵*ՙ5|vmCIQoo\?}]ᱽs$ۊ$&MM!2SůaB'vDmMm8_xܨѾU]D|\̄uvf\. (Ra۱("`?(* R-vRLOH'lVa5$6D,#L'x+ ,nJ!8tOk]?nh!o^wxΈl3n,| ۵7o_[_+S}w;,ukk[Ӄ9I$EI`ayP.__ѕϑ94Y47Cp%: a_7{!`U{3iWCRhO%vrшpIDGڱR 5a!UTՄDd8:'.gӓ\D"8(Gf@^B8_0b˴$K,EMK @f!0ywզ)4#& K5*^=+‡/m3OuF_'񛁄;4P"A` vCsee]xBSXDh!8 x(L^xKĘM<׮\-+닣o_^k|W}?|XZng۬ۦlw{iRH"H;#Ӂ9#Wڷf8X4Ӫ` u{š,)k&(#1, C.) =IJӭ`cyv^- fO-S+Ij?@ͼTJ}A"!hmZ9 NO,%#-+*H^<[9w/ٮ{w۟4DhC:Pi?E 'WBdwIrsEDEo0+/m&쿂)lV 32|m/k:%n]^O @0,dJ# ;-$1.s4 X -5PR0M?zBE~.AuB !Y a6\G NqW籭3yhxjs,T.hX嫳xJ 'أo,Q+3W$H$Yj_xOU4 UA;VЋ3CDPNgkC܏/O~Ay`r~+kBU!<+2+DXcǞ qױǎ$*OH_#ᔞv)AÂ]Nw O䰻t x3*{>Ψ{}۰7Ǘ.Yyũd$0s"DIg l_+cf$e NDp}+~ƑQA {A? "nԑ&WamzŒ7@ , 0$b:YN3(ƍ.P$E-ňbm b>"UI >bSm12"k!AWO !)Hqᑽa\ߟŏNG*RĂamAR]x[^[[B\D"8^hcE1R5KI`# AU|Eg _b1ůl=2WY$_"u6D(Ph᜽?FJNETys*"lO.Pw1MF. H "D8\KfAvF5'U /^X߹qw935way:߼|ici4 ?u=;}G[-rEDxQ͎ IF RC~MץAjg[(L OD2XšP\M`FJ>xUDBeYQ/Ȯ%H%j4ÞA:PB,Lu^X@4p H9 ōvƅED?qi< u-\|uuFtxXSPI$P_UsՈ _! Q]_w3Y7ůދ_7B.@203BYoDcTO]k5 uMb˫)Au~Q;iͯcMd^OiV0aU['%@&ԶfTmF`C٩4Il= cmN 5R+HM=" D5G$@僔D"qBl/o'́|t֌,⿼z-"}]j(kk+Ypۆg*L> \D"8VƯ*F,Tw=ld2k7i]F'5?)~M >ޣ$?N[Zy:W<~H. {[Lmh&RT& 8~PK! ]X]@`1U~>ZfvVĠa/&&!+8 b{aaۣAI$cr׊_oxJ? pů|[xalȯvAY_7G{V D*CI d`ޏZYfDU&q 0Z? OQz/p sGxvLn\)lJ~ % /`Y'Gv%Nm+pṲCݻwo߾f)Ẓ'/13'3KWWg$4\{jskT|185I$M8c"R!$(~rM/AZ*dzI*7PlcGQP [uv&I$p~wdjJ( 85W;b} z<~G>!-Ҍ!ǻGKJJԷ`8kLDqGu|%eMNS;'(OT[|eyou닣o_?/\?V&'I7!Wn0"&M1HdOBtC#C. | `0v(x:O[NC'tM~\l(ب8[edO T1nґ]'BYTm.S;~(`>H1 4a䦛\ (v$=0u0!ԌXVJC^]m!>ndtwR|?qw;ۣٴRy/[yx6R3opR8sED8Q[2Rb466=J|>^eP&5 5XW:OԨH}xLj0pU`E"Q / _LɱNZ Ȱ`yA?zW> 1FB39FIJ&aDfz/Lrb!dXˈ "p+qv#auo͂37זdz_~A_DT,b0ظtdDIgьeҳrMmE|&ةƸ[N jyvx! 5rHćk9_z -$D@fPK 6Þ)l-f z&POp5ZS(𾡽2OTϦĉ3j7$S3K.]rit[o^lg N$˛|yuug66 g7QԐoٽ.`օpBɑI$M8S`A y%ːiu 0DZM_Cʯmz {F3BuE?B(L" /"2 F τ_>8BpOpr+.`1.ZΏ& HDF֛n؉ D[_eci=ۼTP=a1=?|q}qqF+=q;FS173W$H$Vޡ5~Muw_ir8!Tkk;lܑAC6J$Z"j__4TO:"Al TAuZDPeaLU(01r3L(T،`\;2KE=~[kz)q0s&OnZϜpneDϟ^__9U9×'MoIʵLGom]Sa>q\V3WVV%W$H$xc⁊F ί #G`S^$2$ůב)P !!Q}#3`=@;o/RӇd"">#N \QB5)xyh^ SACh BǬ ]`ŧnm.ͬ N~͵vvBwULlVU:!SutIOQovf8o8Ld YY9xDŽdzJ8($D P7fA ONo g 7L!3&kAA BQK*m̝H$NK]]wBZ7fZ`6ov]$On}e1_~ݻ__m:GI$cǞ2Ӏ2չ놴2{k(`P_ k9_Ba{KaȃvU--QO\eMFXY8@'D<)^pg('r;CV`(1D=Di.UB$3k۸4ϝ;8s|ruuݗff0QX8|z֟ظu`<έ̨&W$W$H$Bj TU8j{\BƯcjs#uPҢ]߬(v0?M})"7HEbՀc*3J Kt*+gdԓ@{Hs闠kG&cXx üD0_GR^aıbE{M ظҹ+މWWl7zm}X!Dzȟ}GwvUʹs]*jI$bx0ʯ1hqf ïA ( ۄP;{ N!PUCxG?" r^ POz! 38,(<DivdCD5U T 6UEE\WO`G rZc+h/^(R3JhawX(CP~YѐH;~wgXd.?8wnpW\κBnEr|ݝ޹3잘-˯>yN@Cr~?I$++FjX[hPx DH#~Q0j _+AB ODN7ñOf \^šDU(oӳՆ@LmO(mvt@FWPI$֟Пs+i5ϕeW>z@Ͽ@+]!ǭdWZNœW^x'_z\{L{':q`|e;߹tE ߼t7^~^~sc^^YY8Pcc#bV$7iI Q[|e:{Eadž +'r>Nȯ)|H5 m`h2U#23fM%p`@ɀ]#u Ht/ʇbBO(9prԨPUGy- fTUAFA"2 >dN8jWB.QՀrTUS̐H+ /̋?.k+'U ~t?|X9~P+of5?k_|i^_ZkfH"H| PqgJ3P~Mk BEưjFL Uq?H֢}P~J,{2W=!t2_ 'tb[DNigaTCazo=N)Q)"8ʾ*"uo*a=7+1j=XQ{< DDms/ Eѫ;)$Tř!ѥk;W_Dkb_|^|a>.uʭ pI$)$I. ]G %נH͘hӣp- P2bT x:82a060P(=&{mTc)P!G0Aba*(Ϻp*/kG0Py̽BgH%8 m^M$fغW}7c!GL]{{?xkk}WVwFF'73nw-Q >x<'76W-vucq1E\D"8np87Y_pcފ_4-Ubu=0~=B# c>f;IA+MeqA@Vp|@402 b=mhgT lAo;s3t3LnnvYñ *TOja(PPsvPзF39fD"1K\{/{1vgo-L;WK^M6ovB%[t8?+o Jm#,V. 2Ny>9uoh6X¦1gL'\NRB¢ L֬\{05}0pmG޸ocn@1\9ooEY+=kﻳ=#gnֵ.4{ͧ6ĖOV;W7Gr޲g~MOˊ$4qF;D](^[&(&?{odWz]}2$P(b"4ئDI_Ѓ=8 ~C:ᇎ,y Vj[*H -U@&Đ>yϷ^ܛDn"3%Tgݛk}{5 rք[ #0#7`~O~ >MH&,L dA@q&/d}>X$FEI7%-)(SY"2:,E16(iTd܋.4 $xCB4sfY(>1֝o=ֽ{~tN1=slҾrȾ駇{$4|ieg?xoϐXk^U+R+R( 6jX B蘠]oatLd B9z n0ז+.uB[ބY D sҷrE.B779FU,Y[P9G9QylPH<їi"*(H*>"͖3i9o-9&F=,@ u2J_-c?ѽMM&+yVw/ lk{;{ҋϪA7WٯwVw*K=Z^s[3\nZL.]ؿ&o{0wl*~E7w'Z+R( ISG5p0ZGkPؒ,l 9V(-©p+,+)NawJ]!N0Bԁ5x~,JIzx.awk 9B 09m 4 9$#1NÖNMpn6 tjiaUZqiƳ|gDkpoLo]ʣ-|#4wӇg}) YٗԊ )tC0m0HiE%G(QF=XlHZq @6UPvԝ{,r @ _DN# <28!/#R0ncECD-B,[@x;q]e%Q {Ji/Ad`Ae/B,.RrQ>ZcՅ\vOݾsю©+'T) (ˎJe6B,qR@Gem^oHش,* @8DU8AteTejIh(90#q!Jf&ء,e|(i3i,Sd~П='e05o*5hh30fƏ F0* S 3}76vgӽxօɢcۋ)q;};I6|ׯ\T,kE BYCP`?}YߜSCt'oBb̍i1r.f@AQR i^op9peK𝌘&Dz5xhNjqWD9 NLTbâ2tdQD >~&BA\, ,p6mGѱ0 @W:Z(r3슊].7M3wj]XQûJh8Mڧ^`B) g.2@.o{’@ l`5Db'mU֎o @:W(\Y`6 ^0@P$hAZJ)fR# E$3D%CAJĠ)r)lz[WFh4)J4U@~g[b4j+4^B|^\yVa=߼we g%SWꥊ6) 3 2 F ^rT?#`@wL49L%GVp9%&r\9!# q< ~b<"A`B 4 \.!̹#Cw(!i&"4)RG+88 %@QXi#X##w ox=z~>앗3+X`4/Nh9h s09&=˗~kϝ#jMOڊ &-1 -O1:QA|2tSM:TPy*Ic萶(9JLB#6[s%pt hr y#gChH/q5Yd-b1JPVz{"h ف sS&" 2Mx$d30 י(,=5!z}N_}gc1 ϯ,nܹ®.{b~IO>UOWHJzӯiq"BI g  h/`ز&쿩W= A=ܹZבLJ_8 KrJ}H `5TFYP:H0+u(Ub8Ŏ aMʩlZA jG(MYT][hƯ3qXB Sh<~7wƣ&D~}x÷'N:~՗`mjE Ba4PdcGGًѶ nB0~mc~=roPjW&l)>M(.t%SP %+EۨK$OYY%GYH$!#%D_itt{^ `0Pء.IpYE(}" 8)!Z g^o~~y}ol/Zhx[3z|uٟOӯx|׊ IϿ&O ~Mi A%4!p{PFQLZ3&S6}ت_=Hnʠ@t5@ AVFgXl#KP8aXRtTnYP@LÜˣzrϊT f򭢁C%$̭ٙ}1JJD^# +B7^y?{:gn/n?Z.bK6./띛[+Cg5H} נ8mHP(,_BNK#^ldT` ]0n{;iFb4$5a^s!`󟤖8#;j8G}K :m3h] o %#fr܌04o(0Z~t)j˗^Go}Z3 Xt=XT@gݻ eW7?Õ'I[Bޤ qPS`F5ja>NO9;rtPh$>f@=dh)SA(]^osApF鬧ѝ0 8PLsIˡi0bvR 'a GN4G  о+ Yhx_ZIO޻߼]>z_HPoV秳)^d<~… AOn31ZQiaQ0l`ǠlTIQ Nlw@ E6`6Bal*m~*I@z>G(Fw QOAzJ3Q, aȡlT!QYB˻P8÷? =~~sdAl//VpvyܹI&?Y9u$;[o奋)N[+R( 'ט$wBw+# Za&f ցo`<*q~ᕊGv`ѳaƞJ$FE>* D n?LT6a2;EX.0{˦;Q #je[9(2)Iote]SZ Ǻ gd^JA%-˚#Lf> )ׯ?͓2~sse Dn,ݟq~N_}(N[+R( '@@-B!끭M(ZPZ3T5Z%C6SJpoCF$Z>+g72 &2I>ܩ k'Oɒb"sRR> &=1>W rAUasBwMtcn//(Rp}ngK/[ZU) pt/t(RIy̯ Uk g/߄20]1^f@vΖG  e_5LDL( K5&Oښ w<rKEBD槊 Q3N(ACH J/$nZzCN_SMZGo ӂ7/gv}sseoB.\؛y P?xG; *Ӹ>|e k~oVHHP(x1n\L!~M &‰tVN;%[;UïX,&N; 56$њ0Q/`zI`<I$OD d`AQ^V1*;95TqFq0|кiP!OQ % xxhA2w`Y=…K+ç?/^z>pkg,l?3}^VBcܹ_ySKFEhkE BTT)֌0f/wY! T0_75f"?_Mt/ D}Ɂ,"9^#,Ol9x+cbH7p"&(¢ģ7%PaTx`0?jtgIA .j0}{I"/sX4w3(F%Y% ‰Ǝ?۟ɉܺHȳ/޾h̪' {*~) kTQ0U4 i'@9Ln 8g,՜w54fa`:ߪB\CAhHrG rKBjtPX` @A^;h!ӯ "%ˮmdV20Ro|<82?֠A<)U|%Akv$]A<36DSM/TP}P +5Bb_W]:K(YdR1wH Jm>4-LI0bl/-WK|Kw5;^y$c͛+%4,^}?|iqwoRN̊ &-5Hq~!Rqu@$C2Zbo]=ڀo55jN_\6xANqÏO,:HJ@, $' Y~`솀<JH WpT/P.@SeX{BDwH . 4qb/W2NP̡~jե߸v+]yV4~l}k>_ _W׮_ŋز{VP7i `RA5T&=E<_KK=A[d3}lQTx=QB|别,< P-ǽ$aPR'&h|ŘNJi7xQ2b)XT\@)mH@\"Od^ AID÷&>+⍋D^0x6MQPx k?^_;=2>_ Rss.pzg߹}o}3O) Ghx)J5<1LZ>AK'LTţ"*J4#ڈ_G.J )B+(wԀdq,%(gfIrT èsbF1bٓj1fL 0Su2p4ǼyCS CY~fed &څBp^o_+kH_z;ë;E? ?u|'}7 +^[TlVP(Ζ`n{61kL( B~-[K1'%_6;9u&er4D'r B/#" (<2X55%==.ohypX FGAfR3#B5DUD ?~vHehƝLZߢrAH n Mn( FN/77?/Y^9olU9'}^uOtFÍO1עGb`YHe@JƦ C,y(A7ѬH6J -L ^Pa)”UIF NQ BW`͈WE5$4~ &-'-o f1$m(%H4 n;֍O+Kv~߾ze tp/vyR+R( <*2l ^ |=k'Þr8DFRrh'5zv|{>s5$߈ Ṛ ՐH( 3硬PQx !Z%pnH0AH$D}K)@%HҬ*N]Ax:$eZ߲( Ou| O _RkBP(Bٔ ,E. f`D 47c4O˯$0 <_ju nQ4ɀIdn hscG`P(l08c)a|)+a:1xl=(*I,Pb2}t3OY&v}f “g7^/i+7. BCD. B0bkFw@6}ԍQ$8wZ_a{ݴݡ1ȉ#~E+ -xe1*2 iG'RC4$! _O;W(A4BL|hB0r34(RМ$+vJjr) #xwBP( (:U6hcL, *&-u!Ie~Gז5 ̯e_ h*br0$Y?z R-6 6x7&0d3pG U> lu EXR(dM8f J/|Ӕ '7K^ԳJv$a1jP(~wPX_<~-OƯEPKŃ f&/}!|וpPj'RYca`hm4<3$<#H3"Dp5 ?qk}ؒb,dah4~T_H4"XBd %4\#~mk{,v^ PZP0FG 7\AuB85 Wz6MtdD;lMP#|d@/OD@К31/hϠTylXk&g$ 1E4 ơ(S݊5]x{U."|QoBPoBa#~f~m\0q@luגl1`Fظy=eotDX2p:;rm`s0OD0fkpIFq3lxR!Nr4Ho&x7tBP( |г /SPr"DD \ 8Ayp@G=B"e5D]qv: hROP ĀZL[hr FE I@B Cip֔bL%#Lg$ $ Rh B#{ۯ?xT?47o^,BP( ISo$E2ɂE=ZGzZuK{/LlHxG>$LDTV1^- Je$ "rGLy=4ޚE ("BjQF3zdzxMāb#ápQD$$BP(U wdP( Banc$>}M@:{Q4pT~=͒D˘^׽!Yw52 ?G96&ߘ7 :ZQMDr}: \i|a^@T¨Cg߂G+#dye!KIJ6EdDڌ'tBPx,غ0)aB\YBP(X_ϥj͂@Z =zG1GZ?_GBPSGYvб/AOR*r(H&) DSQ6'9ƢCd7V0zRwd!H@v5Ϥn!Q/K!> B@KD`ccի]TԚ>];,z,FJh8eX[[ߤ5BI E\M_vq 5n/̯5ʯm_ +hkr o5E^axp.TJ`Aȃ kD`Ѱid`/;jՁFGL pdgP7 /Wұuh|Pը{$)jjM>ykecx7-KuOԛP(ԛPY~mZ$,YBŧKk; Y~ZbQy4`ʠ k R9D %щa:HPqԍ('ךNO (\~F[S^BP(B:y OSm Ջ/!kc~mc~ +#CjS$'K9KF Jh] ٓT !s{BQ 5B1C#{1`S6z@mfu9 5$5\QLaC-lC W(XS6]Q( Kl,yY(kh;2UC 5[lp4_?%~-#~tٳQC{pAO~:z@{+#lnD!ϨE& ` K>5tkꋏG)(*(6MZ :V5 Bxa2ͭEG!<je%DÛtmovon}s}m| BPxA@EM[]_ $sM ?ϯ_"FT 4F?ïۏ6-$R4l+@m 4uD'4HR ׂ8E@9"9&@|Oe~8ڝ["5o7p^=˗^IƗ'Я>/./uh=.\ /mPn܃>|x=||؋,%m?Ú2vww$ի]cί\_>uu>!}_d ^[?|C ^xMh+XJͭnB_3@9JP%aE؟?y m hՐ7#¯"BD&XGU5<i#&rI,l30+lj| ` Jq-$F{#wS:' U"u9gpf.Ta}͘X},L[^YP8=z{lD;/s;x( B9Gר(W|?F˃Fd.nN{~ǯǕ w]"0XCOt-ᎄD 4eS+Xby+%q<&4@Epqu:45D3ҫ7ZĠDBEHOɗU614h^Q&>~}.J~W~r)x~cӽ|ăyc~/`hB16k|ٝ3!=XsR/{Wnlʅ۽qa}{: v<3?u΋;;[b{#cE_燯:jO>ODo2y+3S;-Wo/0+ҿO/zG{;d{?g͉D\LR(!msBdQ6qzOIOP$-P#4ܯaP㟘D6Huj/0 šP(fq}8&@[[+ w/09?\YypP(<o~i+]נWp8]zT>6=eI:o{?45 r826RLb*'aڲF=0q̛Dzq'0`PO!$4G&TCDߵ& h ̵*0O T XBV L5 5d`".$ɠRZebpзTҮ5xsg,/oWwӵ(^7nEW|+%4ԛppqpGO}ޤ]"l1u#փ@^ClߛpAGD,7u "ɯE"[ሽ<3p}BEDh*8uȊZp .\S8)"K,ņhgpFpD0[Ÿ%,{6Fr)UC)0OɒQCJW={[7^D]ђZOw6.,a{i黫w'z,o~%)?M/^| \P7i aшe ̆ZCP} Ԛ,ۉq.y惇kCW#tIɋJqqvқF%+)MIR=| L] ѩrgBP1?,UI.B¥uqЇbTR@c6xb# ㄏ0zP_H*  M/FX?Gߚ_qBYB B!([5`acx* 6 "H}[(fcwpgi?"qectlwWw?wVJh( B9ML!;@~A$&'9<)F<(X tδV /B]⎏Gh9dǀِRco?Gu0G-@|ʈ*R4ňRUAdrP Yh5&U~gd\t4E4?XpͲXP(fOn^ΰ<:>Kgy޲TDP( #SM8@?@si?^x= BP(N"o1vڲCta"Q_ƖQ),+4JIY0JpBuH2i/9t+(#$gr.;1Ayâ~u RCݐ,<:YB?2ﶈ (s4ո`)<~[EYvP~9 +c&>D 9BPp|;@OoĀp/\Ӆ?;7n5ݧ BPx@͈uzW1Jn ~aD{@oޠ a5~ozsgDBѢ6#$ ף0xAJvȞ` E"G/ڪ ԷbNZgA+;<F,*B~c+=G?q޹R BPxfO6'b؈Z;Vwx ZDA:C'AAVE_O['$#<5Ӗyl{ȸJA&C P{DRBDGa6F! h yG'" xrDf ,)Ν:쳉K8P(DV~1++r-cc鞸u ! BP(Ng<B׾tήJ DbnРί5KFn9@\1_uۀd1,4fċA F? LK[Z2L%p|%b ebU`xMDfx!D;LsPrÍ%l((ː{&S<Ԛ~lc+;i_?AͭK=QoBPo4BּnglUC(_LZא"T""*hIE?2fx˗wOWč͕ڑ+ BN`k8U2#> <@[Oί陔soNQ3H$CAxBj'c 3" ҤB٩ K3ɽTKBgpUC(}CDףA2ȖPj|妚YYšaBP[/O&-/CuOoj]-=Q( s3#~h9qį-`q"DG2]v| o T WOq7",iDZ |k0W { g4 Z=l]81|B;"3<*̌?[>BE7c-hIƖ'GqoW6vh{^ BP(<Q@o(*_e)фy*"%n4R8cg_S\ArZ(F92k2Zk@r$es' BP88 Pph ~0(h|F|"馱!6bmZAB;}kM={l1p;HvB@T5k}W7B/h"EtEQ̎MSsp$0na-t*sH+6oW(O?߽uar,}ϮVo//OW77G* BlsCn02|fPԠW{T;EeL@6p.b*aHGT7p.΂K &8] .PKV wwpU pь@39Bd9))!utX^RT8ZAZcQ:V[Ù 󈟼sڣc7tKgu&{ͫ΍[+6T? BP8@!&mmƵa _Kp `+a#~-evJ \d~=;y<{hޫ犂T4J#KAX ,-1 rn%JDkCO7(|7h؀>jM7oÃl/-}wmu;?t-{G~s2BPoLDMnTkĘś (L~y; (QH)ijk3Dx&?AQr'AV4 4{J(4Li O'Z@ѯ*.d5!3v bgtXn$8i$6 -}37)jjMf?wcsXڃ]k'WonWDqBPoY Ok68 (Fimd@0_k%sA;C >&|@N(ZPC5@7Ë 49hxC_HPB v BBMcK%X< Gh '(Da)ZgƲtKI*{>wwS$8yv}w}uX{&n* w_( Wkh!M;/xמ6}8P&~Jʯ1tMZBCrp]An0E O/B\+22K,4acICɃoq?5 LprFۉE:x5mrK(c$Jخ\1>%dKP8鸳嚇x߯}?Tx"[Z~jjE Ba.,U4X7e؈=wR;dIR~ ڵ-hGx:]<d u##RM[E8&F^h}ҮQ,&;,em#4z^Fvy'qF% ߌ/e]g1"ԏ3~xAxu'8b24^FQ( BP( 'QK߹vT$rN )ٜ K_GYRHVޱ4 Φ)x?qKUTqƕ^"@r(COiv2Oy:+|XqxY?2jQ*y5-ԂjM Z@Oa&PX@2/*R!\~|[p!(! Wru5c_G/_oe2Ai`^Saod\)āHÉV6Sȉ遅^=ml_ "ȗ?hN5_r;ִP Z8&k\SQkZ-d捓$Eu#MD0¯m#khÞ|)>Zw[h Ð v !AڽmA*no1$^3/r7wD >Nׂf ?`4[3J(F(A_դ&?i~,?/*cY BP( B O51C#2n1h/BkyADwK3$b ̥ux ilmHW{sP( BP(Nڨ܈Qs"EAAfR0]4b#Rk>"W (IO%N'p6t" 3rF;F \Z} '(~$+̙A2t=_ rExDDF\ޛS BP( Bp"gN-sZfC 90c~-G:#?Ch=1D;i-`~ >(}Qb=y#4&AULEo`p@K) hPd,z\<GƤ`B@W4Pxy)ES#" T,IBP( BP8Q&~ ¯DR ~ ME6Vȁk9z53~A87W>tyxJ20ȽhvC?xLي9-;TsaY&ٓѣ^;$ԐĘB%4W4ՕЈEeIh0iqoZTDP( BP(X4I%kai. Na[ŀw=Malf? JAn#UX?j)6 .FvuL]yeG #Eµ{H!NCDŬ#']J 0ueoQED|Z LC\>Ag@BN BP( U#$g_R$1Z@fC%hQ#oAT&  T #Gk'l fPP5u <¦T1L;z.ƒ$ԛ0ԽcA-Mv|Q55FkoY Q$#qG\r~?)>Q( BP( |6r͒`\ 1W_[qC&Y=!J =bK Y ' PA JvD(n:4ab<C+ $$BĪi ED`ɒ P.({)'.Ih.)q?x΄V%Y( BP( '2iTЮ U"2L^~ͯ[f~_[k!~<']zDOzZg3Xt:IPhfp"Ld0GK^Ravԣ|$F#H|&)&^м.ܣB t⡧枢ǭ['IMEipnhr2( كk$4{"pD,D> dhcUZ~P(1B,@(BpkLӌ<:[Ăpk?R 5CP0zMO\5 BP( BpB=(`3-2?ur$vSkGJr}&~ӜqR'dTH24w*6P ;wXKDje&x"L.n1+LD(.XN#B \X(գ_ >pAM<|71MIP( BP(NrH"hP"dlhå/!Al_[f|Y-%+o c.b&͕'4 [&|ސ }6 >)fɔxYA)\>/RJk.Qaxf߲)ȈA83W1_,"٪cQp&5Z±ŋv]WSQkZ-:FSA5E|f"פ*OCu~낹G0r)qUC'*"g.4 :g?x2)7jP9 MتL+\:ky$%+j.HLX8y( ԉ3 .MWiiPkZ5-ԂlT MQ2L\R˯7O T"l)%{)A6~lH "٘PpTr&HOДژ2)2d"{IM+ J1kP!U}#P_5K f\bsWBP( BP8 Fk 9J:| l>Se!vGQxDl;Z$STG$,w=K.uO!%0:p^ :^f7x(U^ RYOYٗ!;22߇ LRHRYxRF3Jc^ЮEoBkSx.[U=CP( BP(|ɡ| i-l,L-&m"a`^@z|(%ZB Wqԁ Eϒh(tEq :M8,У1n6i)3B YD4i9" b8 ,]^pLWX?Mx4Ad@Bژ~Z BP( Bp%]N$RCAT CAT+K_}8 F)ٺ %_`8Ӯm[:pM6ڹ.AhFzIdpQl F0&0{${ =,[FE)1~ECA^e)2߈" BP( Bp`\GA# ~-i0b`(OkOp _Lхa$)?@>ωI-n*׃P I[N<"n³=ScTνC9QŸ_UyQ^ZOdR(gkJѿj(TÇaz͜)>Y( BP( e W?m&~~)d8O bsDI; m񘞝d`H#JV,j3aIDTج9c #N0QRc4Xjp/s 1fI5 @ƾq>=PR ڸd4R BP( Bd j{: 1uTSq缉̯ͣilɕPb:bOѦtRI*YRRe,}Q:([3*;^[hʟQHD\^=lI n !KS~֗|:#1ed>|[i{|,vTDP( BP(H nL C$zŐKkV|^Lի QlMм!ȶ4'`؍7wRZ h7䄚 D [& RŸ *4rD#E0m|\V)ԗ`K7\Oq̓'Cz27&c>~ʝ8[;3TԚjA Ƕ)j*jM S bݔ&N::5KZ8Z_&k{ NJ H_ 5rvs /mFA LntWAHdljE&. Re<9jܬ3wȢ!gBwB@運v E@XM3 ] xW^J"R gwܩI5-ԂݫI5-Ԃ ] *槟u0䓡U~Z(Ak@q{/vꡍ LA…k$&NpMJiw'Qc9mH LrʠKxFm~{j``f5|4YbI65q 断Sc(L?U}=yI< J'$)?* BP( B$w-FꃷO50*f)~eDa# M(zYsD&E)r8^"ppo]FoPHl N UTiDفOB&EHH^&H#1w~ ~@8fUP( BP( 'A%]dȧ- ""3:7#'4=T8ttqogP ^vpU5p7䢌@1t$KU dV_5mJ/LaP[$"`"C#25'І phPhZsFP( BP(N@m׉b cސk9_S2C'"2<l.)G˞OiFRT y@RW YH N Jމ lӊk%&=)Tg1{<~DrIA$dB;\tp4\*JSAg2(6b p],cK$|x C\͂ɨU#PB].„q fP].D"$ .?7,"τ:]/T  HZ7CիW]u]MEip1[NAD!=7̍%DdJD>$&dAgTt:lDTz|"aE Gj|x\ 4˦L%Fc$NǯncW BP( BpYTa &1suVfsu̴miʚP]h e@r^9@N9BflXnAۅ&5C>Q ՙ ^&R%IXNm@CSg|8U ](1A$R5#ͿwTaZ( BP( ' M@bсz~įίQ Ec8- jj0x隖MY4 6L#2=, 9H!IC D gHm |)ӉJA<6J64.A[v3F$Rph5"N`OLJAdIH,@ D CDŽ:i99 /f9P( BP( 'ZkNhx0uȦCߢ?2tL'BG6@-IJltWAȽnv1glz F2 EN$wKT!HP^&(B`RBIA0P_^ v/r[7Mc!Kmj|*P( BP( '[eׅ*rC7p!Sd_8-8ڲnG8wT]b19f9Hcp.fђf9_Nǹf1%a8J͡Ӵ-Fsv@JHf@҂BP( BP(XaJw]ϹLbIO5`ȍFra@Z*D<| Zf@ɭIqB""1dzX|E3b ڧ cq3r*S\{d9Y Wepd!hwwwbB2wGdqiN yɬ+w&D$h)C1Mц-VC59CKĐP( qń4 `0 yoiOD/!{y(wOrA.PdC0*лj U!o)p {AQm=ZMKV"^ݽ_= Sә",@pY[KȐ gmI.q?rc./`0 `0 ފ%F*V_QXV(UdoH}] 4BBar.1 W\,^,FkKM}dd"Tp=C]<џQQR[K9f|Y-2$xFՄ|~,GPwko͗`0 `08>J}R41^Gÿß`? =f}(hY~yAli (r5(gcg73:[RgYCR,QYKwx"C+!C q5BaJ^REF jD2pѐXO9 `0 w#NLnBO~8gFE( `j6pjQMjQO:w {R'T49j#[c= O[@ʁE/!?d&pCZ$55/avj*c鍫i aA^n`0 eN?sY{. _.x+ӠךY!r ܵNID0rJ쨷E"2 . h֍@VQVΔI 5h5h~8>26ň @a.AS'UFGCxs$EpS8!nY s 4h qG4 `0 7kTxڰȆRAzeX\ &::hZy)9"\*x YEmX3!wke?(bv/oS#GCS2~f &] O\ .?衘؉`0 `0x;ou>eNaq~D:o!'bfES5icH6D@M $J OF 3AKe `Dgd.D^.I  W[( Y$i!)b0 EF+ᰤ**K%6 Ӏˇ.ZQ!w/t4CA٠>?H!!J@$gwZ`0 `0 0h6΄5"ąܡ䵠[i;Upv8,] Zs(0#Bln/ΐρ禿 nppUsq4oHA!)$ Ma,<3k4#D+1P )9 `0 /D*=K}7ª 5@Ssi^KO^aW!E$ h3TB›˄S$ڠGfJxNr-(wQMNKO@2~z:HƗT@/JџP+P4Sq9tS 0 `0 `J}׵ K^К:HhD Uavw@͒U+ t[sz?U4.6)66^t"M4.5()t1( !+v88KyeX0)"W `0 `0x/Z⤷̤VI}{_@k}O[l9]#ogA[?D5XWa*Fh9ɂ*!BOɡ*0S$$ӎraCPqѨfCl jHzDok5y&^`!nwcB8XL`0 `0M_A A gX@J}-wURRqF R40bH ^2*ȫEE^ :µh_M~\H>xTL/Gbif6IB( CB)LR& (^Vd I$ci2TA 5MSAG&  `0 {5 րP.D>Q B f AAz,M &)+ӥƎ=Өmc`IA 2aFBf!B 1Sx!"0dMIS:dOVPB2۔*& $:⸜`Zn)߰ڣǻ5m`0 `r^|9cdХ20bhg؁c0K,wieH 4l-T*ߪ@x LB!U*wzŤ+VW ,&jd(xѐamu£s+ \NwYC5^ `0 `0 Gk|n/1hZoݫ߯&ߪuG)$FhůamO(76:5JiG%]CZRlOn`;$ 6 U;2Q= ԆV WzAțB G#e )9dQzCxa!* `0 `0{[P*W6):X_P w~+NVD1{V9SчPAIRDL ${_jJx*QU:hP tՑBtCI޸ Ac]&ȡk`p*l.':n5 QjL:+d0 `0 C "]+Ma5\F.RqU 5pC2垾T?L6< |_AݣOKIWY@ \&Thg^ 5V;}m qgw%;BǟK=D2E!"p +B-G3lI `0 u`ƾU^r ?ܫn6 j91KlG8 0H V].-{B"`Й2) _r/. >zKi`HEKb6DE{Iڜbfe{ ^@M!8Eu0`0 `6T&k rRV_3&~a{)V]55JLWd` +=>D ,8'a 9 / LD&tI[o~J.jJV?Ǘ|#NWSS;u y ǔ<`0 6ɣ4I] ;ERj8J+@eI?\." *!MNtqHԂ"821D0kZ4,90KvȒ؋ƹX儆?$23>/gN oYSx(^aO`0 `0޶Q>) ;cr.dv3iޱ9.fA SHJ/^ّqTV m/D@h<-2{5I_Dpi2~N$onR0fTFK=Qр@f`,0ޮRLBysxzq `0 Ѐn7y7 kMt1p$'>|+{JDAQ&iEm~WKB@H0IB7ձcC ߘu%Ԕ\+Y >.nEIs;5d&)u0q-¾2t\o|a(Idr`0 `0 'H{Z?RѠ:;Jh=t(ZK TS_Dd@fyc\nX3RcgoF_GJ(PdrBЌ v+Fa460z2GP jt)J6=G [ ,J! ?$\WJDsa0 `0 ލ0V8@}}m3f,6ĮU¥?{%z- Q:웸(t ΕgQbL[@Hhy_ FxSs`̡ص EBm l6 xp"N

c%z4 } #4>:.Jh)ʽ)?펕[E4y$b *y3Ӵ1~7lVI1> `0 `VH ?juUbAV iiS$+0u,mW?Mbg #^ć?nH!1((Ǫ+=2*XȰЦ`jvcߌQv N 28k 7!\AUxnnysvO`0 `0S-9ɅW?5?qקQ_3!5d|G-AW.$?`iRNd12S35@Ke;oûs@;aw)fJ`[*Ra;n͂1l&,E߷IBȆd(Ȑ~ 1 `0 B5f"& MdPR_ rkJlJT w7([" cJkUc4 @^Lrd=9X0ٝ0S(d0~42_&Vgi=1>E=Qb?X< \&tB)@dEgs4Xl@M~`ʣ}%S!kKDu!&>ҟjvJ u؁Qycq8`? H`0 `0! J"m; TH0~!@^)JvPgCKd6^`[ZY!h' *pXto( ꅡc^xƵ%\ QNHoIF D& EA9Cw6|LM_N8cHRȨ`0 `0 ^ Ԭ 8k?_WjxQ1{Pe x$X;<Q[3X }fCVf  zסKDwVb$Q' ;Fh)~a B<mQe#IgMfaTz{}؏B `0 `0x-6ҎE^U#I`}M1? T0 R@K`ӡ Z*3fAu'*"Hyj;. ;G@_u;WHT{D,- 쒨/DL~W $@ީ̂ZR 7$^!  PK `0 `rБ6{aWo}+D~$4@¨P(p"7C+O^V=w}s.n&Q⨀to讎 4R\dI8c?e^,đ% 4m&E1$I}&wI?٪_Bg7,*qNwQ>a0 `0 /`E9(cZPK.vľ yִȱpPR1k%6xvɯA@q IAKȄ<JEYAȶbi)Qd`ѓ(H^jj) Q"Hxdzƙ(A 7֞ўB-$#Ter>v0 `0 ތUk]v׭ J|/WTe !Ң28B.z*,qzlۀ9D5эɝ# Eu]^ #[D8~oz2 |C81EClnC#'jbEiE `0 ie\gGJD^UBv|{HLq=BAk1;utCjSz($0萲~ tG.x: q&:¥]$dPX=<;Rq2x IQE^CEb4<^!FPMPjh`0 `0 #~r T.PZbW&%~/M02A'z &I _ oI/ Pl=D #[}1+վĭi 'j! Ѭ=BB #˂ps4;@SQ7Q V{sCaGF}8d0 `0 PVRjhR= o޺ @M\B-jߒYJ @ \:b,*\%\Ty_ d(l]&!P&r| rK'T4 &JxOZ&JT7MttLBgK9tDK6 `0  |;]di~}B7=M"wDId)zQ r-Y:<ZGPf QbWK ~ggF] C@/dʓE(4TQRGc@Krzt艴yPݑA-=a'T `0 u0:&2Qq9D:?V`W@lc#3$}ƍSf=폊pȖEixe`EBS;U\$$JQM3}9H6B%iŚ-MQ/8)R@_8BU.`0 `:`Zj+7ޫG +Tbc+v/S] ,h z H\I9Rx{POstp \ 4,eP~P#-\-5Q_aߕJ05^x?'"hZTQ0 `0 `ZT13jZi*A0`WDǥ/EH} y_ g+EH. P(1D(@|a|#eGv~"fg5TE2)jBw]#$ AΈ&dD} $H_IA&whm{##f41m`0 `bH}mԹ{QeRJH?Az_BuGHa *? րW$B:f#l%v 8K=NdWJr0 1p$kVJE{vL ~:>wIqP.9Jh= 6:%i8qdg `0 ]HXË4Sv9xa"FQq[`ltS)G@&%C)oZ&+"Gs^7| rG˃,ACăQzo=*ZqBPHةJ8$KZMTE@8">s| vXx#`0 `0 ޅ]@>;.&컐M#*!`*nGC^ ,4Bݐx~K,)ЍU}I3 > `0 "`eXuwy.& m;> x=gj!F,n%!) .VH%$# @0}T eUijXI`8ڦDklfUb(nC z)d@FFh'{PQ&q=xPga0 `0 ^FpK HH:/lưyytIl7'w[< b2U#% h1"hBe`IQvB{ @AGENLCC'?yK!*oIvfRXvCobA{,Ɗ?`0 `0x+k/5z`pDɌ]t%+׆d dٛ-&$"A@0Qſ} ]6a1XMdFFuǩ32BҨ˨⹠z @3}2qBFȯSp>!7U_kBJOAW1hkʡ@v >3?M&7L,p #=5?{.rA/*-᎙=X'<#R? y*ph{q+D߬B9OEC b.`0 `0 ^B =°w!1,B6py{hDVhsTHj $Ӣ ȳA-a3QFPkw%hʔƯ dGƆ ?@iL\hp3rAa0 `0 ތ( x;Jih1f1z;JP9yeKVFBB3R)_P:}D%TE CtD'14W9_~x"Bp(:\./#R!¤ƀȘ`qPV>#ho rf :߀ES}`0 XOjԻޏ(A6>|~ϯJVh} mRb$ӪL5a8Αz R4;!0QlF;aRjLBA*?l~>8&2&;2~knT։(5t`0 ୈ@ԣޕV 8+vy!;%v4Pm2X2Ƚq ?aychvJF|u 9TOo;O;߲WFstv@1~Y9J >ϔ(֢d're0atO `0 c }oTN)5t2^Vb0P ד$aЯ n6Qž4d5rФ ̯z7wOM5/z,tbp?ǟ]}@HNrBAIgKPH}^Hh `0 2|gZ+,0C >mt%Y; 5jc>d])HȻչGVtգ. ®0 _A0%%wֆ4r(f* G2h`ѭX1TEsplCJVE`0 `0`^ԛ8 .BC`2ū82(Q:Qjz'Bgb a5qT%.G*qVn+Mb 8$Kcpa JbFu48vv e X32~{[kaQ?>j#g `0 w#kޯ8rw޾֋=zR)b(a2-Ns0{_%ѥ8#ܥ$A&N_M"PǤvN/eI>ix&J(!V̴pkteH$D}GԽq N/wן`0 4\P#g> v0/GDh[@0DH !G~pp-D[6$A޸7˕`erC 钰h foJɯaȪ3TWڀbQTReX@DכH`0 ൠ̠ ɓ7M@A4] B  Q_>%Ꮣ86y_-uD$F4K HrDuzh"I> P ?(5?X~K%AkdLk]zІ\R2$%Q`0 `0fB.˘ywk! 6k Tt@uOQǓR1y^8DDKB A`0 `0x(76]e6@y1&NR:&NA^8^ a3cLL ?*s1 ,\toeCtwt2lHIɰL54䊺UGTtKQH3DHH;C?b) $wXa<1 `0 /]*DUAW %׏R_3 B`֘ު^c-U/H^[] ]MX B_j؟H)X!%(ٱ7G0$ՁbmݚaXY> Wc k7Y)j8s51<0} eKӓc0 sx,D $4H'Ƿ+mPyUD'9V?e1C$}G믃?/Xij(xh]c)|l-\~Xn.޶uֿ?Rl? ;>OHm{!|;ߠ^uqy0 B%/3ܵ^1B u|笷֢^,Ah@} !sh>P#t ]ョ3DCDzB!i)+L8؊tD\r-CEvD/\ҁ9\uUbK0^y|yގQC~3`4g~oԵxȪw!jEb`sX# ƒ`wNOcyi,ǿU2=dHhڲ=i sTiXUzLyTu5)Nsw>QWzۻ|i(؞_ }ks u6/0~y`i<}&S+u{8mCe&@薐WyI#{Wb祯Įq_S>*y#GpEgge| WGQdV!6.΋]I͟i(Q@KIq>FIoZ.Eۂ(  |+7 ?e='0I4t(`wBv4~W;{ MgRӮU! ^qS_`0wcu͞6 S&8?Dca%ýʞ8ԷxхbP[/`eE~ |LOl:T4W=h⚔/#pSҝlj/Ѧ(vE|*Oz%!Lֳ:o4yz }([q8CqQf+"O)[}5gɿX,ȭ4k>Z2oLyb\TxSx=a٢˽U/bPf'f0jr3-W*J)$35`Fbʌek7ɛri~OZymA8|HBR- tPIuP'm F>&5YM*n'҃ҔP/CAR"d`F[Wӆ`eg M9yٮi A~~4 ҊP㏫(vl_],u>ߗ$G]CVЧaٯ*0뇲 zjg6a?\abzY7kΛ6$* 촕tڢ9 )Ϋp%$[Vj0 u/ xaij.jԜߟ VdgX m-chpXuWxy㱒[IIjqE婭qܢej]zeSoB-lhֈ:?G-uu;*JCi0gg>?˟ڍ;-?8_?dY`,%]iSG hNtd)d-as$M$.Q+H+G{]U`gT!TB,QNpcb0Qu}s㏊]4 7ay+Rŀ]k!r y-iyւFoMolG`.AJ*e^UuS Ygjf^Y4_BR( UJDw&ꈬE\q9"*~0j 63ؤ/>Y*]E4ecÅj K*RMhgܒ]O0pCJKŽP 1fN4E]BےXm{  4""T@z&Ǖy sd48mzC}~:n1XSa\͡Ƨ.e= `}?T- V=h&@W44AbEB_b\sT.BΆiٺҶPZZ6sʂrscψ ˪ϋ!̎z ކ]-!mBF.TЏG2D/7 !;bjK1(@hTj-Tum-7EUoz}azʿ%{)73ֲfτueaa}"ן\C+PZLNGH?ү6iwTmd V>?cߞ0DgAEs=#<a4YO!^O'YPrRnSW9 їhRx_e-/hp}gܛ1֊&r0 qL$[5R} 5d(}LH9A=Ģ-7Zv kwyb9!-!{inw"ӮhO i'=_Dd\h( 7E(\N#b)ڬO+2aIVŀ0함JU˝yHlG`0ψ=C.xxoj$WKEfY25|T~!ǴL,!9*x)C`Qa =&LB(>M׬$\@FR K#R< vy^yb_dhdem{r[  \D0^_bmQMpo-vjQڮHLĺ\Ιoo Z y$0֏Fj򘸬u˽^CWCzUϽJ*m;Zp3/zZ< ^@b[֔p[ߦrRίwHn~Ԇ2. ):D^_;ߩӏhK,ij?HSI{8Mh@ KS9!8w۴E"j톬8Կ ok 04]j@cyő}pc  /JfEJx/w-2ߍ.E6!V*S" 5pu271#w1H:Z ݴC~IoWu;[C4,(`> ME|ːH{Kȝm 1Dܩџ֚#cR=iށ/aj^08E"ձQy)ޥi@|풀q[%V~Z;_$"?DVrւu-+-%:Q& XL^e°GCvSZss>;bJG"")}UvkYwqgml7A!o?k%G tZwK9UgOYTt)6Z^khC{yM)MlH?DRH4J!88ԩ+J `0xD öR:) [SI}5 $HcvmTYT@BBH1$[U=D >9KB )q)s콟d֌dcIh~vb/09l&6sts- ,4Kfҙ,uu?5ʉ x{Dȩ@tH CCCuY-{ϼjXȔUWAKwsDBxs3rnRA~\c#n및uÏFOk": .k6 It NU$Sw77/1ԋ5>|m\Ez}[-a7dakI7]Kj23K$P]x϶}Ǒ1dϣՄKئ`K}O0R $ty5 S\-]1-mdCMY*K-kF]v?;I SPw[KtaxaS<5}^Q~d b07+'}6ۄW+&Xcx,J꨻Fc?5!!g N7%{_AcE`, kǶ=pՄҘ&tBj¾B(t-̑nj~rR@% L>Jl IW{F,yY^Bc^j[QeX`Fż2bflڦ6#c`VH+6-50m]UsEMd+p`\fh!6Wce>]_XNp(dwG3 Jp: Lz[$z*M*Hl^}Ӗp6B_=,)nĥqPU q^K^hP,wRf^5|`0x<^t3u\՝͒1.B*p"w.|ퟳ]'C&u(%L tC6޶h>?D_3e {Ly%d`ÚK%\5էN^^AFya ΤGwH=pr$0ڹh&|e$%%ѵ z3{RG_YcN3SiX*ÐXƂE.d$FTѐ8{ɗFlQY$N؝;.7k?k;EQ?G)N~kH` ^6A(]9 3"稯oie|גogfIF9`I #b>RdVGJ%~>Y[+ŤФN4IӝizC'ndLJq<R`-6W.ռ3wĈKX7R~Y;P ̮QCD-茣se*#PmL~&bj%O;*oGV>gwD{ =H~Aux{6jtzI~\ψghk&C#3VA;/_WǤL{B$4lU.WT;yW? PGpbOo?ɘ 3 ^h6l68,QK@HC˞̨uM4}#Øya% n#IyP!bԠH[!JtP8ȏUǓhO@1lRTT(\D*hvv&IL{ӊKԐ&M=)p`0mel25ak~ed"tqɡ:gQ: ihAfA#.zZQ*[3/#^/A 7숟BVϟ{#vSd]S./A{ϽJӼ{9' `fjдZ7 [0(j7#Juz G_t| nG,rJA4Z2le B$$\ώg!\vj?^!ky?ԒَzoK c.=!vؓf>@5SuNh'M7$k r(Y}OR!-i,NC [X<>bFL`0x*4uo](kJM0(1D(PR_X_̀o+f6CerTzeޡtTSQS ̻;73KI?\R-2z_$n- qAPy">]!٩CZp-"VfVUA?ZMb,sX=ifL1=tOP셴ѣ0*^(_Ճ+;JmxU5[m-Hzko_;)<BaΒT@SSK_M`Ph 4,Yd=Lo.m%@;f MC5|#SO{?]q"&$QVLTRhׇ3ê5*rɞFHhw. õG]xN~euSN׭g4K ( JVtͣp?4Tu(վ/d,{}ݬZ_<#Ko)2Ulع8:ib^Շc뿴X0Dse(43@GBD|tPiXac`Eu9%iP9IQ߇#Ĉa`4R$aoAuʦ ^߅"n0bU̓_L$xsKp ysasҐ}փ*byIʊ/L[9_ȅ<_<v ,J!P[u"vؑ;~\A9@z"p!.@R՜x!]3s5*V ~ҭZĄ2Z?b=8ˢsrIVXQ\˟]8qM`0xIu;QxGQ cck5mwompDj,W0C \*i"\#-LNЯ[Ie!ȃH}+cM9iLfHN#lNsw՟h&4; Uz2V/:1 3Xn{:-MW6M?_W$ 0uЇoFXϻa\beTUBՑ܅1Ҡ_O:Qg25U OHsZ0̵ P]&w]a2Zjz%-&O4[\:5X#¹hAlaQLm?a"n&r ֌`z^:K{Fw$Ǎ!D֠,}~Y\-!;h,cF1Ui~~e,G8z`!DיBܟ )ȭ73瘚r%PG,⬯U,t<4>~!4ʷ tȎP.8- ~P/"a9-)Ahع)mڦRGDFqC-NGGiw+,ca)C4!NmLC,@.]eunTYܦSa4? lSfUUa漊I'FA =Z|)*հի.@~xN-hPkEXRYN.[ &AVdCCY^HQ&l2!)8߹Aq kGh{kǗvr,hqm 1)Zh=p^jCʬYlbai(gDiK0 4A?@C5gT* 0T4!ΞΥ~#jN@\<|ްsJpc }"{; ?: /\"M؃GN}I 3s(!Hea\&Vw.~@@7gjݒ\8m,CU jD:0I7e4?xk_O} `8fX.~.Z`$hz茀b)bG+:yA.4$#JXP /B%q *[J^1h#o:q+}U.6םz;XG AhˏVmw1}lkᶳiXem[U6pP'n܃dSQE#)XcnhtRePoÿ?#4n6n*S9~>HP"H?[տi6"1$Ctd0L %l wC=L"%U?Y^{N7$_muc"G)|e+".&ػ^+G?$f&p%`Tݹ.W_<]3uD̾75aheUa Y40&3dk( kފfǀES[ /t0ޗE̹)pmmm1GX@ ˖QqS.wP8=Lbث+V`eq}`0g&wZ殳{2w6;)h.ddnZ-bu,Vz&A~@rXU@xMp懅߫ߏmr5\rcn7DN,';("7,:>t hy)gh}\0u2h@#jm5vY1D*?"rHz~mɛf.O92ڒֲN'^c6t1HN$U.{*5䣳X}635{OGv6klg\ҴaYśP9ÿP_k*?v᛻ZʌO9JwvL$;\J IK&=(LIM"h@*n}pH z3:Dԫg.>. UZM*[}gVȴqp4WKҶr|K_<`j9&[w즖NA/50؜Iv_]?H4M"IgPxBd|Q?Lu7\OەJ ى'x~1bo5WL"g̊p|ƞ~' EkpE@/%:) ;p4~Ah#nZ7])FnGz4e FWKEzF$t/~%z₥aojVJ\|Y= V![5Iy/%+DmNbCCŌj UwkÉҡyrDnbSxRk@/721OeY&rsC£kKn"8HWI婉LBc*[QW2qOa C4L:5!q?4RaM!תޥ:CdC^_GE7t), 7pp+`^ P߼UYo;坭~H4TB$beG#ļU} B:2i]MW*6EXJ$,}ejcB D{PHʦ ׬v[,N@)Q[幅UnȊI3bAܛ?~ +{O|a0iytR64ہz/ 'z 4-Zz&f5};b3S? A䛚6ሖkLZkJl SG3FD`*XhWC3%IR9# 5Ac'8,$’Мϖ'k\e]3ѪvLz 4tOt{($٫PTwLE%I7k} mz_rlڰ`'NQFfdqqKde 瞽 ˖ - = {;D<)t% XB}#x~0#Z?1IzD@mϏ\J0%dL$@RXo H S| ŀ25:>!( ǽdIG c7:܆ m% 7-fb"Qls|zs?״I:$! 3w  f@W4(Fz PcYJѲCi YqBG,n,$9"-_#.Y8Խ0ZE5?ָ)e!7[Qp5kbRK{8exj~ghB Jty! t)f,X{V\I#Y?} tGŽ[;4K5/Y++jKDmPx}sKq2ǟ> &64*xtC 6Z)>Xzjc,CK |t4Ui b> !W O[64k)WPQ(/R>_~1ox{vZyWgIdM8SVèfNv[.`0xY_KR04syo=Q_z%NT} MޛM0)ɪLZ&28lp]eNA/}RgWh3ˁ# +m-"A"\Th o6 #j]w=Tћt] kCmq7O{碀5E)ZBNzdLè*ҭrhl䯮 Dy"蛵备5K~*_?} i7\ 3 ޵>%#;:c\#tVf%iߧ"f9[ "!Ke(N06D_^@OWy1(Mӈ$iT*I3,8!z{J^1tO Χ~߲4z#|f`.>[Wz-ŵI~g؉V1 S{`L2LO=0 4QQta<``ֲ!ю`#ǎ83ey@ǭ\Tw_hCEOf-}7e*I IaEEK9-fkg=%g e$",WFgp1APijH6Cc/61h6ĒOZo3c_r,uCJ4UF1z[h*n#[Ie9By<;.t9?4[tk]>]Cg.vF\W['a1 Ynd#:R[ t]ZV^ƭsBSAmHTӪ_DqyBJ'_$&A@zy!382Vr!C4Ux~ ߺ{T^y#x,E7{͎=! o\'44#hV_Á(?[!7Mx2_d˧ch .O(wQmf wh\O0ur wQr$וVaKd(glhsoUR"@DesZFN=R )-f LJL6tUSȈĽhuYg}Y5_8kw_w}v[f*`ue # hD&.>I Jph0h5S'%7{q8K+C1w%79Y w룙Tj3L ~L"fHa[P~ Lrl|5o.?_b2@0E#*jS+; ܄iPFfLÒ O[OG輆 _R1dst; M"߹?#o8dkū6E2guY_҉駧сS_ݢ^f[~M3MJ؍9N Kr>D44裺Im.H/CU4~ň*xQ!+# F̓ôbQ g6G@%'禎`Ej ODI∌YX# \KqguѠt.+p*IXop^e WYa7F9 vd[66v/Ռ#Q lt*S;@f+tO1rhj5O^, [0h#)q`ґs]奛yp;IR_K`*ܺ e* &i?a%;oQ5Y4 Lh~* {#5F{!HG j92ZcURI[LL]4=,?kq)_I))XV@$:묳a݄pZc?$-^5%sMA?ސ$DvB&ov>HdьNw0rWdD|s+5.8[[ _2)5#`_JDгZ !rV(_hڮ)Rc&u)>_T;tYgm*Ωzq{=r2_Ѐ?3+62c!*Y "4 )d5ݤ+zQ3HRPXW̲FQ1l b pB`޽˅$+Q`}%i#7^^aPr:7p$n$<(_xrX&Yi$be}VDߤ^DW OvzPQ%X:묯iIxiA$$yʯr4H_:x !aid[XZkB HtՔ嬴 |>9KOcEPW SddLTTj@ F1(nw/D!Yguw,Rom~"qN1wbbI'=U(\c{`l7E +%Z1)YA%(qOBq`ZL Srkk9?Ƣ1)2MQxu!rYH1;tԥZJ ێ∉^(t%*4 sDY|&8 1sTo(E| $RV-u4px!]ۄ 1 IR=>JF?^d],گ0̑ ?2gBv'YguGb2RybuLU~M<JՠF8ט_&a̓GLeDljhhY n1=8SQsW. m29%[Cb_,9v)TeJD`@͍`B¤Ygub_筵nj93%y-8Ǽ۝H3t4ɵo:\fL`r 0oD8>HFKD0)C ^D E䮶_0|Q2(@Uſ8xty{`sAė7ꛈ,=;P45eaG _ ކx 5A9]Ľډd8i Y)\/ڏ-S$Xɣ !}1_Kl?<ÐZi RWu҅Tfw: ! ;,VguGkEM>tp_ ]/6 P `؍JxO %XLaO$>?Ao8A\s+:DsۅN. 0EJrÄ&7htNj/]<Eҗ+u77)zMo soI P$o}h&G>DeYAޜ]X+:yॲh+2wC~]Ȑ'cYp4__⏘ض$5*q`20cxh )Z 3k,Wɵ vJhoIMP~LɃY 2WTլ 'YiiF 壄0(]A: <̫YŢLAoh yMA0`wUQb1R(@rL`0;r *pTm"q"N7N%c`vyb)B`c $H aY ~y mbK;IH4:ٛX(u nd~&GClgK@$㥢椌Y7AbAƠ+r(r T4uYԆy:"KT[F nzM1wD$ziUk&{*_"Iă_VryWD+ /X{2 MeO)@Ac{p%v9SS "T:ZwdՁ07(pu*Et Nrpz=,xхr /.u`l1 !4=):L GHW{ߎb) qD-ND  P^!R( ʢGqFrVmp3p(jW{sno0}6P%!ɼʫ@{} P'_ d5l = iB"4qjA@بKvKʣdoH@3ǮguY_ \ܶ33ϡ;YRK "2E9h66''wb>ljž0\3~\c4>Kul$0 !cY4B.yQRS뉅X`#~흹.Op;g/g&1irYg%jNa::s9+31TLiC )Gor`\6R/A#̪3ҜSP>קY !MshSC$]~zba."My5{oov9묳挗!GY,9<*f,*N#ȯ9_CLʳRU^!< \_1NA|Ys*͑.k)8Ao$%Ŧ(tR8ԧ$x@f$]~ CYgu7xa|@ ]+&nXD!\+<&">I80uaa_xցHT607iKMգ B؎*2Y<P|3B#"E1B` @V~ӣ=ސ?diAT"6*yI0O $QW@F<\!> оW&Uw.OyЈ:І-0w91 ] A9ίc_73t,K A EvBjv&1B:GAЧs᛹[y²]:mN$tӣj8 QC+ Ȯ9{{qaDO&?6y guYEW)A:oxM14JOvº˴EӆHA;p@1-x?58x.#; /&:'N@~e^KlV3|,E}Kc>`  073Pm1cH}3B=)M.G)yL$)ƐiWCsʊ$L.Oq.; Nfd{uMqCUH , y){+Μ6+1'lar%LT < 1ʤAQj+Ygu9:*yϒs~CQhK5o:8vJ4rʲfAJaixT!$퐭$Oej.񼀳ǨEoH8BE]66X*: Qfhaքe;{Yg}M> [%SFp_9ϗyO-2}tp阐A, b+ʉzJmp&n:?3L8Ka(:9bX؃;3%ftwЂ&04L_jwBD:A  DlN #SMw׿ OƐVk2$F꒪v,BA~ޢADTEnT V0C_guַHrp qɟq~twu_K5eXEQ TacmXI2Y42-B M`n!̤Њd c(kYd)Y[=`I*W#EE=E%@PMKJTBDf!C'Xo! S[ɼȥwCXE@&s(x^+ _PhE RU(K9!$q& e K V6;>Ҋðž />qM:7꿓9q/ƨC':^_EdzBW/D'? TeD,KCb!2UKC0SqDnYDBƵ;Go 3+u!ɗܕ GHu+Bb^HW(j"4 u^hL{FJÜÃ'mF>jDH$2KqpO8vhJK=&@rP:0ouYg}I! krI_7Z> BmkubCT2]&S+R1MLyD{$ "CFx2*N4hAPʽ4 guS"D.\o',%U 4 gY1kTqZFyy/i)K:8$;q!DŽ hALD a$ ]a=t R6q!mR6J"(rk";4_ț!{ g~̃D±k{s{˙^Rx]?@t1,~&1 \J{@q< Z SN}80ME:묳%:Zw.U5Hx>}~T:rf6[W~:E8zzp{%5ຂ4Yb-B]!Ã}a;V jb™B\t`E0Rh@߱ 26঎6/I^s}(eC{#GY]"B\Bļjq[b2 $iUKH E<.7evK #hҧx6 Vip*CZ`^&͡]PXY 8:b$^_.[*&_&zKP[!4 sl#Hbϸa^1 P;J(@hCN{R.S"xZ!`2Y 8/<h[/+1$b_ ]J}*P&q_vd':麂yzhDaD9k"@Z-h)$i Ac^OgDCB8,!%e~XHFLR0{si"!&5#¨} qp^U^%OઈM5([D4EdPhJh$ޠ/~R\/O ~td<)A[=8H:y8ne 7y!z*S2Y{:kV8Tě SlT? K&.&NEөjBèd;H0K$ף7-HLF+_~*D$ᣨ8$y.7Jקk!.b xXۤLkRFG$>%*+Gx⬳.WJ$r¹|4S4lԟ)M|y(8"X ![& VSκ׺ J5Q6:,C! .,z_Gᏺ=oRQڊd6ڛHfMeڍSNETP򓅭܃ Te&0b&U~XDORR Hrt` T-}aTwٔNttYg}4BoX5EC!5ChGCM2*&,GG JNZTf)G?32@"T}RN"GɨՐ8ɑ8rhtț{#bI(otђKpNjqtR,ga6挤WP&B撶6bUMk>(5o "l Uᬳk$BXk$k 8_xAGcLm ί9וFЏ~ԙ*')%_,b40Pd* 30  J8izdѩ+DM,)vQF֧kLvYg=tMT.Tuؤ-%FɌq&3L7}ze'PJJK!O @;yd$fFm:2/1_gD:nG3$At5.6c?qخwޱaFQh7!h謢"@"u S\%rBw7#veLPru !&lܠ=111+ \m$,6z_=$ekVXI ҕ ҡ5כ HBRdB$ցeY"D(;XΊLk'cȺBh:묳 >BG){M|H)07*PW_]` z !}#>)R2(aQd x=lF Mp:HAt828mH%/ITpyɅSUn;:[| @sZ6Y`*'saY8ZYQU*@Ao$=]H Eb4jL uZ^IK .R:ں O&H0 QcN/i*/D%j09ZY`69U=l}j&uy}z=VV`JOCG+n!FM(FWH-gniAȅ6wZjUɄ͝ 5?tb~TT/1,]~~WMIFC!jpFDeo!Ol* 3iXdon9c}JJ.^X)FΠ*EguY_Rf܂e&dBDK 3U?E( Iu5t>Y?*'1A(%_'!K3FU]Dx >_HP&ً~bҁqzWU Fguַ`BS{~ 댛,xC}a9RC$(tAځ!&$Ȝ_729Z mèڄt'2j"[Ub@΅ϕ>@fKq `&.NAՏX (pտPt8AC6|Yg5*λ5 $ܷF%7eFluւZM6 /H!Ô2A]T"S@Ws^x5<d%x4Rɰ i{IQ )PqbJuJ!靻\uwZ]oq5;SNaQqq(I5t/ ;/uPQiwނAkNa *҅A ջ {~h':/ l +\k0,0VdN?u~k'wQMa.@5bj$ VTF Sn2UUrU˨fT^y/S_3T QS> -2qRyldN@C:묯Zqq'ax%4\M3kM|:5Tg0Q. G3cԹk Ѐ$PәIlС8#  BQyl+P") B5;ltl.``bLpcqI~bRNPT!Ū $Ql(tLEԛ!4QF v9[+ᄰa#@\vV GOK ϴ+ۂH\J(2!\jo$Ɓ!;T:/ LD>%iE먘>rdMN_!u#Kbbx)t?8H*.%P<R2L8X"x%#3B84=*?-|!8gu׹R 6z;.sԦ!yYr.}9"Y-a  CBZ)uET5 *-.E ,UP {J:oG8uPm{OeGlp]$(iq)g 9„ ٣$"rЁP gH8Jf6xXi] ,ҕaf_nƲad0e΀ⓤ5jH0DpQ!|1RX>>u'"O(booV|bp!fh*"S%T3aVԍ]=+Ռd ڥ `oN02lh)"Z8®a4<.Z?c+e9:묯28ù073C0(103o"( s^e9k9M~-D|F;1@e`UUV3z/P673 \wo5ӍtJE,0v%) \KX7qA7t'憍:묳ʙ1H4*8oI{#(:ny,$qڽKI(Se3Um~؉W֝Irp_4Bj]ވ 4iOtUf {s\ME$Q)8#M ^A\PP] 5TJ· B0v;p@f5r:0W~ 3s1$ޝ__w/kw%bAE$+ε`獩JU5% "gNX>3ӘǺPv'jE* pL]Q7x! :ģj7apmuYg}a IbZfGA$1n!9s#|6wb[տ飾>*`yV$;hЮQ)J? B`A9脶W`T"LxJ9+E;M̛dNJO(o77#Xe88P*M0A 3b?~aZ$ g@%%sxE ~I(7P.5[v9N SKpEy0g'FW)M. Y{$uYg-tvS1)l)p B RPP1##V[@R !3$+֐ lEgLR53 GF}Iɗ69l(h- Bx*B?46;7~B -^PtIޘOArX{k;0bMiJeKZ{͘Ez`-+Mp4y12D>p gu g:ƈ͉/)%?uf_W:{2$1!Iq9^ֹfq oRo B\ᅊLghE6N -`Imh ^h׬]zA(XAU7*\¨VhtWgIlRjYg]kLeUgt`1H b+ uX4W2F&R?bjȷD!{P<ŸДaVZK`Ëls_2,(#eȌq@ib-,}лtըtU3& U!]i5Y Bck<$^*uJKT!`vD+B$F9f@4JX,4ţA4ARD믧a"q 3u 1cӁ/Ј3e.HҭfM7 exJ_UKjYYZLfPAR^/o5$Ärɴc`ZWwHEUAW48dtWlR` 8/B`iނhS:_:ѴL^+W\W%~7s"ٿx࡭jlO\Y1٘ ؏GG{GA[l.5\p 6e/k 56ؠONv$.4ߔ[;H .O|x}|?wqgx;~f!o €6O7&sߊF۾5N߸Ef=I@K?B>qxwAx GZӣ=Hyy_,|PEqB<<^@Pu[+d.U$-V"mhzvv/g~23 V8&D x֣x •l~ *εЛ[h8BP_,BM tzDU? f<Ғ/5^s&ǃ_djWpXxŭ5yR~6x"1[(lǫ|02Nj;11ſ 'p ~ Ptui+CcZ4C]Ah`yWm~g2a}}bW1ͼ-0Ld?'C4ǝoo\wt`T~wyBcE\,V}n\|Em1hSObD. ?AMs]<߀ZΉzBkMzD0@|\ntkhC삚S AǼL.OȥymyDH_FX!  B2W_oBW?n_\>M|jcm6m?[s|5waE/jx_/ofhB-70lne^:׉5PE}b qN+\@yEis<'9 pݟr'.;/nf?W=\SnseE4Aސl0_] Vueƾ@`*fxv0~}:TAro:x^K'-4u$.@,+m=[@q6[,) #Vi e9/ Z߅\ !"Uаyhw䔚G;yA%AJQrC&U_DGFN&á IjAT0P k#y}d!c!  6xhD_R#~=xTʤP !m~sNןGՁQL]328ΐ=^ykV3O~+^ Tn vW^ߊ6 d: e opH&Pi\3пf<*s|`iK NP knǂHݎzvr#=,Í,_ΌQޖ4ؕfFzuxwt]pi@#h;ACʞXz(H͸&H/#7 R-f 'Jl2΄e!tɡ_*ܻß2:;pWPv?fw]*yU xmsqK?jՌAueza</ r> _i]?O y9`!cYFAJBIk#\\H p.ȥ:³Kg)pID93K=p LT]~ i`{/"Qtі / \a`^]|%G+q+5];{bbBߜAkίzT`0zx4݌ ş]Fe NfvI,(_ ']k;ioLh!߱*3mH6MUUcOCOSI=>̞o <΃iH$94rdiPbQ w_sqnLHǔȩ|* U9w%A4 >{?#N]h3'5'=RMpKFsNB*ױ'(v-MȄ1 [$bB_.@ރy;׬9F V~;l F`birk|A(/m'BG~g? ЦW?؛&hv0{Y-bJN6J+kV (vl6!>, u{ |Bñy0iEJ@>!;<<ƭm}#T=! #i3\}/LJ:fM o>[G^L= o#Fd$@nKe X r(<9oaGp}Sls4'SGFogA ŷw|͠7"&H's?+n5hθkvCdF lpOGmzjR=ٝ|WHnh¾^IdKxFq7M=~CuŌJD7fZMxM1?^ ZD=~VmPtSY >ѷ_/b*K/&xgw k:tpU% )ݣrM2̠a#1n4/n(ѣ捶6 94%ʺU[6͍ZC2¾od8ny޵}`MgfZݘMx<;U OIbT6{\/hq̥/#߃0%~ҌpQG6L"J2&^ |a.gdh-UJ?|s,^m+VJZ mk aq0_~W9|?+}|_<#'#~wړƟ!T.Y#fSߚBy38euO$tA p8 !c8G5pr!+ MD>'7щj?+?7,UD# pgn!7 ۃD,$#bXd!4Mt|/h2lnZ_jPwIvWD*ȷL_0{nCj#`sS6"jbc?d?ٛj>cV{;H9n0hzk=kE6|h\tcEumj;Ӫh?{w+T \ FVN{쟄Er'(POjSf7*ybF]Њ2 Oog9;xґP7* .cRy\0MO˭GBl<=?^Lծ6ɟ6>ВpOwZm IZ99Jqlc+&Q'[?}9" xwG);FfbG{䀗 y}oXE( |޷nWlGq[S֩R{9%m9{0:dܔɅ4.aH5jts`wt@=7qoݕXNԽx{S6.߱hhPCA1vh.HvomhfUlbm"_SU/~kS|vPfFK)Pt}=?XlG*?[oٶLo~LU7c-gCENavJzѓEc6m_ ̟|d|_+gPS(_?jQQ0FVx?Lh?%kx}.PN/TO1I6](!ܒU&e5\XZlP%E؍-_(u=!2պ-|]96 y'y|ޕT紉.fpUÑNۧ#=m?;ʍWWU+Pjb(_wId:D_Lr)rSHI* EΏm]p,w ·2yC?mu[:rb Fi^?ίet Sfol=9a)_BoA>ܶM;:xRd+Z[!&P/"ˀN'ȊҳzH7pB@Z=إH-~_柭J k<< '9:Y4<5m)B%~pEߢ-ȂL/Vqo[oJ7NImڛ@5v"Q|+9gtC׆_\ &dpOA9Nmn@7>g[d;Ĉ/P Mդv{w#‡O5ldǵ:C\u R$ZƻgSmHYO_j,|1iq/ϯPkF1wxtz)wLd2“z4b)^IP7MŝE'[G`k-L~}7o|DBv<H@<ΐ!?4c 0n֠@΅W=?:؛b.(x\~7a1n7d[$>zi\Ept_U2//2H4)(ՃQ*\Sk w.=eE[~_8뷽CrtHy`NVYrktXt&F ѱ  eۦ,ܙt}||P5 0d8|[U}h&~SZq 2E'"g>1C:#w{ Q+cB&,PDkyLK'~ܝ͏/RN-d NKW7^ju\R. =`},c`dZ[yhM7/T"D6*`s m̽:̾ȁXSdDr>L^2ىJ,$urDiGHj5BtV=Ma^KraܔE*ƶ;Q|u{aH'd' eo}{E/%\L+U t~9v#Ye~|/!h?j/X-h9N QED KS0cTC>Έ(MPvֿ%7BN' a*[؉i$/{U؏?:OmHCh)A=Y 1SEFXe-U>?' qEK~a۪]p#{w kJ2G+J;!o畿Jn\_٫D">ۃPno1;խz*^LqLyub7+ޖ.pH6h^,͜M'4.z BUfU* ~މ!cO$ Bݻ" wcPڒ6{rJ$?HE8W)adU96a5pjoYN@?׬z͏ְ"a5Bڼ V4dg(m댗 /ơod3 Ew!s1qb۬Aw0ʢqՍլ:_}ؔ[u +hAcɗoHgє뻋8ز9KPu HT̚Wa (:Cs.N^a,QuTZğR nTHk:V!E `moM\ژw'tcp;#( u AiBr?2MDݿgShJՈJRD5jQsv%ZקYlcpй) !hp HqO>OX]&K5Sk s`DAP{H۔Wg Dc3^4I4/etOy(J0aY!kO:FojOrd+-wAgLZ+ S"!$|cz/Q9M%n Ҝ5bOϏ9Iaxh6kxǘ- W0vn8Cd?PtfF U槗J~w0(!$|h'udyX2/L{`Ein$G >ͳ}icze_x΢QaaU)\]Y"ɥ1!t4FtEa^iUދ1Fk>(21FCPAv綬&EP^akFdgɯTAKuMin$t)Nbqe,`2P#C|6X3?:*jShsAE, ǽ-sQ/ qޟ㈈E4tik,c-ok5\lnvTeRiN'U:vw2?P{݃Pz"T]l7cǩ!\o}~-Xo[/~p-:ʔU4A >жi[buޟg096Q5kGSKHsBskLVn* [VӋl! @4)a rgGHө\G f 뇆)XgcJ<F| 0~ ]"ڙb?ځ 2ѡP-y؛XpSkvjԫ#kIx;0~.&߫)u3U #kV"x[+Sڀ񌩼8L ˯q7hd<}8'ߴx-bq)^}yv[9cꇽm6R{??GT9SJ47Nc~$܀NTidz}6_?Z'wl),ՍKQؐwQN9UP }5kSPԹD|`bc΅ Z?׊m~]jV]{[,=rۣB9eѓaM۪|hM_Vvl~L,xT[Ȓ&M%IrP ܛː!/U,aIKKVV,03,Ci͗dLf\NkyUsd9־_Y~Wdxj@-ب+8ϫ纬.wu[Fs?Uɓ5_dFBt(-V+}=FMPк*%9m1DV:GX,9nrwnАj)ג-~h:2k0SStIIgv%r$f \#r؅B$?xzHB$*9+_(>~\qWCďR4rܪ8mS.s҅4S}^?j#)^ɾ2u[_Rz^=Xh }ba}uyЀ.m|yIswtgpY{`M/rz7ed.|d.{$ ~oY/-^OA׾ޫ.5`v$I⦀k4nh|\Qye^4 7Su[m)&U4iχyn'= ;|C)=݅GoT9 *^@ePb,][!\~kOJ .2jXl׿$|i׻ ?bDx 㶗|9i咯z{Q Y{?mUj?MComPPa  DL䢇=o/.xJڀTw^ |l]`,m)dُ3Ժ$!Fe&fV_6bY oQĨqk1LO.'cD;j gȉ}X;؎UIa?1oJtEKdBp5~.WjgyTx^k =RW_1碈ܩ 3n5"Cw(,{=d^?gizǐՕzc/i6$>ۉO-FE~^LeiG >0*kP]wnvo+`MYz_`6ք;L!~ʅR3F½0@~Z)Y\.iksd+` 5wx߶5Y`R}%^.:3kk UCAAzιq% V$JP{ )Ό+a 7ƴs@&lyUݧ=^CҴltZ kPml]u]gC6_I~vqWp50"uu=񃃍Rjh] "*I^tf/CkotA >ۅC􃊞  O ~IyasE=.Oe[fqxUWtǹq:|р|O eg6jt@1 FnqgM}2[tWy!~L\B;rH"偊O/ +y! Ե1lJ㔓M y(]_kdx>/F5W0?wXakhHxOߝ=rԂNH~Əkx7@R2m6L Z7}+c(aO|VU #3B b8XE܁#b r7mޅ|}XXN 5?<`qNRi}ca!\t UؼS?\ tlE>$\_` ϲ+9PC?JdWO? dhM%a@x5!ka"_z_I$Xd[}__>m%F[8po?EsiL%_ӠóqÉvaIP L’qM P%- 1xt}ˁҲA丝")K sPVz#~ۍEK/SdZyex{ЊbʳMD| 5UҎ;m8Vr?}v(Y˜%JM}dk0A8jM}4Wm!5!Fy 6lKҀhZh@a;#~$3C!W;+iBўAA;yoCC{cT3!hoT`UC#x{>\(]I~_^dBnN_-o*͂(Mq#LBo~exoK`a+oW YMOq4>7V)3p䛟zLvn$P24]7P36ݴMm}eOy^i YIs ΍ZaK7 ||H:]͙o_AUm,G0뤌QƉ:Jr9Νa1'΍y}M^g{-Nb䔖xELtT ^;MN %B~/"~X;~ě}L&}ya%_Uy7.@ zY}q)45;{MFxx~ W0};s=M}ϯM8NpK_VG\In7,@e#aYdԥ'L&Ħv;g%6L/D-z{-}t(|1 ͯK~Ю#ȟ4#%ҸJwPLN*gW&u#K]Ԧ#@JPƔ8 m<66zCFZ@H %̫B6~_Ujfz\6K\w][uc׮dK\.7rH&XG5v)!w1Cy5ᩘRz{T:9㐛69i TΟ?{I?"׫bιo`6+ xTWsy-#~J.o=LU~,`zc6Y6aىY,>qܙn^ *1ؾwS5WgQ O_ 'K>U jِ<Ă=uO~؋eO0OhosOM_ŏ8éʄ?DT_`tC7wpW7h\IpIuOW߱H;_\bQET&1*Mc7ĺѦ0ho)msv|>Rr'ps:ye+r7RpL%7s! $&@ciHuIS_S`QS˾G X]= `>1zUB:೿aLW!^%VKN34H(!/s"V? Ueϋus%Pdz{)>v-i&b+񼡈9MAcY`_>/#۶ObsIQ 7nO0bŌtO8=@wɞ- էiy^p< :[«Ƌ9L 8!(+ gr{iw)?o]z"vx#| gm6hsfB_%`00^X3x8[WL_v2fp ͸BZ@R̆`5j ?S\!b3T%aV$nS*kP8N4snKPyT''e%_ 03j;l s)71=@us)7VW.]ίm7 Ggz2pWV!n8jnTh# (M%9HہG!t s$㧍I3<y=7lϒ: =n0[l.m18/$cS,w|j|`^։1 Iaq%0Y ܀amF%*G/?[M&aD}_'x5ozX^Uk?Ci}UJW\; ۓi{c X\0O6s9d{6SU޽P/ts 摢/s[ى!T f?ƕ!?@g+Qˋ"Om Sg]?|<EAc fp-W;L.U[;.p-3Efد&@'D7y`QXډ/#_&ݙ\DT?ϴ'oӯ4І^i? q*ڒa=I6戡(|{^阷O>!> eg=C^ҟA͚ȶ,64[_UI7S r]W}>bqmVd~,\\K~{Tc`ЩY:?5›4ntx]s^ŏN^t@χ|u?Ͻ;hwA%qX\|TrC+nkf0B 8_^?z2|z a:k4߅UYz=#Mc=ʀO߸h_-_ KXB|mac4K|clpMn[-E6R[QXmJ]~-~|7Y.'/! ք$8FxI Kg,/h7LD+e Ķldqe{ >.׷5FaE,l&&k@|5%-]G@mpЯՂ,xjz&F?TzwLFI| 1iK1KTϣ)h牯Ǐ ,H-H@&w:Âۄ<9~F]J5dl ا"7YO%.mʢw5 R@ko?b#ߞfOzG=Wb}^ 4 Ɲ0} ?3_@x wbgE?n&7l55>OMiP?_.:`!j $Ȃ}3L4q6S;vru7^ ,yo&r[c-0%7S_4^Uy=~%t!<A#zBu6<>^ʸ׹/SeDU+S;3w%i3YkXx{KOU%W\yL`[y^`¢ .O?_TMܟ]TRk Bsi?UB]Ъ§ȅgâ2`7,7V[4#Une ǮsB燾f?@"EgAtȰ `e7 j{My%qP,z,<'tIX*q )*6(z*GO'(HnK_~<+<tъ- gzΞWDFY''GyT"64s"}!a!Ɲ)uzW-=  b{~%:>sy1BD{D_ H6A~WZ-Um/bI (a=Ysk{OϳuӴi1r{l}bO?+~]49-!d.$~[ `TWWO,(Gz'`| lP\tˬ,#?I<;'TyV޻/~X/h֧Q՛(1Hk}},Q?!H84 א{1L+hX%6cۄfsL!0~kܸԖB ]/Qf H"x'ھ[g TvZ4_a#fv8M%!G}0$s4pw~_7{X]SE]Haa"W9P0vpi9l2ŭjNjIq 6M]mJ塯`5ްy_ďjc-tKgYu:*&.% rZ,dfvC<j 369ыfiƴYUٿl ý ̱!LUD|gж7_ g_Y>eiĺ_@.GTBFľúiŷ;$}5[K {}z(?1տK\veYU h OLԿ%M?c׍kPlC?OzDlYwO4p >Stmm/# əz+2)D TPd>Uc k0m-WLÍ>IeC-KWЧĸ~yOZ:u[6tƨec%_7y<܍ dǴO;*TKhJKĵ-uVeC-~xTQ~RU;<{E=ۯ[-<,1ĬJl{4RGF`wDϲ"cP! 3OQ`lxa{ʉih7.Nj..C s㔮E{ &K+7@ i|X^zAATL;jkA,Ck[63=2 ލ D ;ԬN3cN|/ֱyԌW4!dR2Lv|Fg+{l?VӰ{NTt gN0Rg7 DŽϟv$I@?:Zj$~r^=*7 iyIQ@n%neCodA.,AYvSFϜT۹l?/Uݍ=R%|Fk&HvKi<8{ 1}a O| dZ_s}A /&|z ς̮?/#(Wm/|LSMmq2ҋCfUak\}W#{cO$md~_*ЃmKhRL/ÜA3~7^o"|b}SC3G+hǷX>JL'~Z C2.Y:s}Lˮr;WeB &St"ftc&~x3u:5//? 2NqƢmoL @P.2_3~R*[ݦzSO{i"}xZ Z CuȀNfL{BD7`X6?;I=yGx И_oozj2iHzg,J%+z_?d؄kh4'ɚTal)l|1QE^Ki2|Mpl, GuC$UIa9<#hh;bUSޡt7(~9 Ū|o8"'U;l)=~T7*K cIxw>r-~sbX[I,^K0 F=|_o%S 5/->{'Vr fmO/;)k -;(K.6`q ; - i qk1tA׿ò%B Z XBe??3q[t* QgFXy|7@鑊sT3iGsMC!WEp߷7 ҍ#q ċ[ZU<Ջϣ8j^)|md_EԿ~4)xtʘaz% ֲz?P#-$/^DGZ7DrG'__UhsK}yw:+WnM5 ĔEGt""LαCp^X[-<~,f$[K[ %lga407冎ү%N j1|Sc3Wp8Ll eK66H*ue ,:k o!mMpå4TU wNoBۛoi|z |n e=m;&; ˆ~<k?" |u7kOpvO5r%jYu‡;熸XL e8i@V;`zgd~lk}M"2ѡB]O,/yI!}yn)q = *awD+y$cҌ<,Ayk?G#lZ"wG0R_Rt V4(I9 8 z!V +yJзj4g.ZCpMAA8zB(^n/i2=<]"cQ̫5早Jr7cth h0Wj:e8C"wkqBװ AJq4s*d ȫ@g(S3C~M;FG!9gT=F#U6d9J8>[Ύ/|(kcSMjnVpȓ0VhSM3%~ڤH̚TFg%-~~`Kߓ.d0 <"vcG= "<׿T~4cL&`:b*U9ԴG 9X9H-Ȳ(! qC<% @>iM,^sC9#x2Lڹe׋K󼀖Wc.Z7Oih=8H ģJLhO:ZKM? 2@GW4יִ/qC7X"hX@dCR=BTQDnj9vB% G r84>wzj0@p=Lbx1|㺋-F :-FyFF } %!y%$N!J"u h>ޤnJ\d0l}%=1^*%zd+%z@h_ )G()=f) B'yhU/ECD6dc٭Ң&i?4cÛ ~<? S$vDP`Y^üuȡ=OMᴧz^=-)|8yTP3$bďGIwO%AO1ͱb{K3>!R،=Qٌf%&w@$m@v™Em$Η?DNeҮ=P=vTN?= qx Jy,O~>ӫ 4+j)EIRR~ym܈瞲pw+ɫ;E2(Y)|.,t{,{X/?5JIZ2a4~D/&Q?|W } t6'x;bI 2HR:x8ERZ}g"Xj9X1: +ėe NVx#|I\EZEX%NQ((2VJ5AgdS'Fq+6"}bH0ʿZ~*L,(qsqNȊsڴ6$,4 f3Pc8*/e"3FfP\o\oP il$ 6?.5"I%6z2Zu?Wވ7!/ Az'8sw6^& Fl[q:{ޒ+mx_z|n;jlio ʙb:YmQft6~wyߨ`TI3ޠr7L71HRG% Ν 'ٌ7;CK15!A*bWx6gR[G}.[o0}c3Vpmo@sd#Vt0-1<6E j v. aGp /ۡ zH<$~z`ewgDm;UGC ?L< >=%U amV+Kb>mx E[E\ xoTA=^}A`+׻p^?(D8vřJmCaiMh\%GVT$MJw {zqѽѺD8ّH'%7zzOx(5+ApRmV|Tb<k}Mp rJUD5nF_2`s$SRB $oaʀ6SH?sI~eZ)69!L? G&i.'6: 5z抯ną $bҩz7%Cl|x8061j1E_F\G{<޾`J4lÙV[q,X'I7SXo]OHK… 0Tb"DOG3@ASuw2ۿ:_FSR!⍬))%!޷x"|:o1#/:66ixE IVMA7шKDJ4R Cvb $DofƋ2Yrc Pߍ12эodNHMR8iP'odqeaTb !v&Or7@܃MU1"Ĝ2%S#z,&n^AKx Hq%PuyPqu2f}()NlAϳ& l3k;v=* fB)S3I<{+/r/ 7·zD C+.R3(_A2r :/ch}\-G8wYtRw%qx+扷Lr`SZm I\4[:2 v2ƉN`m ò !8_t/>>Y%' wEN=c&)7jzeDʉ;JT%4ɨb}}rS}׳@{X ge)~~ P;(ynB[TOk*1")#6^H~Mq.K!WeHWN]1/x{|Wzל|-7?ަinǟu_ 3򿪾@+킛!O[UZt尀MWfX9ϊ-]%Q,BER؛^=ͷkG%qFGr:$ԫe׌]8& .{fiA^ׯv/- Y1*ד.êm*'M(KW{e MF}|ۘqL~o`1\x[SO+=V$8~i@0-MB.$]:iSci,׺Di2"(%Sm#.xu5̄R \P$ '_}-~rCdDbḨ"gǙoT?jҐm; tZHNuO 9^,@QV]FI#*Νv @}oUӋ/ $0DG]O3d00yW 56c]r@!׿ &aq'I ~A4!WY>X֔i"TE|fg}{4%sAbsJaBty]V&{Ci96;ߕ-B3FX? YH%wǏԏyw=OB1( Qmje]?ABگ+X吏RD6VDM#!Ewu|S6 GvIʞ`HI9b0`!$DJ)!?vDnN >To0Y!hV%%SP[ga!U폣%(K}tlH=dk׃qRŨNs ba꿕f;Q?~yHkŵUj|,F#i=;6,у:՝m>oZߨtSzuή43CtmY~s*~u, 9T5`s?Bq{E~(B3Vi(cqupy 1"2>OGZSʮ_SHf$û-ĄܼH#-%jsiJ5q-w˨3 $rȫΊsIiM,ΏB@f4\?eSsr L;l Q\n(S18fL -~2S8R[jao!FoI}^uU6(hNCN;f[D#ݦWK ?LAL+.J ~]<(sƏŁ7P[/QrCB59胆@L7V ɘ92XX*n0Y?t"ׯi-1#*oBjdT0)۴ :Eׂ` E_rT<*ţ U뗦tO Av|j6jO$*[UZFa,7,r'dc5wK[J#]("mT0=;+%!aK 3۬;I!n{ye9&ulj=kms\-`-_}rc=qJ0 JJrX6=iwG jnZlm=J m]\_;&G̔zʜ z=b10Q^1 5䒠7:!_~ֈ۬(eB>$!݀eW K=D ";ttSk |E|N5TWL*C30yYRV;3MHT0f2X׶ E|R2yVgT*(~băHgzKď7cC!/O,f.ZXoYl \WN*xd?4L1tЦx٨bCEcv 7Tk?`R\Pl8hԢ!tu}@H2uv-$cmjQÃV_i o 8n~ࢳ_^LhнloC)ð:dx^ҟ "($(XwB(L` DE-pUM6H h'(xv~HĈ73AgPϳgdM߷CBWMȄ&M5E$*G|"I~U@wgKu^,]>=c1TH]1<>>j.9F t7UF.St 4ɥ^c;ZWlIr!F&4Q)t|r#Y`nO+OzxyZHӖ5_~̀ӊ5ΰ.5ϴȭDәaDuCf&D'9 dwBNI0 k3@%ŵ#I"h 3wL<]NBغ@5GX2&f* ΨymiT=cu՚ "~  j4Z^_M k*>\熬x-)d TnG7m9_Zėֆ 5_e \Dr=[kLcԘ`kޖ ,~T X7ͪAB}D;`}5C0e%[*kŞi8"9}7suu6 ӗwXoP#ڠQZ|R XWv|W{dz*DOm(|OR̉#wbLj>MLl^]0R|ͣoԠ a6{iw(G{FC~Bb$&0w^)?z8\Ra]ׇ`4DQžǙWJxlRz=QK9ZÊ"kFܰ0@Ҭz;:GId 9nliJ6zĽٸ}Q$ިίޱ1L-r2lċvti!SxT66&ޮ@ dHA4. \eI!y7X>2zCCL ß h-s^`+8wm+*$:m7HOڟ^z4,\!FSw> ,}naqZs}DxyC4BYxfL\Kig`ǎ\?EŃbYrat#c1L..MQ/2/a0WEܨY7U.!C? \rWzILEQy6 XH0<`$vƞ*2d>dJ)V܌' ^tx_ MӇlN^"˶CtJe s+4=hy Q)2b' s +'+n,ly]?ԷE 7߾Y!8ZTu0$/88K2ߨڸErH!B2奻w_y?3>maQ4xJ]vx9i_Qh[d ӀNB!(Ac[C?=CWe'T|R_SN˴< 6Ž&G; f+#fmYl*fI}F0ZWF`DlɬGP0Aq2LD$ĔcIQCezTQ\?-Z\`6ri=^$۟9Jci@7HthoHVMeCl=J])>irrH-jJ#9pYi^/ױs5Iໞ)1׶wVY%g'~y EYXRǗoL\^vL1KtB'x^c/rUfSn7HFpM+aH0= "CUK5<ڱ1"WI0HP 1{})e tN\$ա3nISxΖd"ެ!}A>fax ym%ӥwgnG㍸8k6em^AޗFT  [{-t`):fh'҈^L,[/z v8PbʘJ ~%]|uE4Pgݧ'FH}q+Dm^[i M{bĸfG8S'r.aU'2 P= b2N?%KqDzxVu>4_TD3EB!ctOӈ73* ,'> ;$|ؔP9r(~ BQ>&ZlwCdDO%i4Om41LX!oeU}YL| gq,jH*|rr6|?oI23!txc;Y#!)Di7A\\̫3K1+B4 Fw8q.5e ƒ'F`P\"*8oT$O[TȱxA7A|[D#n!.65 m()TEG67rLY tHIZacdwyjXAO 3u%W@/di8G<a gx%'qB1e&P_a@Ռ5s^ʆdTk\(#8 Z MGZOjͱ9-̤Sz(1JY $ݧdsct06ĉa+7~׹EK}ٮn%/؁%jLѡ)01^WrQ _qt@SPf Z_G4 PαAC6'X9gkΞr扟W)`qQpԇ5Q6;p>QCs !h6K^iSU_YKA<+HW$B;z"y$. b-L"ZZx5@aI$R]y cELaZN&^"0j ; /OCx#zq[G*PG4d$8w؅GC'In6q(hr-j1]_`',74D,M$ n%b e ɭ& >ƆȼrJ6A|'Nj՜V5cLGYezKC lIX-@B԰R |ZUT D5 buL'~^O䀦-bZmݝ (4&H,+=jq:N3bV;CDSS[ݙ)q*Ɓoupg}oW<&*"~$ N3n k4˃cOA"6QBI2Z|8VCѡa:5\ M4aΡHEn,qxRe Ej.Mye;\H0Z$RbqI ע'4UжR^P#OmHw)#ԴV,ed O#u65 Ȁe*[ɨ`Vhxc!>]?;Aoj9ҍ+V"$6ڭ.ismibG r@xixHX+f7?z!􎹣')@h+ǞU*>ϰ0r!#/# oj,|)\ $#ٯNf$*|0?UJOGq}CU\1z >ap#ǚ( :ebUp2%rMmojɐ1 {7ԴQC|>O{;K6?Kz'Dq: @tT3ʸ3!!mǭ. :+?ZB!^f!Ѳ޸Gz^@ 92[H}4q)U,Hz/7&+>w O0$Y*k^59:!|ゥ\jFo'i%F:>Rk:7d3fC~S.q* ݾZ8b)UB_Z_O4^?~x^e(A/K2D~?~, evxc}xi}Ҝvu85[$hI!~hN?vXl+bgy97l#?Fvk/Ť9x,Z[AkxsּDa1`%ްиŏW{@DNLN~8~o[_m|u͕e4tᙥ~뺟H0?2 o(1;p,C,N0%kK} Qh%Ja l]0OzonOW#VM=]_+6 Z721d÷7- P'p+n v'v=@8 h,)7%?Qm%@TDpx-_]V04y$@[[h+W;7ep}w.^S] U4b;GH}Bq-;[ #kE>BeFtpΠ\9'LZ%2ӎBy*[K `h`C<톫D2X:xGzU]:-I3E&Ͱh^2~n=3o{Ń4W!6l}kݥ ,d2ݴVd=BzC Z R,]"5i ?v9v,|^B}ٴ Y!H8x$#Nʁ4ӄ΁MՅ{a2r#GC֘d @Szgi;xsƔ\ruґ5d8\|^? B0>@QP 3|]j2rbX-%^R0~^ŢDhx^.^<~$޶PuhEU $hhoLS"f_k ^ H2Vg2 3jа:`W`B|rk0U[?Ҏ?O"܊ \TC-4~hMHڴvL:bʱ{ J'ro: %Un)cP{E 4 _~n« }~pP )DM()(_lMDQZ?vHZ4da\~4t6Mm@[Lp`çh?/\9%hnUv:T ,k-v;aNc? 0\!h%d _9ZW>.S֑nJtGVjtuڢ !RogHˁ*yS7Qqz'; ,Br\T`<\5wL#[4fL@Ymp&2PlxwEH7(oHW; jL=+?Gp##uă@Y%my}ͪ|oTe/ ]C7d(Qa!Pkѕ_*r'e{R "ehz;k kc=3hm,v Lϔk D×A2t&]"Zbw~{1消< n~Ο?G}l=lGK"|bcQ_l) ڃ?GMKPrJm֧xݏ bFP~}M9=|OrN#ޓ'MQJ⭎>Frro7\@"Y{I￵-Ua@q ЗfDl\|_w *3WR\2HWm6p2 fჾ$LDZh[.[|=(\W'PFy;c'afd#~딺f<l֯z70c ݼulȶ(詫]"ƁŽ뼊}@y=Nr[f&)i{âJ׫śdJI\)1|Rmj=ЈN:U Krx[CϮӄo9<_>Q<yoTWr".HN <m:*pooNE|I]*8~v]ls%_櫼 2Os}ח8;_xj`V-eݦ_G/\L%2R5ʖLg/7v}UkWv?5/UIG/K˪u0d3҇1 ,K_nZ6^L\(Z)=.y /ȹx:s>S D v $.W e CXP\׏I`imi_Ǩja?=@~/Ɲx3JI Az8ExY?Ea/&?W½D!׬g5Z x[Q{ۋjCh1g;'JD+}R)ʈ:c!}!@*n0ϲG@:HP9EHY:ʁW2h'ikoMx7%-A~$\A y|8B{`M)x9%ۀL@K}\E_D"X3ay #:%4#шJ@AJO&^%ߑhnS?}h[2joS#T-a4BoU}uDᓩ+_##R C ͥUjP.QItWC7#B#WRX10Ѱqx;*B"`@oD( @oPb@Smi !@\VY`r}$z9t yWWkW|kAIմi=<ҏ!(v*xʜFќb|倠_wyM{vfHD%[}͸X91:j57<60fչ}{æJ6rW$ŸZ.z0>%E f:HD qب)!d|q$i6vaB 6awlJ#0ҹj Vd&J22`d띋0޶ Sl #349#|U{.RgC6oo" :JZ~4f!H?"^Ӂ|p6X' _7> .^LLs3ccqwh\pNT2ool*RlO>y< h2$Iːpf>?mq:wHdīhK+„sr(3VsCSy8l8SāFG?|#&/9t=r^e ~V.篩eXfO; &xa>z 1G6<~2?Sd]kUS~ś2/N}Dx_H΄6ۼ2@VZdAS)w0d:PRpjDI1z]ᅴM<*(5Z8$h?WU?NwUi/x{?߷Jsd-2wm7EX[Z_|}4Res@@ECz\{f@։~Ilre <}K$\\oY?G\8KZ[fނ7  9cILПE38;;rtdq;{DQukxUŏ 3'F?M~-ox+W%MI7,9ܫS'C^W }#5ʤiJ[&D>]|ɡ34Y s̡%Emx-q[b %!~0n^QJ8GĕI%:bGnJRN:E;FcS {Q'#쐒 a,qԙj?١e'OďG?xYy ampdd]1yK>IފP3)o ) *Q<,7ŰEcXVzU?zf1$f+H hHQ gc"I}d<1 `oy<^dsc5i6 F5BLE4J(-P dĺ[%A.0Am>f UzO.0|ε59fygj!-zı U` SXp4uer :fqmK; W'YD[ڼ>B)3ѥTp|WS\J~Z cȾ<*ʀ%uO]"'ɲcZ_z Y;?o::kv˴6O@|sjӍ; , + 3U'4edWA|~эBR٧zY\9p ҍ\`Lҹu$X!4 ꮅP.pڥ #bAςf Q !@nc."#3Hm Qa[IR5~TplSNCxb8'@tEGq 0^Ou:~JUJpdS#r4 A h(策 n7@ҲuGuL 'Q+ފSB..zߓqO 0ӹ(Z7`??ѽ>^h'^$Ydԩ20Q)`2m?D'Q4al2Re;Ŝ@r!84ĩbqd$BЫ 8O.rdD@͈9ebPCqʜFP`zz[M py\>VX٤Zj*b6D=kY>k 4F+FircY"ĐE; 9L WsF1=U;,w5>kǴ}B|Bb ]⥾x'w>|N?>C&4߀ o9 0}8e0R( ^RGF F"jqDZ;č_֠ !$IK\n'|A_cWPŞRnf3b =m)XE~/j>+~ҞH5尬񗢏2\TcF!pLCjࡴQ/)e{AHi/?(8sZ#zW^5niq1\/G-x>S*! $3S ?Ndg]tj>!/z ^`U׌>M*2؄>Ԃ')@-"JdB2H4x.?&\&1ٚQL}^ْMD2ɢ =3T$z7UkArrVN4&QvLAz-xd(_2o$ c]hH3?a;-fAW(:Mem`>bdH׼nZǓ`ǢoHFU/ >`mI^r480HOԳol\IrmtLP<=_% $l| |5U@T x);" GZ .v掲K ډJW@P߆˜/U_ U4Jj}\x2;,0AJiƒqȇ׫̱C`ȮAmj%×oX- 7aBղ$}GX0+`)S0].|̥@rtd.GBƹ\ǔBL Wi"`Zi!j&/3Pa.})7g `z#U\H JD;IXTjɌgP@=ٍń…;,ޞ7ȖAwIل?2$I8# NC4Ԉ!oߑ|bg$"ڂK~.ŃI^C!*\1 K0BK\eɀTIKMd>Zq/ Bl|THSIQP'SQ?5pk%ruiyOMW%핆..3P.r6<^rt ދ 0 7m#~T (x݌0G}4i#ב&*U٢  )#1~)z`JN01E>I\?WN-~'i-%bd*@ѓ$Ƶ_Le N L& TGE.qIWywO^NäE,u cӳxxG8"7_?~:Jb٫_JFY2^ٟ,,g4BNb 6XPB"*Ezc@5yzߝ6iJ8D؋iT =PClO(RODbLfsFZ$f!u=Y@n#o0 K [俀)mi|K0AP^7 5]0hxgZqSvVƛX-OE4ZR?X࢈)޸E0#RE_6Ճԙtz' CU 1{0ނD}d+fz1 :2FMXގ7/kY8~7;$ (_YN =)rqHkT??r oO/0 ]t8'(3pN+D]Nlbp:}S'Du}xhaҏ;;U#CQV0:5*I ~6<é{U+oh䎷Vp=  |-f4j$"F)*GT?QvqK[}4:L㐔E}~.C%{c /JVQP:/0x9Fbz9AzA I_`i&;vg ŔwׅOy#pQss O}[רuvq VG#O  O:Yfc6z.٭ѐpiz`7Tjc@빵&7zb-udWkA|t)/fo*[c&)G7®PWeֆQ_zc<=붂O8dDbg*,L$͓p뻚* dp \Ve3\0,XH`"RTXS}^ j&3+E[70,XkD/\Y>K-H-*q-j CA GƉJݭpQ'|dX.1zL7#{B=}C&dI?0"X~kr'sw"6LbJNZy 3/!-xjIk^6qR*qIIx6[J+k1+4Ioo4NF*EkEкn*3RT R>B< S Bmۧ;%,B#]*I??Fy *7(4\Df66*Ua \vrp7ZxGBĵ`qG] YDU4/@ !T)~ sׯLSa%:O͙aPN ͔'nbTKB0<%>Z]ǏƕƀWm>^F*O>|)~Ra .8k>`HH M HU7RGQ~D ti^Lv.hoYҨAF!na|qWA~Ã%<eH/:Tc]Ʋ%c?Iu-.u%- !zC$`XM0-A/ 9Rχϯ'~#qW y8@$~1nsaxsEΣVp%ߧ6t[*BtXS`X_̍?ac5H2Qi1 ՉYDhAW44fjua ʮ0rb PJĸTEӇ0\(Tg!ʒKkk%84lu~*Lǯwu~"S2"e KTÄj5J7)#j?*`608|J9Kp1-tA];<`䋚DR$Gx!6ɣfEB#;姧`$(atȞ+˦<غ'rԃ B"#|}53ko'kN<;^Em|*(4i@^ P2.P*B;{+ }rV]SѼsl`5ZT֒: rs5F ?=Dc%.O`$5XdD ~; vfhJcMEY DmQ t;_]O-tzWQBՀҹ AÁ;Z" ;W ǃoN;O?:c P*.;dq( ]hȀk},O3{lt"R[$=/>J.r}DXFףwjZ,ˠS6Coy͂,f)AC# m 5Tg \I?*m} 9>=V9`/hs\ ;KUb[_ $Y-e) S3;.JXUWDTx&-7oEJH-<?!Po&taWL-?V jl/=9t^0OvnZi&߮,Nη\HuN'TQ ;JAڈ Id,?M _몿 +E5N!)@p\kRsyuASt} JCG,g^`$bD@5%$'/ ImuK 91DXFTvJ\iL O]!WNWȿ ~h"mMxO_G.WG=}$=ן_(s4$Zյ_^S"~*UiN:zLruMz7R%c)1%]dk&jKfߍ˖Mχ1qT%4qa~>L eqw,Eχ:㴥2NUi<V@OYz4Ms{O&?>}x2? \!F-\{] _F4 ;\2N?_Gx$txj`"~?^X劥"Lc[Št~Ko/DŽ:;  KjGX)9!a/o5xbeBvK—k~hztA ɶojGvׅOwp%au WI8jB{GFr~?w>;{}t.#m6P4oVZvvۆײߪN_ .qb9H' o؇`R|GI 5-pH ,jKYAuǵ J9y~JNC܂-F͟ DcU7KGpr)0yGGN<obQԹ9͒Bz_-*{|u]bZpk'o#$6V!R)BԮώ䡡?b(}ȁ 4>,S1c7F &rF ⇈ r `2P ƴ<` GT*Y=~hgUq@iČK=Pzj ޠDBS T~%OPز3CFӔ!Yyg/B*iwV,5 QIMX$uҊ:ql>U3N_HۦXiThv}|7ʒ$_gZ!ޡC|dZTbL+iد>ʗߙ$UxG?D}Tecb h@s@dBV/lN,3GzK}k\)Yv53#7 tגּ:1EEc)y>_4`XkZ;Jӛ`؉kZPW8 (.5uMFM.bpn" X:~ƈbmKj+UQj굝#8iv"ޙHN߃~j ~3;޲TҬE4-$ 6HvďHVe9Z} |5kr<ᅤ9VIΫ#~:yaR? S#PD2.TJjNg bAxvNL)?:Q%?_-Ҩ{k !~}OLG)*z?J B,i;*@WaK5>ʐ^ 磋E,E ^K<4T, ,*7Ð=$LфU/N,!/< O.A*TxTvyc8&1y'*EQ(G%[6uc/1k}t;:+ <1MS6V}d|=L{r/tI7z0Ò>?a[DMxO{X&e?k|v}};O?Ķ/0u?z)K¸ hw\b!6KC8_>MXv’ TgDqP}7Y8N6Gk{pU:xH霎;~\ck)`y:"Hv8e_~IUfyk[ydz,`+~|Y&zbW޴o= ۺqq=a1z oi>z=Z6u:^O畀"1W꺰I=ŏ+a]n.юX_]?<ŰIF9T/יL:^ͅ_?XP.DoXYGD9Q5z_ `Ht^@ /`q%@+@ .v~SS$Zڲ1f[@ #5} D/ʄ@t >?|\lEŖC;7zˉ\Z.R~2vn>]E&kr.üN)T Bsn=Ċ\_Ku [QNrg"@ \*CP\kZ{8WZ<}*Λe̮8=gN"~c#wlh[ +d= uQebIU71OݭɓXF\ Rgf׈[ a0=`w{~JMX֑Nr ' L;FYk`{U,؎Ǐ~_F2K}T:rjo߫N}Ecim,lCTbfhR\Qz \:]Dm!AF6GEod/Yҷf9}dGedw"TEkt/?tO~R)Wy_s^7|JJ?#XDA5 B3b?ȅ>C!\ ˶VcUKJ6xeeߐd+' ^BBѿdhI2qAK|v@ĽO.z;~Z>@~ҶVsP3 l 5g;JՑJtW"<٦PeGQ-'CwGC}L9.$t+K-°kR/gp7H~ղHƥD4wX33E1E񞄋H:e5?Z2~y~y3A__w duS8⇠ 7"!륷m۟ ]nVu ^Fo3f%__[ȩϿB%$ٶ#޴ijuW&F-E5_Zoԯܸ٣ c[[Έ??4,~8u[lPTS=sO$$x^-5>`RSQk":x F8H8I.8(-Zӯ+;؀V.Qy Kؗ}/8|Q(lRK_@:V1cn,9ɵCϐx,a|8zdMLD\y+4A' gh~c{r6joߵPLRߍѕ;%pq#?ސ _T0 s/>rL!iHUl{Gs}H]^fZl˷{HAksΣnGc hH( \Ӣ6^tY(zPd K i%44j r\A񏒊C17O C>kTi?ϟږ1QҰ g}Ǻ+ F?:&vnl?k<3_X5ֻ-Z35E]w[>ʎ?`4m˅q[~nwThPsTƢ1]{J^(aIU}Z.t7}!9uׯoeU`jL+x h,,[o1$(fVeD-TcQѠʎ9ts"hG"՛ZKYOYgYk·-kf.RpW!/rL_5(/Y2πbABE/?UO6|#'J)")YZ˳?ڋ8OdiꈷX6<w{2m(d[ؿbdިv S w{ڿ(0B529H97~qW+KJt]IW"qlVa3, ^`OP26:I͋{> +&@9_ ;Qĥ1kFN"%7CTBxwGGW/GO?7zw}Jx̣0HK>eOChހ UϯRW8Bl΂}B8b:띯!|^ -XLx>*;B[3!ϣ:EK N/ 8~T)AX,őyD ÒQaBz] 2|j>T۩BBUr.!<[j1gyv#~DxVuI4~j ib4~DOTmˣoOs6ʥIIk8XY֓ěG@je_97d[lGl0\+/4 P=FVBQ l⍺KiḨ&[<9^V|T Lr~-?=>(W+@cx ܴ#9!Uis8&Z~K/.@\JIk^{M&XM| 3{c bfޮӮ 1|~' MjXZN4I?A㡧K@%#tVfqGT"<5j3cܨ>-y*M=X ]"Ӊ.-!UAԜ&?r<:kɃ@]aTx9_ VwqBld!A*ݬ n!9qi?7%L$`={J?OY9Djem_5mg;v u /e5s Q5X,A= : HPK fZ"֟D}hږL+wuGMeYN7rҩaY`f%X>j4}w!*B݄2XuIywh-: !B c;%=F$Z_AM0ѵXr% `y&d#Rm^«@6A7=Թ^Hdx 7{Iά1%`(2!a^7( 嘴gP< siz&9B?jEia $pUv"@/'K X3{+ӆocIÏPW`\0GsH3ȶ\!{PEԙT;!X1{Q<ɔg,C‰7=o3°MFXUp {tJy"Z9sD/PgHOJr 95f\⡐K@)B8=.Ig@!>Jn6-F<\e98B'f+~&j5wܧ W"yܐofeF?L#:4JO 2 340u7@H_n1&"~T_B2O 1=אO,̕Z4VWsIdNae#3Ho>rqZމt@e?}/'.hS `Q i"V>bݚǹ@={$h%0 BUx?-n}ьX&EJ|kzn!fwG&MܑwZgVz<ǥ:W#V"*<,8a6%e9cU")(ix_l%o4!T쏦0U.o;Ny2ȩJ5%2q): ͚\%,rz|_Ē%:}ě%Z7ȷz..n>3E"}t!Z' V3ɟ?AgśjT( K׉/<PN _`.P47*_qXR_? yǀvOV8zT ԤxDjy,w]VnfmYE޿v7(/N4}/ ϟ 3%7{llzKmyxx(1OgUۣe5IGט%Iy?xJlMXR>vOZP/?Fon dc-x3u:THOցx}aV{ Czʗi ! Ʒ\vUg$|p SSz 6dPxʍtZ{UiI:d)9Sǂ ąq0i_& Pk1"yU_ sLk9P~wPѽbkD\?\Lz+Q&~Ϋ+*t{ayGȷCaVԤc{|q(֫~67N=ؠ,M3ˏ,4l](|k4"@]qR/g*fI[oG5$l=2P߸ z10_^Y_le!!I@(Pg|$UHؼRԞM6DAу~Ph(CO\@x@@_={1d#+$T7" ئ2 KS Ͽ'AqϠ/ RL72.zɗ w? UMf8S;Jm E5lo2)*{2ƞ!јexB65~条q*HX\Zs%\AQY.@\dOY#aUb`A},=Hځ^!& }=4Nd@5B#S*E+ 1AhmTRtG<G8ÿpMdHm^;u7gb;ҡ!rFH7L# 4ȳJgJ E"Fc$T2NrHgBM+sv hnS39m(WW~RaH6ɔK5PAZ{0lѪ `֢,4IWʽCT22sQä1͢%?GqxWQVC2G%qs;K@lvv(^lsχ$pS9h}YA eO*+礪pDrG|i&0rO;Dos>/r M\4Ă4 >~Uafmj&zkR4G% -~$-x#4JE ҏ:#C_Y^'8@H_f;~<7_Py?|?(&REY:ղ83y5|fX3@|! X}/r ʭشG xhB/HU)p N?TYA{<|¹eA?#7~NJ eԛVAO)Ktڃ2##W!o -AN83UhT#wT8[ ѝQ\KysCDª>zwژHII}fಽv}ZRqX`4vrFBE{⸩\^ڻۮ*Ԓij\]!v@*3!=p+# k.Eﬤrmq?Mׯ+Tnɿw>.Ñ/jm^q~?śH~ȿ|5 [{߱PI;HS?%&~B϶_[Z+TX|[wۚ'd\;~zfO z8ʎ?~]i1ԗt̳K[aKotŊ=j ŷ7d]omFS]!Jj%|y9f"ulZ8hM+e ˁs1>v!%U8h5ezG8|ӣ~ʼ䘜?{߸{2T=T@2|;z ʜץ]^a(ïWuP#e~YV5jV|ċ&Լ"cb}jhuX5HF(Se#L- 8|؃GQ[|2{rKhNoݦ2QnK }ե`B ,k0׫6əMlĀW@m֙@,gjȐUli+x+GiBun&>khj#jeL:-mݪaoK4żˤ1-za3Urڲ;ʦÔC{ [}ďO|9V}<>KuϏZ>d|cI6f)#TsYP@tjl*`GUڛ~g@hxʯ]oz!~K[d ZMvȅiƴޛy"vݨxb)(SxgƈO17;w/ϯq9e[8=cG<|DP0,p@c%,`mS >Bd0 ~p j1eV(@Ro 7܏egxIX:79˃-lnH%d hNxnk>*V6z>_m|T)qskb;Wa<2>@jXFv0Ÿ)ԛy+r8D uw ɤ_ QȍK 4UG}Zצ#c񉟖[F-%{t~![ZyuN/?gՖ*=շ@5 ::yuB4|͇Ǧyup5tyu7f5x8o%o2{4i&͑Ύ{{{Ö4mou[}]/{`k2[64?/~ߊ7 |lȅ{xcY@-L'1^hYu[vFD9^M@[se{z3pY[;MvQt9x+Ės$*),HdT{)Qt]'jNN&&$YH~"4q-qʀ,g[o5.1rs\W 'Zc%ɊӠŏl7].<(#*Q %ϯ",r~'Y(uױÜVvVIxK7Kn.j 6*:Ek]NEAH=1^rD,` #]Q~6^{Sir(H*lJDal#L+%D3KI)jTxxn"'zx솒[2]#\̲ soὑʔ7O6I"+ɓK} oCbS.K}OWޱH: G"Qz]{}WQ^dCǑ+>G)Pː,# G!$tg7`DЗ~Q_uI ry}2G??QNsn^+rcx65djd<~[g/hjci\im0HPpKKvhȇօQ u:$!3{7u^VuL^ ~k'Iaַ`(Ve@o(ѕj1F˷ሟ4S=46H@eP+;`Aܠ@azh 4C!Sgl4WWD[&:A?Ο_W?gh5-[_[U{3}}!U/h;(*87jBAX˽^WS/koLL^o5OH~h7ԀdcfV_>B?_Xo`'OUd#4h3]4 P H3̘; ]aIhb (=7>i#T9>O+]Ewo:dO=*'EH+gr^}T>m^aH9"'sD9frw32wŸGG?mb6v}U=_GFV8jP7g'W[?^U((?LruX =xZ,/aCÏ+,ڎ+qTwSRv9fӂ:A oیA %e?]"Y Kc^ԻSŁ?vR!Y t]r |Y+-ql&騡_,1 ~(ϯF_Zs,gaIy_ȷxbn *ѵM0aՆ-"S@[~}-⣿T?khgo~a+\b]n[7hy/+FI$YaS  ď?F _bzc˗w@#Aa Ϩa^.}=v@{O畲+Q.`KRfyD|qօեmۑul?(x+CW|363zhJGTivw%JWK}'_k+> ŰQw[{" 'I%} Ғ8Y®,J B;rzyL ~__s%mO!Zæ>/G `1^/'\ >΀ADkƃgw#"˭O ǰE}햘>Ƞ9(Y"d];)ߪLeK6GDhlkTᖬ_pdK?WH$SJX!,* 2`b$ 9=*E2lCwsu4%NCE&=S̍ ﱭGے#(Ucϟvv}hUz/֦gr>P{8$m6s,L 2Npy~|dc =,N -w#A)DldcSF ݓMk- dљIz4JEx{pKT;,~f?:)2tJ2\Ύ",yU/QQ1Rr1_\S0@}C]n?5 RHiN y_y93xKMT QȯƮ: aSu@(Z;*r}(ug%ۯAETۑgG,_M5a*^oh8wjRV"@SK<҅5^v  Ksױ'0j򙢨ä6>@ʻu\2+|?.:%|@c ȄIJZB?ЭJKP]WCaF̈́ȴt7 TSt Lkh`M ;1٣ E0Ys,#J;ϟ7{Ēz4CIFdzQ'~p6v=b?pZIzŏ"|$KWsuv7Bzp\X dS8Apl`31xyL1\(=MV/*"X ˁR4϶Q;rd*[ş8EO.;mt e8D蛒y EYxɈ7)[?IHQH' Q?" 1F6ͺ;2Րofkޫ5/-2; >!Šݠ޲]'>]}@i 'J/ /r$5idmsf-~ dIv,iؒ`<"E/'?e3,<2.҆#F!M#@e "N^.OB!ա̠詁$ 1 [7\`}ڲ ~O4 )ܠpz sxȾX;8\1"}_TrJPp[::J\xk|>"D^eKGw1IA5b`M}>)˰;[M}>&B)tV-*, P̂5|ـ0^_/DK6mP͇4!_W5գSʚ~NGu҇= "ć({hӷ fGh} T[ jI?mhɜ!AUy}%}tOhuѤBgM͜+fu>X*ٌZ/ joMbU"EzIuQKUx ďid-}xgrO: H B%>j~mW_5M[`!~{HPC]4Z]\%SfVȵJR FA&>K\P5<?Oq^fPJȋmrHxZPPHʣ-'JY}W y'˵ѣ'zMV]ApŏAo)?f|tw(G5ZS'͜3rc ցQ>m26`[5AYFF x$Qs['g ͟_ id܊-Co *_ƖJ /T6iOWc%VN zCTLC?>*wg#wkh.;Zץ=A+?:奴-x!Y}JWc7F=~1ܮ7rt^i}͇vߚBN68My]_Ǯwn:O?sX3/)%S_~QS~ HʚlQJ.e8ĒtwaDVŋ"ɹڊ@0t.ȥ,!iJŖ~c\5y^"YEo=uXy3CHhj(ԮjβI !pa7Ls}]x쪊.aPA-~3uL:jK)AsFfrTL%,h|F>gU!Үv$չ8l(:[.JA)a>]*/ŠLBS$xGiV6⠎g C^ď]sAx.+ AqmǓ;@ h8{:*&} Vuϒ SmQ> GxdvÞf{>ƃC5.+d8%趯x<`uT P&tq4&^tHg2Ʉy$N'8ZlPHҧrUg~{r!V 7Mm|LYInvz`f0[pA)8|9 ̈{3D($js!PJkO*fJ}2w]`0_x؅DtZy@S϶J!TJТ?qBZ9R2CQ y_\3ʸ]<=_cy>C./QhNisi>#Hw,_EH[b^(.)]Ti~{JWy` &ӯ<ˋ, ̔ =8S!x"oَd:u=Ε@XCIAhqK}T065r 埧ɻYdڄY0HjFc 1}(/מ*։GaE/PA<>x@ %nԙł^O 象-J Z^Ps)r$ xu1Ӻ=0CfԆT x0;Īw땞M&FCghTl;[`^B.meS-zi4[s_hvd5mD>#k\"uӋ.3 -f^0m.6Hۘ; iu F`k6 {>b@+z/pT^dr,$;Y'3mD@5۫0~4h1\"B L^ t At#S=*=)F+%ѧ,HBK΀cG1}|f(pJvP<f7Gx&'sk.eI+|0 5YbB3v4yK f) XlE3 G-F5 )sR('OkBŽl ҹg\MJ鄣+JR[>ϑ- e:b%@FZې;譔ؗUX©j8_e;O1^La91_E Eh/B2ߏ(Ca|{@O֒9k2Qx N*UK 4P4lݨcL^. "FQ_h+GSzߪK}D3 ̚(+l%.kR B_C>WACAbCyLi7NcVs lVA6NyQ8N;uQW>oOHoPyllzV4V*QnaBBMv&HU5sbH|n~hT!\R%$bPG?=&"a! VXW-"s۳Q v"To᜸~WMg}tn.dnDGUzXS!qGwԫ)t bj"!0Q)rLh~qtpm1sҙ~dϽ d0KFW}G}}@Ь0H~@B+lA R&o,LiU_jņ/B~?7eN 9ϫD!RT~ᨡJ\]O\u @>i( !#bN,3'M5_rk+mQ-6[==sCXgG|aJRXϏD=P|xmM0O1٬x Ϭ |)v8gr|I%bd`*% ac.Pc!B,~e'~ArP0u@I zXom ?:~&f:h"|oРdWƲ{o[s|?o߻=0ϔAࢹ~y%S8 BLm%Ci^gV|n#x,w@Y A*,Cr.]1O}Dʌ__fB/3j@Gϓoy96V=>ffƒq,I((#6nv~'2s⧵ d<&k5.o/wRR5Sٖ/Gf+7q'Kq>EH8V(}ylژQ.`Tv8bPl 6yZ)J+C-ľtLbzۿs)vSlkAv|U#'Gl<8CϷwFB5cp5+u$FzT U,SI`kq,bZU߱&]jMSXxQCPnlֶt|utဪ, 3+w=2iQǁ5uaȫBߎaeȱj XfS3(.T+0ta0 ^J@fsh+ҧd& a_O>P&T`bo2aE,0(,2a_[+,Vª"Ԋ*Jk8tgHЄZޙR]XzA L`u(xaPp A VjW91n)u(@*x#d|31ذ=klcKp SL5j58KfIR'lxRygS{-qba?Bi!)x6_̡䌮=ڞDHޤٯ,~ =nh阇)6c(:@e$էMPrHFKP7\ +UmMRg$"ְTqt* udC&~lg?3r:QQiËFio-oi4yg䑊)HIJX2(Օ e>LfNPͻP)Gj࣭y^ru|R8V<|WTS鹣rT(幎P>7̧G;茽IKU = ڡS 4)P\{@0LWELY6#^]I2 c]o̊UJA R s-k2 5O7tTCpiyز7'>;?`o79 @jGRGG^ҷQ8Ca%r#ņ;uxVEwG+k $ޓÑ{lVs1f+ )7n貓;ǿ=;il6oa*+DCh(GVokb#~V37G[BbODxw1<Ϲ ^үҮZVzӐpp,fD?K'dCQﶡe&9,-dkB wDžtq> L;dgoA[6o L MzGGE) VyãCQAh h%b:n[r?Pdؠ6"b&\! &TN+yJT`ZWXjAU0'Ge4(-R(8^n>|C29xM x~M܏V,`%R%J fm _u6 Ceb\+8ҋ'F&Z*7&rC#xSJ;Em7]ˆT8-_ioG3zWSC ѱT~_cI<_RAO>Z2vn&674p1m.imen(;M ݄2 L ~pyK ,uä+rC9ʹ74|;lT"Wڗ(CdAà1pү } ͒x?9v24NVO*%VLGn{zX#K"t9?l<24|SGF@#ܬ>wH]Bm-Vz{aY!?=a 2z'qT S( dk}O9L'':WDòi81A5v ˺2'3 Uy 1;Ho zo+)$o뮷K~pϰ/Rc A_0?bSM=>-ǧߊz,MV]x dq߈M ?} c9)Dyw[|w׻yfuM3ƅ=' +ԟm@D_#|#12:H U.W ?GY i/PukaF14 rc"nz?R|cׂj)oq3b[I}ksfBYJm\yf%tA[A DޘY:!44[qo.wP*hXD6|NEGyW"6(VHՈ"jP.^R҅+!#éGQ*=fjT%qzzψAߔ&8ePTͣ$*@EOe,Rbz/КP{aipXA[Oe%1T<Ϥ!N1_"pM39rGLJLSc&qu_R?QjeөoJ/`ڴ=6$M5>m>҂GeѨ<+hGa@ZESxGX-[GΟY?;5dijJØK 7XLSX&]QWT* m5L!!f/ۏ.fwNJz+U'Kt]޷ȥlZH8{!G8 8Ε +^5#a(֍xՈ|.1q|[o097<:9Ҟ؈5w~d3[H3:4%SOxk0pzi~(SLOR)5ʍbD["ٞ27IX;eo2w # _{ fH_qR R*0#;1`5^:3;dW%(?$2])X lYѓ~&s6~Pch6Ojz"ai\c>COZNBAA ^:(hQ60D[ o U=~B0\@ˤНgG>w(+}Ldz?4G< .`O[ixԦ؏FoQviqQw?V9ԇU_0O*>^J#`-Ms>XE`ZB$TZ;W/uPT` x`oiH (F92??|&YAD@7ZiT_;QW4VC>y-`bEf?yd|);A3^>Os&(f!o[}v>r3 $ bŏ[(bhwϑ S=ΉD~t,S80͌?^I}n}+.qZtd> E,$jřq`JeYfsc"Hb[co=wR' ?V)Y,Љ?#`zb_fsSwԌ-۾~.ׯSRT7LI.qQN`FFMp[YZ]g؀gIlYG-țr%LpO"4.x?W+Z`2v)yOq/C̷C|oeG%mp@,[u0X4&+'\}?<  kg~ eݠk88 j]ʷ/MT<,x?oa[Tm9~cuQu u3~0;bd![!!GMיVpr)V6D}<Vor,!JH_?x'%BxM7pypQ)W*xqv^b:{\**ұgᮯ^ƫp _⍾n~-"T96Sexy4QN@o4f>c 5"-,i~?R3ppi-"zdT-)TZ[a5P. dH fshz\MLN7MPS@k|D50>l1Sx󙭨2+MѫIՌcS!/ /א-K, )m\,Sޅm>Xf ?#7t=,$[!\2ne=Zí$2PV0O)m ^eGgJWCy@)fiyFxw/''Qc2 CfCm1AHPQ苂Ǜ%= Îk-t 8@=08osQOAx8D r[kwna@H.?"MjPR<| >"kKT M&U;6pA1Ox|Z<_'l˥z3X ɤ RjgOx"w'H:0S41&hL,r [J~?J޾sZx4 ,aMs_g5lU+**OC6e:EY4u# GRXhkg2FtoY]%~4 Vb2U2#AlW?dƏ۸U?'6Q&^큣r  a_HD8#-hDP㇊7qsxa F R/C`I0֊:zFiZmL2})*E_J5ݎxcT͡~"׿C&EO~L{GA5Rru'k'^Ihz;Q~*>0?r(Y/c]^,<=F<Ƿ{ ` 6OLlXW`vd)Ovؼf_`ρ ?w`=;(Wj2mta8:e Y aZ(yM~ܛ3Wv1|m`ʲo{Gň1#P)E5qzW(g ~$?Y0H]7SR_WDbY*zK}du]u]Y_>iKvAج@I;n ȶJKj[uͦh U eIec&@}QE\_Xت2hrث-m"d\{nV$\7ɐ4I\u -W2U.zX"ŵG'T?%91򶧟iImԩ8Fu6/7EPZfa/knMϫc6@q4M?Oěh'Wěćy^N?.yca ,1G[o%2?T?q7[A )lձ[f(G8?MP~jꟇ&H8` 4"H0\>%?*̦"!s.MbT¤t 8_nЈmKG^򙝱pvj4AhbgЂ=@"Xh:w%@7"˱){%lyκg{e.wk}OTbs3paXE})pTIfUK#D_8voWgɁc+ev+tP |k6lԥz~4Ҟj%D9&>]+ud'85>3[(w47UXh4߄:΍k 2*Q1ws-w?̖&.3?r,u؎y^Mgy1x1h͏Xq-f^ޢ`21NB]T* ^Ky^'*8|97(iJ-/qްiN+uD?}Z%lt'U69v_32_\Q #9`-Q:5]s82*(3l5M yjjlрpsbm,݀Kޥί5C e,9i%X{h`ENK;F*GW}d_YB{G~!>T 5ԋ7\u6rNPP>BDfFA``ٯ%k\~'|8vet-&+wE )tQ<*.Q>#͒&؆(S.<VyP`CGI|Vp-t(zJxxsEs.RJ)jqB^~%Bf_q[?_#InS/:w2E>,P @Q Q(Z>sl6Dve}u^q-wIxaB xTJ1o5FeA8sʬsJD#wMX𮯻P2NzTƨ۫>E=*Qe7|bkm=EGA1LB;rbjC:e8,$)uDŽr\|ܪI^JIv+-c'zk\wg1ua fZ>u64nD{LbRF<^iUj-T1 W`o7[_?˸7ORF.\29p|;g'5^j@OLg#\46)%;pr~#~&qIĴ2+=SjFCoW0=To&_`eDF~@)H9>gfĂ+ꆒ嬔M9=grUCH(˄Õ?WQ" 竻P;X+l{zv4RqlrH迫Oèm)042,Ӫ]('rs(}@QTS`XŋM~Cbi%q$,Iܠ!iRo(vu#]- _:Aat ~HG7cE,CnYȵGԽ=ڟoꄋIH@93劖)D뿻N-[1wYE1 nְͣ7B9l f:Ȗ p Ӗ"D႕2*N-jsPȉfqḁx~`KY[Q`4r9sXxa3=)D}^Wż p؅[1zwpO\?=`UtX^xÁڀGffF`]' us$ћhQ6a*7QVm( /+ z޽}(0:qp r3XE(rA1L)W%p1H2X|e X#`S"HjUl}ceh}MDN(p( LeZ6K(ګu|:a-sxG| 'xΧ L:MfR?U׵ 6k.| |PqcX}6o>0LJR)cg>kw 8\$V$@TM> QDpl }#l?3ly+|s^Dxܶ!e|֣ $zKRaE-Ev{eeQ-t#D}t *5t*FXXn(C2T!n8oO% #] |%ac)z娏gR_W.P|Y-*_lbm0|h=6cLta>Gi&C{RN!NFld!-8?$%i0$S5fI,r~Sg-swbgb0}gٸeo:>P=O`(c3kK2pu(JP d'G5/VJM_6ؐU!;:`dKf!^~dp> 5Sw'RE5fZ-N2MLl,>"lĆq ,~lTPq'n@X,>Vnfh}E SQk5ʨWĉи[e8ccle72އ]2/%8p1p KyP%\sqgI۞ # rt+?x]:.eCQU{Bj?`3y5a; H=~(4m>9n_?Jn4,Զ[',Z!w=AvDb76$^n=kCY Tnr'~=0C6}9(v,J[U_uFkV+/Q̠~64`vZ 4ZM%Je[h46W{Ch9I_F<@4r_qud4w֚c-耕ݶ]q<=҂6W>Pُ hѡ@J,qU>+8j iYf}=ѡ X}fm#B$ם(}IHn LHT<~Mf񣒸{5DǏt(Y&C@DIK:̾=2*x錟dRѱy? (L?(F{)a# <oFQ&YolWw ߲͂-))ק%5ӡ?H2Hyc~wkr/|VdlJ7}ܭ)>o(Zvy)GkrCVЀGj[$e@ԖMO%6zTݯ&cbZl1$HPn\z{?"=Q4C6pԐ@ۋѦ+*?r_lAsװp.T ܧ)Jس {8?Gծb1P\@|jSq,wl~-=fF}&6ELWi{CV|5rw``>(Z80Iw!I1-2qɽkP00´r^8O{i^5&1 xOӼ[Z`\z [2z/g`AͳOl-V 4f5.\V TJT4f3OReVH~L@۳ٙz~=d8Ik۪sFf*6gLC7]?e"z[ICOF**gIMPpbkCp* ҧoyXCrrUm!c8b~u/x9 h{mSG #[cŵƛ'% @mz{MRa԰J_2.8nSG ؾ9_w9[M^Fv|`k:<~niE(zwd& ׂ`U[fy< :u4{WWz 6o}sCۮo轾W]aR9D۞SuNNZ)ϯ6rU7QhhM#"[ s%h*&U+!i Rnw%]sXFdUL䛾k7xcrK$ZrF@u9OV[\)Xݨ1 *7䊟Ł'y1 _bNsq,o-ReHV[ ig@KS1ln2Jx1]x5'9k}[ &1$";XmU7:"QJk3בQQ93 B WR='ޞ N&`cO6͵+@-ʯm[ƏkOʾ9DƏޠr`=YTv:<~v! 2\?C.PB {ooCgVθ5Jmy ':e 4[g/_fRG P!k2 Y:~:3CXY0F"Sv)>3PmwP8 ߯ ̮lsA!%6]yyZ`6tff B?j+u1a*x_v#7^x/ѲuCZȌ%`3_ÚYv9>px$d#G}H "x-qWyQy㛝G:$ߔ_Rd>:awVkB^*TzH400cH C{PxΗYPG}TZq^\6z',ꮯ4xΣ1(P<-[B4()TSgU Ѩzݩծ_zio(44o~YD1aĹ^_PL2x|3e'iMx󁶴Dž?ux׺DU7 Sez#;xD^ik} |\/G+&^pZ z>dJ}Ye-EeeŗyN~5~d*o}"4Y6}vr / x }/6U~J^1@B%_8 ?K?ey1|Lp=A1p?frηc?9Abַ 3eF*x .!^GwCE|}ZG q}NL|ep^'_M\y;X=f+S6vI5m3e|:Q TDgy9>Kmj5~w"`|eN/g/p[7_k7oQAh~^?h }uJd@mmAiάJ4~5D ~NoB0UiN?(onXo}2Ȱ~7FQ|T:K4DjU\^f,haM?8xy͢ꤠAHH)b;6Pt?]kHQBhFμ^jr;LVjF/%?yN^0[jP"]݃eN%Xf0,?^"j@0sGeY* &0dO{W2}MA@uKC&(O'^Ʊs.o< Y93y\{~ 4y=?:ܙUE> .|@Y_;G1 ME1Nv]dNBK\i$M{zpRUѿTi7+r> ӳpO%GZ|:<$}0뱟jvuRT͟EK'P5QvarWK`)LԋrQ:l eS{%4(i3SXPdʯ};3Z[?soY*RNxBTG^ dلR@^s(N־~^?-KookN<ǛiOjKzj/5ϣjXryF#)EGO"ã TZZIDE= H=&tNEM A_(7vn vvQ~*B*t,N[/uEC?`#B(׳xɧ ~c?YQy #޴GGOp'?%zv=Tz#gI82fc?QSyt]aɉcC\ RtƳX,xQU;@i$a@A_Zԯ7{aƹG <@_d@ nA( )NC Ý|0Ε؏'Di:3?/w9n:(sG"5ޮ9QtoB޲p')~e!.ezW)MS^ű:G֩>/wBV||ٯKC(x; ̊NfqGpC|?/SlP~@= }:7[xqIPx|H ,U|R썵%ܜ̸RTxviJCs1FXg#PWÕxێD扻afSn| ˁ'o|oGP<73!Ԩ%-q\/GHSpR/s4J qb(?1Qy|-'Wq7T[帶ܮ^aELI(.I؝oJhz5孛6sDtdB`XflnYրE;MÇǫm,QTzb~7`YaZt@ŘWnp׽״,x0>0 pvBkxERH`e>^zD],e hsYa :ƥ[Ӽ`.Lq(AFTJ:r cOg(gfsA?j3Bk|K/]-i)y!+98e2~3r7Z?1 ͬ` نQlϲqU<Ǜ"055qZ?Iۣ8WC*C3fD﬌NSQ1GuěN#mv Q2E fHqNQw~&Y``@x 4Z!ˑT͜Qy j "Xe kanr\xḝT# CB!``XyrW[QAz ^wG}")kxķTk{Q~pmqD+!g&8-߿AŠ@$:2vSt{J uDO%>!9ъ\VxO]. 8}+'=dD<`@)+hhjߍz{z!u;n۞qtE Cѓ ~ǃB{rKlI,+DN)TEnK=j<*dŴr)b U]OBJ"*%'qb2c~޷8)q"gy[ET+Ӑ]G7Z Ae8su83Ҫ&OEaǏ/,֊2 P$B#{k<|R? 49:I$B3݆m@3aή726 լ0Gi8O=G6c \Z i0zI[M&[.E@]+(%.P%v' _`"Qߧ"tC\vb0'̕t_,RSnPsg0~j^g #l+_na0/ H|SN0xXXa)ɂq|/xz`pOa“"gQ͚j0W5΁J1eAs%ÓPV o7;20&p o.fXsZ䫷-ZvOzpؘz'Ǣ<+HY5o"&\f<.}.N~dbfvqz;zGO#np~z ^ĀS,{ :>!qd=b(ζofLT+ Rs)'1 DA-j{|NQW?ׂ_xݞkjnG? l)H/%Ώ7X]#F}6Q|(@wCCҥ^z0z/?+{VdVg o6hC._=7;OTl:ρWl3n7ܦKaYk)89MFB5gO>}53l?*uG?>3+w]ǣ>Á(G&(;;-/,L=aLul#~~O<uQVr .sHZ}G bc+ێCqW ɘ$ܕ1>/gNŏE_oinӡJԧlƱ$hf}[o_$}hE($ZܮTda4I {x׻d|-~lGL钔pqu˥ϵguAV?8^*ppPkD#㜬6.+w01Y*aVBܟϯFK/8`&p)$1SfxgJ?鶲/='W _lAwګ6tU@$K ʇĆ֌-W%,W9[tO>V ! >Gn:1R9F Qdu\{#t8~JIIΒGcBѮ\R,A]U߸8cMvn=fw#`#~ԫD=Riws-sj d9^~ %c:% `>ڡ r$O xӤOQo+$ 4gxs/DT<0 .L8ms.`GYF?Ϧ;s`>sʏb^ Ҏ$53{ll운O[ɔjjq&s8 z#"L\RP\ ^)=LwiJy-|0|o;~ɵQ }`0em4S^Q7h3Y)4.pq5|RQ8asДư&V`x5@&D#oLJ˲ٞp>HծxU~F} 3|}}wF,G70eNi>j 0GPZUKȥkt`!NIMF>qT+fG"qoQ{GCYH}TVy}]RgPW}Ra4 Wj 2FF%m_RUz^'_[n Ynu$bzh"ߥJV"[:X_7v"ahaqôPݺD]jaN%qBZ9#q ?r: $x*-+l/4K >c\'\~t >\+ !oCE@vL]?Xre?Џ4u`8!ݽ!WcwT3!ՙ͑msI /3'42 eBY_8m1XZƱ'ܘ %0]t7m!?(!TqX\tJ,ϗfa*1L-8$>G/|G" a)prhNS?nPhcTNz$8^?''_kr*P HOU{HH߈ݪ O9:a6c Wǝ<۴L٤(A? dyytxud֭0QM(lۯ)FDD,ZԷV5(|26WD-ۈUi-G>7nlM峄(ԔRq [}]V/3ڵ?c;Fݦ厒V>=\~1~ _nbM1DquXY+}BٜAS9= ӣ eHSs FQ$Ik.MM_x;[0Oq4A?jB)ɧx13W{6ocS>ݞq/^6ExL`;CF$ֻn4I޲_GʭG;OKD7NJ-FKM%@] C[X@ ꍆ}#@* u M*C; ZҠvKNXC9c53%jf2O _}#-U>Օ۹§7v?ػBtt_I68<,;.Pk.̾ma8NIJ)"N;fd9.R9Usar|X.q =oe hp띰g)%YO-?yw\T~~[h=kj@IO>1H-ypu8Cjk>CݻF]_wV*zT{Gѧwѻ =n,fcˬso jo՛6P,tgG Q֗}Ψ^18hh`U1|FkA\D'#9ȹ%~L1>X" Zٳz`4ʽSUW ?؋fL}J(vEMCgCIRșlMMߚ6QѲ'Rd%MFy[̔-Srίh.  jY 5 uYw0SĄ`Y |c|wzCI#Z*9]9mB';}$y^yX7i!Ck%_.SD/E4`qbV @Č3:뷉)hr\_!ET!^y!;p$%8nHe@ڔ>'6# zGlV$iP49|^ݤ 5ގ(Wo0hropۃΖ fZ#(%Gv}MIϱ~:'y}eCZo$XՎe8ZL5}S L!lzTH"cgH3nx&idh}Jό(<>L#BR+aؤVdIח2(+q[N(~'m∷'2ARl5\+X- S@=JI'NbJ}kv9tӓ"7 Xװe9j1x2_5PU'q>PTQPAh(H:0 uVvV. bƘjDxXď m1 9(C?֡2O 㠫EDum]|I8s7G_ˡ`xn33"Q%EyMB G[7.(I{&," IݠkcCO9t5ᅢrkeG-aV/p>^?o_"ǔT[ ?8 CC \gT l, Pd3{1'wc@"!P}vo`5nKVTSCHn~Z'dLA,⁙Ĝ>x33ei5kz"IV:_]A (BqX[Kf w"\1,VF8ޮZ'a6*K>crch߲5٣8D9;vօ=͉j> sOG4pVsZbzB^`vUQ\E{7'5S_Vw-l,iÑEEHoYϿqV]b!-$jm7#.807Zژ/5|QMCo(ܤ;iBHO~sb:د gt/3 ]_ @RCoc|d?>.D~NZe @Uj(*(͈s%I!u U^TϊSzpk<#lYa[0iO l\^jixqp'$@ҭ%Wf !jďގQPz4_?4@[PN(ĩK'>S/ۯaZrR,D` C H*xhF? ɒ6Dnrӕh])N)"mx5w/?1¼dGUT҄Ql)qs_ża6{Ƽ3<ዜwVyv{CL;\JdD䶨hbr[􄲖 tAIYJw!2mF0lac:d+JU\Qe=`6^nzRW34O͡􆅏G?ugфjB?)?"QfCgof !a̪pxg@X&BS.ÑY_{}>r6ozSB:g}uז"94<&eeWS(T C(/k~E1?։y!ʞxfN[ K\U]]p&imJH:l)QP0l! lOh%N?P[7w=}0r} `w}_=^sӳG[US8A8뼀3?[ya ^}Xޗ*Y'E/˼G18p6 T˚5y os~% xc<ύbۥ(q~\ȗ'KXaR|N׳3=:' 8>!6a W ;pyCwx㢥?yGq7~GAo dž>dNL _%kIip8Ca3=-,\s3W@1B?~UC6ibD$eDZF v;C^8[Z-Bbwj&oO 8C]m\E1n#@ 2M?̯m6 9ۈnw+o,LxC>.y^-p'Ck6~fr%P9P~WʎE#$2az ٯ!uoDiPV ϫ~lDr .ʀ?U&clp%+X;bCDfa*8ihv-~D5fqc آHo ħƼ =lЦ<7q4XF 0V}*!9#@-׭r^܈R󑊏~U55IQxy ԥ]=aXI:RMX P_WANDO!|u=Kն+8#zJ tFǣzhD0H:P).ֵQ: "EOлݙo[*X޵&@T|~2')-~,0?$vhLQDӜFku`5!$o,1c%^zUh%Boݑn5LJlG `o͟8H[mfLMGNvDh||!G}ϣ\mI;btD 1\ eq"x@T}{9R9W? ɢ#dz'1TQv!r;dHu|չb̾BW[:꣉8p LdbR_fiVМjN0̿ O!q?Đp'DQw@‰GAy*~|mIJ!c@P}zt;ʷ ލKאMYP'ԍ棱0zP Kp{0GC4.-S [~nhO]c*<^!\wK'- jZcLA8xH{p YTPyyd%+'62C BcCH'x[ljZ+}߰/__^.}5<(Ű?<Sf@BH] rq%m\*#۴$|$l|i/~ ε3:smMh]g@9g+~4oV^DϯҞCNv} 7z긝oBzj"Ϥ4S ݝ="9r `hX`H|Gܲ!ci=Ut!)j` S/˖B#i:\8isKlS ˍ}!.ִYUY/4>wrn{(QapJ» 됑AA5SO*N^]/GW'ܒ U>Zn*uPޫ p35J#[W--oc1.'AE\;5Z"~G}iŽ:uo`r\N;볛 ~C@G v4|jXBu/6m< 觛1ư|9;0ܣFtwCվ̋.ܸ0BX=}Z"M"h a_c4Vj'I踠rou#6~yk N6IĈ7OT6ޓ#ޖڔ<`~3 X"|zrnpu򑴟@@K/Ù7oNmǛ䙧x}kAs|oJO{(ۭ<=σիWjcqʥcΦI.)Tӿ$۱Y=#WDgМIm )KosIɚͿsG鳰٦=QsW,tsqg zQ5pIż ]tmZ\aHC'[R }h09 px"_W5J*]"|^rTN6^L~u)WϻaWENjS?}8# znw ]!kD)mЛxЕvu>/τWw7\'{ ׻E2YMx~1w-r3z/"!UlêW !ok}ՎWJs'̎\ Xm:M*$:LI1?TW*,먾;[|ď0|VχnPѨK?`Phy6yҶ0#-o-h t =4; hfBkr3{)<‰v/ ǰ \^})PYz3׊)"%2m@=*"oNe dZA'd I•йz1 _ְYôf2F7"`7:}pMT{_[ci2t ͇nzcL\8]} 'o<Бu"]]z+?oHG0'YMқI̎4!mn;nIH EçTD]t 0uFH b$@ȝJf |e t:DHX`.úJ[KA f8ٽ7q#,8AGFA=#k/o]y${˨43jfTN!wHN5-(\*J0D1i*#垜?Sick֬z/[[x %t t ֊im3=[xp@m۳ m^EAFr6mw"猷H^lr.3E%aXRN-{_/9cKÇ<y՛pr:?s@k!<wI;Gx/@=~U?9Yxئ$S0p62udH6B:>8ϑS^4)ZCU뀉 C9K'D2b|t2VPm|l9gL;~-@Xİg;lg,oR?̀ - Є2^0aoi.˛3E.voc?\L7}23٣` ց=z`\Adн%A"7toCJ F52nFctx7Z3Pӭ2J{>vsJ-|% ʡ=OMmQ$H=HdCE6h)C҇Fש, ónkL@~ŎZB jZx딄~GlZkyW Ǫ vmNG,5i4?SGk ?y۔ ^sxFOR~(]Rc~My'Oi^P^R=^םx{hG9nsdR;\e: Ќ+=mCȁC\hO(qH1B]"KcXm5Sl-By٤'Z|@xyJd! Yg&E'Ke: 5a͘.d)W٠zܯbyfw]G18 3^m3;2e&fך_t)dAiY!ck]pb^Ai^:a $kuA&ª+R}C3iuuepxAcY") sy1_ UÔ| l Sd++j3cfo8)/vH4#j|yWzi5o8u;l䐀@H?gp%lQ l{OC h!_g[XW6Z UizbA~pӦ,";an&3ڎhM&Mo]+}^3*͆^]RvSGݑOB1413~zv72`B-/W5[~7\^uuMq 㧈BDTlM x8aO*sHXr=ѩN̮5-ygs{hl AoHK:%)\u0HޜJ`/KԶlv{rL U ROoO>ui"D01n`r9qb@ieWY+ fwBo_ŹЛ3m-F؆U3YVFKw8Ҧҗ>11JsHp^z-cncE u/BO< ' >i ly":DD[q$O4lbBO.qVAVo~8G _n,wL%6t.';OӺW% !N$M$Fr؈p󴼢+x)̗Fw#{Cä́? Q`k۞e'j SJ m^[̉rignkl:]Q@̧9TydP60o3J.s&pz'bv8}2#ybX/fތF%B0ϣ0iG9 P\ۧ+xxqAcCNq#uMV}M ݓ팅OO(ok96HcSktTCwPA84<cb8Z RdVozBГƈuҨ}w.>M MALsӈoAy^|!-`ti!i[)t&K9,0ί6&[i@tJa9;CEnVi{X^xk6NJ j͒0lGΣiCrFTh$<-0'N q8]4V08 2Z'MϨL}P%Fº2O&;c l7eY`BLʣO<4WIfX!/nVKCގo\IM0!?BIo7䟣 M+0Aۣ.|N9pNj1h+LtA 9NS2ܩD*Qb$7U'Oz'~< fT'/YvGz.ކɇotGR_ݽzfRn s,:Qn }J+_^ߋpqnCbsSv}86[K ?q˘n7=tkSN}̤Z 9'vntqȕM4MA(+1]TxYp&m,S\zSE8CJ.cOud)~XƩ}`d4z ۚRd 3hu7+AX aU1[[PӤ3IKdX Q/դcИ :14p)pfqL_`c"R̈́gs!zM '}6xc.t7|4r NoJ{;p# 5`2q"vY2ͦN`MDzG䆥HfANa( 1+>EV`0_}cG'@U?@LU+ 5Pұyr}l|P_[vnb$@߆k#u"#q޽J}m$ YL]'47 M~[x6;j>&>KpĽ En!c+r53t#> ӛr@c4׻-rۍpʗCIgfIMġx]|(rv_߂4t@ULY1tK~utd.bw=O$B ShΑZZ2R-l?jD<.4*5?&.7f"ɗV[j-O#гeZsWTa>]s;/Udo85~l( NV-Ԩ.9# 0Qk5%PZ)rc v, wLQQq\`Cª 6cږ +k!)jH\`΢2N{&j,i llVI6D&ìykd*Vǚ3) :`mg6C{z$'28qXVTTX}"z2oۧ*q>:Y8dI ipf!=6ilopG y)! VR ezVzҺ,e+<5C䘧[\/g'd:u&sC]P]o`\?a+ Yº^=* sAV ?1ң @֡HWH:V5igI;d vBn$>eu1]9AKXL ;n<)o|( ɵuf9ސ${4LL8z%Qik |!딀Y>%Q5z'k`0DCڒ5GZp$5[{byDҳ{?ʦc佢EV%tI6L.ȋfĐ(FuD@\O^ôM''@yGIy?l w]Y|X9?C.}foN2Lz뇹g`%F`gM '9Pe86' /.W^4h%o۝{4U J]x@8گH3;\xϏ.7i}lZ!Ѻ?>u?o)}8} d6M׻A1et2t7F896o=Tgk.9^W=_^MkP< sO|Ya&ϳ~Kl[9haZId<fxlK!!n {>PuvG{D_W<_"6~1c|# :+=DDJfNsNFgqG]s6%9꣈OYoxu|Su<VLeT ѹz:7e8 {T#>g,bw:rv mگL18\^5E&|4!#%d7hn%pѪ#;JDD!9S$<ΝkFȜU$wʔ\#/suO i=MK?"dl:Er(OϙvNikj\O2iEQod$pAIP^.=4f|dNvUƮm.h6f%"}J>4 Xfh2-QbtnbVb(l+LDcR*+>jIo'<2Z~Lي;. *$6 &avDM3!~@p;K/W4 *t X񦣙eGly_( oQimhn23P[Ɯ)Zk$|nWh$ןA$sxnR1[` kҘ;hp+a4lcRmHop-B<B*8Z@~W *@?GeƑBpaf~c5Sޱ k:OO [na5pWVAYW #m?w YɄ!榥]c*wx Ɠ^o|^I -mutIQFV~*Fa~ü3N3Q xaM3qϹg6yzW7(aiNV%v:A>NǂF/wtwHxWņVq 9{ܶSzJr{Uxhi9n]=eRFRM5RσV 454 KNQvh>2,m޼4=w\Mˏ4 Lqfȩc!vG$?K6DbY{SAWkѲ^z^/(\h0IsO Y Bɫ3-'1$- ~aj 6c`VUπ "^ xB/ۯъ9v%yK:(7>h{Os x|,`HOo⡫F~Owe [9[ 6[QWDߢm7M޸vXA*:WؐB=[ie^(2[וngLuL@p;{C?2 Sba:>1ò*'<ȫkdw]oЇnIvZ-j~y|;gKX ~cl:+LT&p~Fy.բuH{4'p<"l;RuFfn"ȾN‰9m>Ey4!c3 DĮ,&`|2,F}Y_ 3E8nKv5DxSB\nvN!Ah&_xD/eԵ,yCoԈ-2ᬃnۅMs0'bWvXu̴o[Rt)a=CvCc\Ꮕ)h`ɴs&z t>/Πܛuh_ƏvF )%YSӠMُ8?Ə,=\![X>͏odԤȉrkkKEjƧgw;F)?%o+~bp:9Z1$ЪmŃlwWA8[P<LvB\=n(]rׁ=HjZ`05t5d!&|(/UIa6y!;X1x+ț׋|5Ǽmy8@(<\0TSs 韏d.~D2I wM|Q嫚[3t$)Lxh燇CwMlrnϣ~ il]样p s}z &yj)T}ozG$s2 ʇ 䵟NOO2x}M[ whWCy'7u>?$'`e #CB_ô.c _Gx_S !csR3D742i(mH$YnOπ.8d1%]sq%/z 5E!Wb$  QPZQxݓOʺN#kڈ?TēM5 />NrRxrR@}s YLke'b ۖ:kS̮p~}9gPԶWƒ(ƫI*Ta<'Ke?˕8Jח+;G|`w <[0}#G E%PrG cIrͧY_Ȱ0^^_ʯ^+-nPm P?2oBFD3[x5}&s ɛy L4ש.Q3.P(Q e.Y+G L.mrWr dOCHO(wh]-aC\i}< f*=TճF$ˢmHa Fr8+x럿'0+JS?̚UQtkm^р2k@W@x>X 3p>qM\tޙu XINgƛop0<~\w0>_w2'{ɒ\/XAn-w#n 6F ˂#7zA 7(#uSz)=D;x)[Kx;GOK%LOzѓ&$0NJ7x50od& hhz8<@L{cƞ +@sfW"onq9g_Fsf*!,8<&ylX_^B@hZ/aQZƔ̟RJ;Y Ox[dFxz0GsOnXVT^%,qUa4xj/&zGn絕mp[/8yLaIԷd:|#xR +9a^ [uWϣ}TK.t+*vFKS{9T&whNGHZy1>Dz1#u:v}Wבs/1 @ε*~fk|ĝsdCg܍HbNjie Lʆ䝋t4k1 XIu/\\wl=s3$%6/x? ^^1TZIz&~އx OdL }S=rI>_=`՜hnx_So͈<~V=@cf c7+/Jl Cc'>_ rD|YG(WuGIڹ-a$/$J>m.Ӽ{hPgK})fߦG\o+~n Z >[NUבvI 1lCQnri'.36r8_f@E[f>?r墏} Z' q( a qmMKpy.,BNo++_= TCdM#PIz]s WxBuz\0Nc^MF?Cail29~J9Zld_l3bܟbrͱMN@:^}gXzaPE^'R4Udž*.f>/AB[ 4Sx"Etv13TE먁_8v} @G-.<.ȕWZO{Qڋ%s7uXErSGл-dp6Yγo I6Fxʕ15|JlCzq3~Y׵D 8zljDRqD.xvďm y̛ZvXMjzpYeF=o=li%L4J?'_儣uoJ}dh,*\N)8tGA*#M!>~kZa!iv9Dy7p!~l;`njxiaV x[qY|J`y*~{KwzA2mu :Mϯ#~az E&ĵ! rheqj=ŸNDN eƊI6˾ ۣk2x*FS(3h s.F>-?oaްv)|Ѝ =p_P\:EimO}GP:gՇ[)Dw+ v"cG+_YM l>ۭ1uPVGS}t9EcMz%ñΣLl4(Iމ Iez|p@i\lWf.s(++/v |Dt.vC87w2X&wV}4~7 ktʴ}alQt@HauNH3z[kUZq\!0F=0D˅yqח@!GD_6iIPLBA3 ^Z ^l/h$3alU1<PU"Z<$3&?9vX]=#\xӳ#ȁQr #4ī2m{y+.\cخz0zVƔWU:7|"(|"l )/:o ^ٝ-2aQW8u1 =~pnX*`{+ h\˼6Q+~#Նǡ0uR<ƱVqnziW=GW|an*Qi?hc">7Oqޮ… ;C mwk"qס0븮:%2x+@c" {GL(aj/I7"kbǬaǶ\2 eG˺Z~w^8bhmݟhK>ODFl6: BX=V.-rl꟢`3ɇjZ!}YNK s:註@rb ]m>n6'1#ku SjVpDzׯ) ol&N侼Ll 7G]1/(CC$d4tq4<3[wi# `r,u >4%mE5p]fx&@o;!Q2ڋDnFX1! ^Z]2 88+tJ(|CpBABĘk̲0 *+:*kT?ӄ_7PAa$9rF9 ̈́-ژl {Ot/5 $A&g[&$,oŁpBL7xhS}T*~faU4Gﰰz#mSRmǎ(]%;51H@Wr~OO_) aD Ťe,3ykI5s$ ry$0HBX5|{ OSG)y01ȼCj ,k*&b.m$4G58/i#T4Asƛ}eQ#6/hӏ*-Agy?=T|~1g9WYg6T9̈́(׊k)=>Fhi` S-rm5W= 1]$k!!wN~-Gv0\'n>FrpfF<` ?xIt)*yvw׏ڹC y| WhGb?!7ܯ$8~"VAG/vs???/_k^{W}sI[aYvL^mkg-d{@'@N0w(M1we0&^pҶ罘$:ʅl pVA BD!arX; qNi5yZ2`tZ`OPG仁9x}#p3\| Oی$ad|f,q;8Jdcz܎Z.TXzX#G7Dw9/Pg/X\-B 7Vqi9Wo]i3띺ܓoo|'n80?W//2jyTOׅåe&rܘQߡUT_J!5[ uW_띎K+Wڟ:1bҿzEc_9>k-P2]qوc8\Shdnx̆' .qcB9G phZC(p7IཻЗȹ4L$83b(11Vdm0BH[.+zU45V{ TFf3>_ZRy~?}}}y__տ?i;k )\t@ OFVx7QR Uq^)޼Ao d Єb#v%$8&]1%ږ SBPGi1sK Dth5L[觮s;2bH>S~L.ebVۿ=MQ9i 3Az]9d#kgaDȫ Ip4Uvͫ[q]e~SrRnV h!.n<Kw, Ҥ Y@gbM!AN~<:g2-b@ KE% M J>~{?Oƫ}|1ޘ xN}G(Z1r>!`gG؍꾾N|إYɧحPBE 2_`SczZS8_Jћ^Nb(V8lcKN^%VLk&F_Mίoc򄚃.T*QQ^uASXF. ;0՟KXH z DE_$1/]p7.gOـcEKz)^]~ȏؿ{~׏}CWl[IP#! dIy,'G^:Cz[L*UTIkY* { |ТL% @-V'1^O4pDEmZMD*ris'I >)4jLͿv\9k@ rt u9=xݗ }p)dNߵm1 lf6zP+)kB :{%IC; t3kQM $c#9Cms_}dXJM%[I3*mH<u ;0p8Zk(Hm%쯽Bi ݎ|gcȝ-ơ t<(xvNE$vIk3y):'Y/}NN Ӂ:N㙉*a;nq%tXQ@61 2|'Wʗtm1[xofzUYve fI UQmY"df GExG1xqGqJa92b|w,VxOhjȐQZ0w(]y/K k^wq ʷbv9U:lznZ2\j9zs!BzG'룑l GQtz')S0 S?5O=NCFӜCtV*Lx^ǟui*OSZs`̠<N0E:t3^z~}w]/> .*|cBǸy622/RI58f$}Ǖ%x5e" \smgMVFWD&y̼\㇌$ UrCLZsZ1 &$}Cl!x O^aןDVU&LB/^| D)4ia̰^?o~{ߧskOgzLWhБ$Iw[su)Mv"[`ĴZAhJe,(EۜVECdDKjv`Y3~ǛzwxF5%❣ ^ )48maFÌ$g\ҦEOGj 9;M$QzQ 1epbȇI)[cːy-WF\mzbcRZΗ׻>xY_%H,tJ ,MTqF.Rѥy"̰ m`'UEO)LmTv3kq^XwSb Jr?c?ͻ|/9_˿ ipr:CHh 1׌y&z`Ox&-7\VN|Fh R3 1dgdeW%-)<.VϧNL(e(8cj$'Œ'#ݐ+p8+WV9lFlphr3ml!ʷ?&r:uSWt u)h=V8\KeNJe@YP3!t)e &7cӫ-ߐ숴XpťxPt5RNQ7"AzʱpQM<<7l! $59v"TW 14Ep[`m, l+@V7#.;P!hh]\XluD̫b_ǿK?睟jX+[xF?}O~c?=>k04n MBjx3@.&Pd  ͖V^A,>ۢp T4JJR9H+Z1_*jV,JYzw3}Iiks.Lg *)6C9 db9X+$Fhedbzra,GeA*ބϗ)yE._wCnGgŗ׳V|}}wfzW_W*Um&td](RAy[n9zxycr_&c{T!-e˅Rx $;r`gx\ (9I%€ߌw|/_O}m'ZHT mZb+wh}IB&(Sh{\uP e[n&&5 Z-\< e{MdVgU Nj:ٌU榽]#Ԭ4ɵ4[8M??&v G (IrsS+ldDZq '˜SeŐq6gyQtH[%.K<1YrO5{ZI[~%o>¦1ǩwa^΀%D)A_"5k_7hx~G>O?>{x AΜ& ֦GXZv[L7onqoHWB1x?ED %tͯ?za>ͯ; Ll$ @g k <'o}{>/Cn4quid~Oyr hi|Mf+t?a>+~tv:O8}D y<D 0tQ!]6PJHW¯}wi'Ƕ8G9]޾VS:KάOQ{ʋ6?|9[/X>;O?K ]cW7֚E$\`^{tLcMb䇞@ p7Z]T7lH8oĆ8_'@;!˵. 7EF_~e}w?e|pS)W1<}O?BsEȷe1ytIm./gnG?Vg\`"|F yXKʫ'p(7yt~堧S )!MbGO9m?LŘb}t:*Ũ(k x)m]m;^# ~Rjoh1DġS 1CGl9_=G3J'Z*[(S3*LgCoFɅSg:'^UNJk׸]ey;63M]p+{StR7G>o_u[e4q26.477傼X2a> Az?CBBݒ.zV1D+ ,!K9 pK94Z;$_4k-,52nkVwS ; $̲D=ˌ!S ڻ(% SFldç\$ɸ\/+ Yr,lӷ!@6aYo15C`$19#n[QW?8`Gug&G?[s%ۢ/00tPg}O{ }|Ƌ6( "}HFNdV[|fa ])"4$,xPΞ1^H(\֌=n ,]"n('m5fA77(7a>m>?GğO~$^ ho]Rl'ŒN lj,kf:Y^Z[ß mDd H!ot̩TB^gWp>44! <(9j&de[0[-9 uM3G %$]`DV=4bayPa)]]su2=ކ(`ݓ8T²_!qx=xvݬ\fJp"[i.A#P)$+rn]EY.n'JsxnT=~ ;㘈ZcHW Fkd?ŋo4ykwxmJ Vv8Bt:=Q592cAI_M &@qHysQŁvzb$ #HD|W@êV~̡ 2Ş'ijBۿï<ߞ&C2xz.fv-mhb΋kF!hΙE{J7h!Oԏ0ָeZ ݤbQ`&a5D;J,c`u& {]$y4.;FҐBoZm5ZUV VӒKMG ߴ - C@g\G#9sCtW@kig^Y+zI iyvۊQr۱IgB@_)yc^&@;}<:_Coc.*gL9z~#7}[E/ЯJIwN Ku/^?7b $ݵ<u`&Pc`XҖVV VvSaTV.--S:Lr_!חRL&Kj1S}I@Oy:b|x?|k43t]j4‚*S8r݅:ˈv⍠ 7uZď[x#4 q'[pG-Z"q=owq IU@j,y ?%׷lĶ H] } ? | f/ E jٷw6W|W2i=ɽ/u0!Y&j+s3\'i$@cYQ liq7!cpّ}}?'>0@əÉ0g_:JfeӰQ%p3˜ʷye&* Vb%z\ 1 Zuj|ݴww}A;\Bo>etVK#'S3a&:zwo.}Zڕok:v€yPahʨw0N5,1eeS8[\ #@5?*rrjMA uȩP_G3r/V_GXKT&EU !X!Z:miѡIcQM%+Q+Ӷ\Njf5|1)]!uu()?oG&,IK/N4t gђ\1P3$fv/1Iͪ&Gexb?D|i]wdչJԒD is)M&9ɰ&$E4O$)~'Ɇ#ޠ|]CU:޳OjdלGU9a{h^y,C+reY}d5MV;;zPc?6rۈp<Ҭk?Ih%Vf·@*!_WnȿK~wr~͚lOyl^O(:w;Z$,}f j_E 5jJx¡v NU π4z¦.3Zkɉ QC_2||G/3:om l/my &8t=<(5z|\cC(*"$<>>o$m9|cft ޮ:xA]>O[GHS־E-#hgB9gAϙSIC+SdqU * yDNK,ϋM.HZRU-$H`ɲ`j#C)6jbhS#ڐLRB&nvEŠV7p&$Wm& 8 Q }*Ƃ&8uӯ,k˼~p,:dUTο|n ЊrceX;ңR1 ˰:&.*kxwFT9c*?~?z2 7r<@z`%P0ŝ O;v7T/ B r5h!q"[,AP6#gi O*0n%I2SqsƏ`g4Њr,y)pC N_>|W3,^*X7+DiL7"#x=ޜJKD?oQć 71ky%>گ2w>O M0{N"7:ZbL, r [ ]M% p  aTr.L|h0%2%ߗKؠj-0b jIH7QewdLr*uNb}3{̉X_3U#&c³`6HlЇ>)Gq%}-B_ଯ㦾~q!ԋD?9}˾JqP:QKrfFX#31$ W0Ejׄ ͅ@rRqRkeODݿ|*B\h3v;;~b,S#c1]ld'lI]&0xi`\01 nʺ~./t!fޞ-F-%Yg@7m'9V\MF ird2ci('kU `k۱'VR$;i2dҋ$JTt2Lc#SR߳Պ̷ ;'244$U#$JQExw,u74;MEBy!{~m}C`no (Aw]$P $?4΄ϖd^HpAT0{/_?s?Y\ >5=ʞhk2hqHbC!)}49$+'"j`0pG!$Ii`hU`@%:!PRo>_T-|ڧ|JbۖkJG]O|o_Aġ_ !WE5"fziW{ҍEp6u =#e)haݓ!H j\&nl(4l3A sDA7P"GFrXF?">Rx tz:t%. ?J€H@Ȗ-э9/%2*A1DZqUާiē;$X?c]ٍAV;jK\^&\龾l$Vezg/DL`[3kѹC: RGÔw\%HEp̱!suw1xx5-dɍ~ ~o{Ϸ{N^Z, kpSO8A8Y0ъ-2~ UV>tݰQv?mۖ.X3x;9E~3nuy ^5u6O;H*?91pۆgN,B%ĔS]tnNBu5KBxtF5eMe||4v5]u,apiզH"s0Դ~91q@L̋ߓDMct 1`[uM^**DnYĂ7:: 7/^{m/k+E?OM4ut7,|Ai݋ 2'&a[>Mz`2>砾Z>el,-H`K3z6O zĆe+l1C#6HmLKʏp7v i._64!Z@CGRq}#ld!;XdcDG4)&rpzA d9= 4©fa@Gj?L,Bw)R٤Lo| 5Tbm-\rE0tls7__%T )<cZE<<@O|gs_xa 7ܖc{]f%< ;7ұZG q/0OY,>oj\;Uך>N$6 y R l$E^5.˰^r81E`}~P zR6"A ތ,n7)r:G 2c_ O& nY!0V_l;Q܉l&yI{SbȖ?\]7g;૬IB2e8TTnmjZZj[GݵѪhժ){0V HB @{ss bg|J6a7K!!`F^`.o\v RhVb ϒ7:(BtKh 9:U<Ţ f+Oݗ`!B|oXJKq Arn&ϋI \n9UQ<%U<%D'yvYd)R$P-gAN ฒCE1jD>,1HG:C/4b~KC:K£7õsy@ذb5$KB>nvaARE]j%+!v#vf2 *=(%q%8TIQrO<@u`t1]3E4Hӓ8w9Zp <AHh+(2[7HIqĖc )FP#30IR&&F @fܐd"<˜&tde5q~dd$ף?`ehlPY}|UQ)Y,KӔm{*z|ce=IBLL$ѭC& -:rP "b-+>: #;)Dц 0?\C1 /)>눜O7 fUt|p.ś?ZaSXQ1G>x @"Ku>>AD,@ <r~dOATBHᗨtp pl/i"WTQQiҍ.ZT^7}[qyy-(B @>ߤe c 1.BpQ*uEz*J1y=o6r#ҦXL"w|4녱ܣE9 p -s:GSY _%}a U;,LpeޤRV'|I}/)ш2؄g>g!H! 8OP`᠐ǟ|`kT}GVJy}H>AG\O D ^^أRN GU( +pK ܎T̕Z*ܱǦB o= ]V!$Qju78;1rN9Aa6@_! /#(` Ğr&0 $1($Cd%TĢޝ:e5tRw~b0=Q_hpTw**^z,0D ڣ9_Tx[i$B)V!($A@ 4ğ~~D<-.~{ic4P#P /wkn/SZ)e;Dw4 )? n|l+n1 ']D48b*xmv (uWq:ה |98Z 8ٹ v)xb$qAcZ:hxx( UH|x|(Mxuu$y^PqҴ< SYVRUh%VpNP .L7AWaYVQJdjaʥ=-vm"I9yJV:4ǸqxC+gI¢?1*$8уya6`y^J ,Q㠠ڍWʴ ?5x_ ҁ?WY8 !lJ +/r?f:Qnʚ7A:4cJ=P6=iA(hb>"j盅A@6a8 Jp{Cc}LT7Pdp?|A8#uCz vhtLh>Kg<:|8`|Agjo[3e I)hPNq&Z׊&!؁}\\\ nEF#h185-ހF8@.(YlיV u%a$Ѵ>~g4!@ pHfi$"(啒|n#{;o6sFBÊG@E%ץ<%BzBhT_WwԔTnG{KڡDQWbwTvÍ4NK73o") ”ZȈNZ޼*n\QR- P$|䷚HIiibe+R%hIGznliTtP\yUȀ\;q xRrJfj)PזnW2I ="j1W5WSUࡃ2If7 4Xª#8E oA (>z@ۗf'de+cR J`phLӄ6v o$h 3EeY퍝1S/3--=5jϙAN1 Vʟ`~ D1,8E1Ztr,&saE (],ĩ(̈́+b%-d„oUC/Q79,\!h(*e޽W l/Z hh=z5mmfY}FbQgҥ-6@L]>C>]t-o/ٱc}}uuP͚]}iםqFHG̃w,RUoֺuW.UQQSzWUAHNJJOܲemzmۯ}['mlc$aID:=lICD<:g+,ݸxÆ%J6ܹjMkҮY[ަm&y@ \EIxl4zpFM6~}++5slMKmտ!#}Ae~SSvN{^{lټlSQY٪M6[[[s04Q삜-Z uHn}:uLKnsmQæOFn!$,~?7`Q6>?pc]vںk=oֵ湹rr c̀yYYҴSRqP *_+V~|;U{zW~|yYڵ޽ОziA<|S%Pxqt@ēq |1>;wY-vں{Jyrs5ҳd's %!vuz Ɔ|~X0t6nݭڄ{Q+n(U*46*ۖDLbj h8z %}XqE'Οvsٶ;vGveUU}tXu:'3IvN~nN.];W$RVhY`kLP_USdÒkYqV}zO7-[5oߢE֭;jսm-Zx3Ay#l(|C2 R&NLp}eK;nXy9-/[`ociK:n f.{Ss~U +'vHȕP>-\h>p˼&u}:b\}G:qLק?/8bS/խeY}"pWm&~3Gm${ui>37jޚ>>{]sƈ?\w]d2(P_Q|o-Y&i wޠ.]8 N(p\NbG0裪ARW `ݤKޝ9]n4D(3S{>sni5jykW0kևVٓEO;l$Ym?G]|]CӖ-;=|~N[JmE͘6t}?l9CNn4FUdɾt=PݜA&.:\t߿B%ѷV NPƝo ^Ӗ.>uو馦YـDz?~:o^ĽtgSth\WKV9 K2gdzg-۔LWNW>Qge7$pf/j@ї*۱㽩SޟOLSVN_Mm`^䮧|w d=;t,\v0eOs]s19BrXe%?s[E1Vopjo7ޛoѩ: ;asu.CQwf.^-ܺcGCN|߭%cƌ9JFK.ݭ?Mr͚q˯vlJH/|ͺOg~/וNxtΝwen1e?+Hۯg6nLܪ{sQqK6ldw?qde7Fy8 )Ͼ}-8kԹs7i}:wHO1cZ4OJ9c|p.1msFG?ܾ\UM[( H-SDZC֟zGWŗ_3!0 DG˯!m~M(ţD:X^>ĭHĎ) KeنF ag- igXD))ZcM\ 1J% 0gtI ]4$:hwk / .{2|s1_jm; sXT;+:y+Ӧ}"7[$n&!d|)EB.Xٺ!Ɲ;tYDުmc^2l).ZqLG09 XdOl7O|y[ 0-Eˎyo۶سW}LQhwUͫS&: oj%ɵ2('a]J݋hϗ,UTT׀*Z7/;Fݹe$)8}ڄccgAEţpp.2^eA?_/8-޿A&>Ku L_Y':]ܷChv bDJp {kѦM ݂5Gȸ٧Cto؄Wz0kRpCW?{c /۹S437 j"X9>#xQڤ{>Yt1sK )ZfM˦Mu!OeՖK VZ^\{/fX]a(ru ڊdH4 RNCjL֢Eo~٤ $\:!;6Dh .0 |VT@s߮]wTޕ@Qrv=55ΤHSN`-@Da˖ /FVpN|+~ī*v~>kg^tq3pފ#/k 7\tQ5ۂg a[k6n8Z]jeԴ4ΰdu>pŊ0kk??ք/ .xYO߁?p{ۊ`~5 >LCX{k- 2IC+ġ0f;wWN7/h={4[ZJ+9/_ީi  0Jr%RGZa[0|37{f [Q0>1k7@exr#dh.#ꭐc :!IHayFj<j+b=$ %rbX,cku(-P?&u2+VT7ܹbmHQdp'֤e?-F=wVWqdiFL䚳nB.*)/o`kYAZ%W h>o w?/R=t7GY o͖ηmwڬ5;Si-`k[(%#D 7=?&2l#mڋ*i+o}0gΖ_)ߔwHKJH4? ihYP㚲|}dRb]N=.}m!ʑFRjք7&O9xA}3 oHK90Dbۉr r.k4iVskE%нŋ'u,U &<С߬Y,7|gٍRb\{qc|)4@^- BS}¥2"wGJ0}kշ&}?ץKYve}eĔVVJnſN[6;"Eڭ`񎍀MT}.gꂅZbߩiWh]PxDH9[`fE-h8~JX*^ zůS&5|zSU?|Oo_qe^vפ {УrALg-Y5_b⢅mJ֏ͯ1M pxk~_*k@>p!6l.XϹV/~㘆++~2gv,ѵ@{}1;Cхwy߄*D\:@#3Aڵ"HJ8(#=-pam }; uŋ~iYqgD'*>·1wLU,=7G혗8<5~zǜ˴1?_;qBz-aβ萩UZ˥}]L?G XI4n *lAZ}0%5 (Zv^grWM9Yae<ukZ޻ т5ɝ ? LwmbT8 iX*ّe"???ŝ @6>}9R"\S WS3fuNa̼'+~`M A0G˯`C+&oLa9[{)b_xGG4'9>zsh-`@ӱ'Oɔ-,H9e)cj[]ZRDM!cV_ oeߤg7/P=|{VABϨ?pOoӦj:]o}G v(^StM-婓oxJ#ꦽ3KieJZ͟CoO/:2/ٴI+̈́ x(!ɺ98D+Di_UgZ\\Sl6[_'%'"ieSrc=qWJ#E;$n9#xK ޘ2!ٲ{*֒BiPC % _**;?ֺ`ƌ7B/+Ō"޳4l9S#mIxH*,;zfKʼnjW^^fu(##G.u|;XpƗVE#oۆe t[IBeL 4'nZ߬ ׭e>gWy1~Ry7?amy8fqAh,(H_1?z? sD<{b4tV%8qkw?h*WN[?Aqx0gl]ɿ^,Rt#>P?I[NqݝvO=i$+r`dӆ7fq2€ kqZa=ҾE`l\Ra~a:va*;Ku[#(nBUeĬd.MtHfaѤLU((@[o{|jP_XA+ G6\r ҰuC8󒠊f!^A`$Q=o}qޝ7_ѐ̎ RvujþU{3|^J2 .|}|h7ʀAV“aQ<mڔи&ڦ')[_ֿe}O[`&ŞK6\83Rk +ATbD0\˗ossONPy^$-wN=8֫zXc6*y-[rmO?DV$g*Veħ ݉X=???)ꘀR75qo+`YzVv I-_-;w+PUlKs&oOfVb'7rcRjK(@z_mZ9hpFZBiZ҇sE^LjWuk9q6Tk?PtEpJ2hNJ,m u\ZᶇZ\ET j7}@泗,^QG~ NZ޿W?9r6R}hhǍAB] @IG HxV͛-L6'&ϚwZP} {'%K8$pF1eR+UN] ǂ!r2&f,R7Gȯ,lgנgQ&\NBIH@I(u!l8U?|k3A;F{i(BtTs׽hHibSد$vYrkv7'RU~"jZRmݪN0EhS}j&rƟy{skE 1X P>[Bmr‡'Y [oE_$`Tp1Q ǧGhު>EE_~[{jّG6i/dfLMk1@wՆ&u4+M .ЮJgh _.Z!>8"XM>?#8 $gЅ3Ѕ\1J/mMlr=G\J`DŞG^zQE *QQ}S|'.s oL^˥X4tQT:u+6o>80[m(y?.(YߐM*2`dh|o坯H^ZmPrfG>S}mSdPν۵٦]f*[e.s_vOxt=g{߱c%/K %>nagӬ̈ѩiYK$jѯLb]_dӻޫWnf_7 gYT\}yݤm% Ej %_>}-iI|2PrJNJҭ=UX70w&Ops2rmOm!vݱSώ:j5k6m,ڰq2Pڔq`npFu;o .ɉ.0Ep֜)B{b.L[oٙ>pg-vmصtDݳF2% $7zfsz57ZDzA3TO^⦭*}oN\|Ymr0S 4{ }̏m=SBFިl)Ttȳg[˷]FfmH 4ҔBX|$luV(s-N~4Xmm?&޸ cb?r@ H7A6 vE~.f*.X2\4aUhAo PSkPEA!OAżJO`5B "۩aƲ?/-z?iӺI@jǴi/LJ+AD` M6UT|R{ER 3Nk׽`^]ӬGvܠIxW6g͚nN}w휑ڈ`Pf?i$4:IVv~eڪ-8}M U6}dENѕ.f(իٳ~yUMhpG3~q5C) I4GIpZd.pTFĿL r4aZZCϲGfk7yছ.٧#{9Gdͷ':yde cxO%fw?֞mΟi-TF 6ڠIv ~w8qc]Zשc6msrffjΪ=oƥ׭[_=\cJO(:cNjWMoxU]ڰdR嬙V ni&z<"9$;ߠ@z踍`h4`%n)p`ѸZ{@IhO8W?:$lc&xkӬ+ܻ<;U ]۶{7iѴ@e441p8S6Liz@D#a%<^1R_-WTV3_nܼ$6 $Ō8Oyy:aa~ =͊8SƝ?㏫j/ձMUѩs&y9ٙwܸu͛átf,ZtMi3H _ϥU'f,ZG@1(R; 3X3hCM~6ZLx~,w-u}'5Z\nQ^8Y{-ѻkfʹ;LV=5U6o))++,ZE=".,,]h/Mp[T$o;U3 ]Ƙp#~>:[hE  V HfÀТJ1hRAOTۢ%oIҩh0q$YCBw*ڢoR25-$W`ŕpH;Us`#Q)ސfx^m؉- ȁpBk?ˆtޣϵ|+w3k;BJ]㿿En.HQM AwÞ{5Yy_~늵nEeWӿ4{$U+ cVrѿQpV8z@;iM0* U^<S rM_PҲ={_!kx"Uj X֏@?;z隵ϯ;}]٦K^piiŁh@X<&(A5\(k,B~`O#uP;l6k^rFh$?) 0я+ϼsW]@t:m7 >ڠOWWӪt-[&y|u/[^_O>1p`ZZa*mUaL4EpFce$wOpQ3~{4{1c09a" 5o"=-5 ~7A )ls:2,w}gj(umQ;;H%R9sN??<ܣwڵY|9)>SۿKFBn$%9ڠ7&<քP֥ES>PD h 5rGŒF Rfkc>4q5ۡMF7rdn#ǷI|. ]4f.IǦ4&Q*VaGyU34F[2+fD߾;v6Q+WݺHbL z2i^tMILݿ;XwtݧR7:[<1,'#_ctqQw#~zGeIxk#p f2sʓwHKMa1 3HҚkjugIk8gR-~OŧtcW\.&fc$%֎$ \wرZSCnֽg>78 rCBۂR[8\`:1$:}-ji4O6:w~{:]ON-jD@#__VT}ե5gYӦ6.*ݶ=z?o6I(V[ܣה`TPzR{)Hh{sKpCūͫM7ѻOɒyz(K o?kJәC@Wr.3/ozSwi4j*"LJbQ{߭]u4![X8WF)H~:vnz-~o~pr$ڰ [P;[=TϢ5%%{kjđ ]k fE!m:: $HXb撛}Q%_=~Ci1 ),HF9?%5H!/+Z}nHddb#;|YwyJmWVO0?^J_,"i ܟU@\tk޻\ =IUTBPNȯ_; wIL䈗)X!J֤qH+iHPP*L7q S +U=K ~ {N)(A " ޓ(*Z]N5o~_̀nᢅcwtV%fMkN;킁vA~2>J1[>, Jo[~pZoWCtG5c?Cܼ{.:bE"V{$$ l:_[ܴwvNG5pFǛ z!v霭5I!XiPK&KeMcE{^VF,'LKkM:J||ѫ]; m*lm۵^0=ȃ^R5u_=bTd> '7?g7FqސOrKfTA r(I(qѺ_ ܹggyܪ4o ߻j×k]qOE)m^>n;'~w?pPXc}#pCGNrƄ#Ȩ@\p?ЭSPADHh%qP ~_srnc\'I`BU<7tx0Jي2vR}hA$y%l4L9Y)LX³}0oՠ5+/RfO)IsqD,۬]$O Jpn B@tVy%.Sw3|N"ؑ'̜路=GHdơ(?/ noմAnp7g;L.'wUJhgV[Ym4 RcGee!SZpNa>pxϏ^Ù}dgHX)iw݆vh +8RRݓ-Hη=/-$~]2:0QXҠ(\qƈF<ȸ7rsS~zoͷfFRen)`-ShlϦ#04E{#FxUlEa7| ;tv{VFbM]N7tYwM(سoݻ6ooSg<?W!Ccq3iA3:|ކo?p%wHo's֮ ڒֵۅ'[lp Qp׷]O;=hv1{Qmy[xޖι6Q4 C an4)Pbgn}ڷk A$xaD2ӵ("Q8W ?f@|Sn"Ͳsrp@#htȀq(3].NW1TMy#|Jޝ[ >}(|E=V K3C$QADG^I!椇+jy$G6تe7xx2"<+Ԩ7 lH% BA[w_ xX8/WuvVheɀv2 phHQ4b[d[l'|m.ߡwŻ(qy1\Bؕ򌁃2b.Ǻf,YR t7&ϝ]kP^mW! c<`xy_( [d*(MrsrNb܀7ܨ "*`_ʾॢuy2ìe"On7ixCYB<$DDf!D2cx_`-$+]J`6$Zhع^~[(15:ggknFc)STWzX2E2 => IFa W7ߺkWlUlYI"GjHIb&jHy ֳ~xKybĈga w@(8zEЫFSY|VJpr^^ҍ^?!yJx }v޴gMB2l)P 4o.)f6P0͏Qvlժ*1M+/{ev|7r☙udf$;qخUMVXz\螨Uz+g ~Rf6`IGnĐ۶Bbe}Qb'+q`Nv ߆o>W <>cWo|G05/fm&Bۏki+lNHxټ'. C&Z 3n*m ܔf/JH( ]&+Jؾ^ȯ @т>f~-( (7"wG(t6OɯƂ1Th/Qj¦dBLU5lģ: Z Cz)):E2x9MM>'lnHZujάt7 NuSNJwA4+?SxS5Gc J$D} vlF#Mǘ"|ksFA*rqf>ub#$ȟv5 tس7-5Fۇj؄Щ7ݜ2ж}(|H?4dkNVԴB1i򀗮) Ġ=/.ԎեE kM<<?WQΣxp)0ftf>EpslߺUJJr~2dN4uZz|bIǞvz㘭iyŔJ}*'_ kqiDrkt!V@<֧WEƅ ouV-'Hz]5Ғ>\Ƞ8:"!Y*3ḓAk:f(ͯyrO !ϯ? )A`Hg #!vcu)Hq!t""DpE?HT5!$9G ETJ(KPDԬgH~V31}%n:޷U }îY\vR Z{+ YYoÌݷ7 .:ِ.,) շG° /nكݧoJBì5p{Mԣ" W"(R tR5#q.n( ^ j%ic0GVH9Hb!>/M|\)rwd`KlJ-W ۶7DSbPJCk)%Kkqڼ:{wM"qaX,a\P-3QJwdr Dڂ۷m4%0^@H[F9 Ei|4dh߼K/k\v} F?9o\N,e-vC-8(aT>ɑlL5 n;(YzuW)>4?P(M=opm͛d+ҹg[l脾Qc(o{QBQXGJ6J@U]z;ⵧEdˠ8A]aeGͪxҋH${ Ek^77֘i4 Z !y$Ѱհ3RkU(VQba#XDf] rsL =r!MIQ˛[ khMJB: 2ѥ]Z'2۶jCB#uO7qaQ8]6:s@`|,7 *N7zy' ~V D:lZw@[a'ˈ'w14m $0atgz{;X"#ݶ2&Qb͇-wz|N"~88oqW1R > Oi`j!oo+A(A 70˯1k+{X,;^/VG˯ˏ_+%EW-RL$yo!.%T[Ua<]xi-8"Gc="6% mxݬwMMl27X\6qEHq;׷Nr)BA?uj#q06 %$x$J09g"T¬#V_@G_`Y^^PDÑL/dP2/{#CGz=m峌M: 3<*إ+usێUZBO+mIgFIA8PUXΞٻ @yBȮGjw2P <DlWrQF-'O+YWkJ7 ٬PQ!wT=0'#l`A1 ܙ-\K/Ӆ9vQsc\woӼTE.FO.AK>tAlnKBsh-XUT\tժ+W.]tփa!*?̌<1ǑDKkO*B鬲z'v=%ϯ?^|%=w$7Mi- Foqk6YPZ2M8~/UU `{wDHCIxl=!f} tjAxlPǢ[m[!(%)zyGLTSbbmC{݇R'8PШpz$kמ֋cBmmZL1S(ܬء-?/7>wU0d5BVg%B:"`2x"bL ZْGuWi/*>=/{w$! EpdSGpWaPDAED HȾy~}OWKN -$!uΩ{lх 7mP4EϏk%m(Z69gz'sfSrhj*@CA`pSi!-:ܥkiq OF#ß)k)T(E;NW "a;9`!B1Mf99KTIkZ(({BA/A~&2 DPo᳟z?}cNSN9kq&Æ^;bի˧ _{M82;7?p5krFTjD03&b܌fzA7d4wHicƾ[q|hт676o~s-^_ީ fr$`&(o*G Aa y6䜺#+L}͸g^k{DhMwk`#їP a8J(@)M1 9ykVx>cM'Cd0%Qgt ċQ8N ^:Ӵg@ջ nv.FY_PմxQz@ɬAZa`c"m%~kщ΍ȩh1~g A›o7>v:Zf̜3[P*z;6CS#U+7n\}Qs֓шq/I0w,90$boN^y:'z CZlA"{ݩ@>@(&1-\`=i  KOSgv8)8?QTgBAfa *4ЀrsHEpy#2&s@5T=z&-Pp"0 :<T-OR|}>xe/Gu'Jw=/}L?U .ϠR}MiP$@ -hH>2ZxƄ } ?Γ&_8lذ#`DIىIRO_7o{ ~DP")پ?siFcim h2!wcwr_d“PW=4߹J1;APoJ?1kȆ7aA}mX>֖ͫ&0vтgYګS17ΗڄH&r%2n?ڣ=oH~!Gvx x%v'wc .pL:J^!-Ж:7, [e5<G`ϓ87}[Җ,hTsMMտL;~[>7KW}Z6i{&Q\q;$LSNkj&h`Q SyW"expY9t"0ewM7?<0Ppr_Hւ\%c#8? s@z!g+Q4ʲ ֵ3Z23,;u LNQײțe8McQSYnc?WTE,E&2Qi~7~X?KڳDBI(Lh&<>[HЃO"ӐJpk{[݁ i*c2?"ȢVx10i"IA=D֐;p{/4֋ke^K oZuX`}!Z]KD_hzz+{3Tx5o؄ >_%@1w|UZJUxD ,2@ӠuAʩphf+|E?ұcHS I `c-Vt @k QP?K Tc@ z3cN*Eu o>5G9>s+X)4{O^>\߀=>hݦ/[ hGfӭ1)Ѓ`}͝*aIQЎ̈́?`2zF6گnq;>E138D|e;/3q `jTI. h bņtZ#>[8!\rܺ By$yA)YQ2&aWx#E24y\}QWd9h`6(ZލK' uzr3?kjj~o|=D2Ht_X`ӎ;W" B.aKuhBݑ (?˴^J Tbryn+%hO1!5Lac371zЁSHR?gƤwnk~˻~B`a r>1,7 pO ];%\6ucbImI-o) d r?Ĩ 0#U2$8^+w)ŕimV-0 %ތKX_B TkGX@^ZG/Ԑ"D,HEdGe# AYJ2Q ڸ3`WA*J) sWC% [%u"fŢvCF]NE{|QwRS,2}W.7pA5fu^Yxq#>3:P/a%Cq3Rҕ(S J)UFj^[~Bxfc8*#e/A .0sSidhU) I9o]hgZ+-Sv\EᒈKknFjϸ7[oYvdo2@I*{Ʈ'h~ & B} _0` b J€xb;v( :dյ} ;-gS #M5d>0ae'o X@g ˪}H+,L8iC͡DQB l&V#꘺ $&9̶գkSS$5s'Oؚ>'C&eڪ7xK֦9GXpqNmeSa HsFspk`N^~bTiwӧWzƷ|>9Oܣ{*zOzFCɚeko!*g 8]G`v?|UumæM {Wuͣ/^ac9IeYuIrev$8%.Zt4.Ax%R=SڄԮO4C;xBvŪGA&j#a1M̓[Swe0(Yq}߾H1ӫQ-$ɤ wYL6 kg_r"ݡrkGVHgȞ26NJg`Q2T48H َ6P3֡*hq8rΐW"AhheqO0(_ &#jaɁFxasvac4D%vd̄~!zGLbPHJq{ *ƛ3${Ӕh%<~lmn.<تb xk2xT蚂80i]/[iĘtY/9.էL|^d9Ff0/Gdj'e Kjkw{eVߨF?tܹ!1lt.%rU^I4:7eţS|%@Ʉӑ }rZeFܶTF9w ړ90 1;b?TIΥB*0;C)T@)fpEO[ el}K~SO{y?[iLpq&vX7@Q %zyOӟ^0DѰAF >bֵKG>?~y?eNɠ.l$ϿA ~0`#qJ -JY"{v{e3׮$0?Iq|j, Pwv,w+naHֆ/1i* ft=Cl%>3epf><3.JD΁vRi0ׯ雯K.JtJME4 jvpX*^OA=eٴA8J0ֺoou7 $D>缵[6?3o#c"i?)G29&o )߈6"ӎFc61 *u,{.%iIGNz)1Eհ"ak!o\?د6U tDŽ>/VJv?Nt%* wFRHCZ "D*s²qXR|'Wv\ (nIgA'X&)cѩgdu'mMc;*C9ߴ'$#C:Cd&1 \vQ˗, H~1s|{Z0tiIxno˚<91eK#F'8#j2nŌ%K?x\$Gcg;irRBve;G53E~& ]{.THH0 s<+nWse)j/4SE͆ s MޫGvdPu̍Eۈ)mu.lTy`-$ٌ_DA%9rȠp6 [SkIv wda#iڅi8i>؁`.]WDB[`fJ PM`* ;r)[]i˔Kݳ;5Q+Gj4CmV;k_0P.kҒb^^MĭǸtgxiŊ8t4Be4ן覹Yq:wo~ ӄ~V]}ElQdihÉkj+gk:în}9|@joA hƿ $M9Q-@&kXIlD,<)RO)"WtFTTB ootB{ȯ8- sylIBy v(**1 us$[4nf@eC=!R~ЧO+jl^gϮ]kjj?ڍʹD}}} I`4od@P~nv7u(:Ô1c5ep؆ /ێ|<[ު! \| [ɵ>/Gvx[|ٮs(X<0vϞ'P-]о0P*VE"2].Q 2QX]v6\\j`$xaXb}m#7vȌ@*bhk)pa"Q`( .`̉TLX  ũM5;B#8'-(Q`4NP9Y\= CيF%~-֚  \?Z- Q0ypa,(/z ;^=D^?\2__%0V|ץf2}Ѥ=ksLRשGMxw}-~` Х%dP6ϺA>ҁPrRy^yInJz>-*wIזi%< Qeg:^tDĚù[" iǟp '4MgYԷ;PДrF98%B0Ic?3\όqS;p;M 0phDֹ6yvmZkT~l#6~绮yՉ46 BkL$_q𚉌m7_u#/ vsVY{.F "ȷ ZfnF[x.T5xk֯uN:v֕>1Yz^>~YJS\VJ #/ĮyRGS0M1_eqa}[!ݱBGÈA3c}mbK2yPpb6UD)V[\_&#UVZ!Y%9 yߩR<SB"~ffy%sbƆ## .LcdF1U^PEY:U=9ɺ81auijܒX6$Z.-K n?!'?gւmP3$+7ͱa}_-54toB~c9^*lkK|Y"ʺU᥸_`!&1c3`llϭBD D @vp]"uZU]),w/$N _M#j?H\R˜R ^&):> 4DHhn'j^Aˉy$m"SpRa-#t60~qY#6X DRh#~W]/խ^~L }ʋ4UՎ4&Yҏ4qҪHvgmǯ̎Oa(]p2Ϙ0L/m[.܅ ˩Ꮫ\3`!nO+o3Dr+-k7l[ɝK>(zh \P:z`YR%ޓ䌍ZۧדrV]m}D&5å VY74S#@xdE.G1 .:pp%LŸܵ-*Ge0Ê"tQ̙x '=YU3FlZHo9k!lU#=ᠿpaQGS.#\U/J02/>/0,0Y0C$XѢd~=}p%'7cOmH^^+wX[SU\o8y PP=vo_²e Idt~U X[*~,&/޶n*7tt҄ g=sȑ5 Bb, ``o[_'"BG;.rK׻B~}꼅Lg< E8^|D57r~[*}1*>ߓWdE(Z6I% $狓) FT!I|[^cPU:ĘP%"#yOV=ZN=HÎlg3ɡxrUT4!@)W:^{\S0!H^7we7rŚ5N#N8r҇O|ctJQt.bS~{}&૗gDihQ=tYn^wrNU-4gGغj9v4Z O'2A1z@-bbֶ;f@1^?h`$E4bW.Ҵ7ڀ~՚vj @ \v'q l +֬޾=Kz 3 S3>ڰqΨyUڎ9[PR;7JʑfvdDS S-"QsԞ]EԌ(ʙ ! Jx P(=?`5doԱ^Yȇ,Ljr~XS[]MDz&:09@U9Z;'0uT>A PcR-_[nratW2@ ifnZl.2ǝr %WkpnaY;^,+OxBZf|@C4`@P[3އGk7߹sWԓ m ֧N"P'$G %L}h'?'lno5dls"  N%1Ee.p: ZPp#\.6D1` .REl®RT((^'=$ SϠO%eXR-D V(C x]Ι*wC쮌.Rua79NP7hl8 6]!E :fLscV{Mw hwmq^je^FCuC?twHјg7DY:$edHܰBOaʢ-1;'9^YkuV2iヌڲm\`hGЋ^:7gn:ܥQ3?T?sl8?:2$L$A[AB}_0[ ƪЎ do' rzF"p|~ r^Y DŽ;_aϔ9,q(2bZG ]A6roa5X]QA@Sߣ!!Kt,dL)iLEaJs7Rk) ko8dHuN+g˶C~#قɶ ?ݷ%?=~К*ԯKWOA^xh C'. 12-1 [B@輷e"6ן7g8{T17f)m[:4tg?c׮6R{r$l\d3- RF5h Eݭ(x~"b#^0ݯ=QGl"0\%JRB|lxb=#L''HV6Ͱ0Qq\ݡa`  #Tgkjʇ  ʹ=jt'>4i$}Էȁ Wt\4rϘEZlݚ / JmYgswg{7Et$77f4$[{$WQia '? 6B7pZm۾-/f}<43gʕ{ ƶ\ڐW| }e$5$]~4 z9}H{}a} [EI*$P0,wd6_U99a2E4Pr.7akBRHxvZY0W^Uy;\?|͠XO [C2΢_&e6sǀPZ ,(]%0D:N-f5r}<4p'K*  t'Wˮ/! - #ܢ_ѹy& ԭs3pԅ Џㆭ{O1 G(*.JkfȲDJ[}ހnWvN9ROt0):76彜WM)U-zǘhvB`JfayE_Ԃ휠^2m(l繬UDE=X.^B9tmgM̥L4FLa1@™bEa‘`M(\ D"Yiΰrڽ呣Fw HdO Pz."P\8iO֒~؃@QSJ'CYGNJ ;?HmbT"H *͍My ˤh B!_xbɒC>`;ҏ z>@ @]|9'$EPnwϼ|LEGVuMM]beOnaYGgBGזA8 DɁsд'zQ&l}P"߁\jOTIH*2k Ja:"S#Q=A}JTKTQu%h" ޓSl)hXCKȁGs1 c$0+ܯ5jq0*u80GnZRְt5@%h8"++];kFڃdm< hNyzN佚K ${} 8.AlͺO\}Ն]sթHhlPAjWʚT:@#%uOß+A2*dt(S$|ڄYm3 9&wbfTzYM) ̡uHZp23OP6<3##œpOTEvٸ 6L<~?ﯫ FmE l_O]*s^dں@8B x$ <)ٖT̼D6A4=(S!"7"r~B`1=!{bpP߁6oY]Io(MMEg;k0Q1{y:/˟`,QE"^3G\~ſqێ6*.~蘯~'؝_I+esyH-dh Aw-Sp=S|@!*?ՃcqN@Y.X[!,Gzw} x.l-?Tj' EP>iЪ$`N*$8DyQt&@+֬)ߔ}Ko+pSU`Ebڄ8 tխ :̵aD"0 !KaXYQ83Y& `:̘pFiez\8tin0Os5֯'{^p0\| }|f{}6 -f[&g|U:j^1FE |/|  M?˗~/ 5y׹%/аfn៯ ˝@+}>#S7y͛b6:I/NL53^c:- '~.DFAN ^ɞT}};r6\l3;n^kT85@Ybg~f8a0SfDM}(gЇdA7|/D yс`qrg4 eAJF\SYe ংg5Y=pOѲkz^qq'] N4٪zQ%bˋΨS[ME4~L$Zɚ9)Snz/IIT=gϞ[jkVoڴrݺG,yqc5qi56Z0t͕v__ڵKssK}}KccSmp.~:$%Onչ},Čr" \y^m Ou{oLҽj 7K^xl~\SGW*g)bϽc!8S];t:N򸝛x"2 q K@)"Dw7 d~Yu N@ϴTp|VJTGȩ2Cb4lT9Q?u"5u(qP"M|!#^}Ӟ;a?/zwMMMMu{xjߴ^]0wnTD`^bCMN2S9lMG7HC[wD8:~gL[nޫf9@CB~T=+IZL1BH~}oQt~vJE+#|v%;ܱ#F$Y^{W]5B x~ؙI ġ櫢\u1,; )AG O<;>k>| صcG+s[re[%8,2~ 0 !5}{k]30T'=;bh2:ق3l78 4vģctrT.gST}E I#o#ἇ6e /O1dPUjs(} aB8HZ C暴n,2I:pPmm}`HF)J$1G޶ w8Xq&@ItqmL&yd<&([J2e.@} ׯp:%_d.z[xb]߲wuc4"lmݴ5u²k]}{4ycj0pSBo4t.Lr/g?Ws8K;jp[4TX˰xv+ @z' }(kbS$'./WɊvtrq AgeV sr_*G[8C;TAt:(/tJ_?Mo#Ӛ1Qԗq!" Kʶ}zeٲd G.u9'@ ! ]!U*ˀ0bF!VM|x5_/&㥗7m}ǎ4)6h4LF5.][ZLoKy+",3q3ۅǝ[$pA~0PIıP-XQdxLVR`/iLBS? nL>SN}+ЃnOup#,8!2I Τv^ o\"k;wء6M8u55 ,/`$opGX2|ϕpmuц83xDi0MSҹvS=x! Es k Noҋ/.6H胉7} %.]PXQL9gGWWUg@24q.hml^N"O'_y]_ΞsNÿ'f#Yx^3]8boi^Vߜ]>wvRz`ٗPǟ8 W67?f=ᤧRZL9 hQ-R#C, m:4{$553qTS QLWg]-Moצjݺk~{;?qǖ-[3V!R)' q|3$LC}E2 MRhТyލ,VQcCxZ s!Jk̎Ǐb<Ģ 0%\9=p4JWN3ڵ@l䪴z':qJTHvg !E 8pY^@V=/AQ}m͝33~tZvo_\:{m S ($" Ff\F`lbҢ5BnK4QG"[U'oSUtJH T~XRyÍEK0\Ua8iOp55UW{>}YeyֈjKR@ԑ?vl ߲K| DTrai Gs;={1|D]ZQ’9@ۯ"Gjv:k:2ƖU͵AEGvlY*QÆM3ۺˈ7B2R4kV ,@Q9ﵑ|Ad֧&pfBY #6AkS=kMnd9C\5vrKU:|T8ƅVAS>s#A`H>Q)͜t\?V@3OI,-koNAQ-3|]v&xbG57m)/<9%}S/zĠUB:vC eA]q}QPcY pĀQ{>U4CJIrB.WsE5CDhM~K׉*zh@5oM}̏2hΤ{xѢ\WpVYוpL>COJ5D9W#˷cȄej*)&էcg554!qG@?wĨ lJ(ZJ *]zZ(LO$Uמ3޵;f٭[F rQM'IAt7⭒ӎluIZd*Р $1Ij-8M϶Cv Da}\_]l^2Om&8{HTYw=׃7gY רAPȦNf[SL-']ŭHC xugѠ^v z|WmNf5ݫ년`[2G*~ą~⤓Z5`u_wTWn~VVd˘;3NUA?2ч!(J[$6w۞D*kD(YM$XCk vADpYsN΁'H,JM[>fS&qT%={^\/^z{źu歔zz΋ HJ: fݡa^t$`}&DO̚ C&_gETJG׮1hO.'8#6ɛj4p*;)ñEe@8Y]qi[+~𕯞D*i0#"I;E~Z _>za!Nj/=:[1c@oCQrP[q;3BY!pgiSv>Iz_xAlO@o~ BHG2ѽKMb_]eH20c:Z3h{ *[D 5In&"VU! KA$qU/pqew|^;fWtT|FUaHD'NdŰ9r[>\O>+>brcmSa[t0'(í_;Ǝ{[d<-ݹs;*X6h`#5z xM^zsi؟ǡ}ا['On-;BɠC$v}o*k~BM~zi 9 l0s<;MCW2llAcnwm fш1AiuK}*` r 1Tp8=Ā]wOvt͸~h%bSf,F=4~\ TfȺZ:-\hU!v_$ۧ~ַV;MOC]y% kg'jv XǑ٦瑛 𕑃Us?ѳM5̚:أ*us?dw}:蒯|uҘ3L2Tz`/NV0d?15a}LHGSeEh;׮Z`R@:l2$6åwIsfr otykSDUtD΀c~m^@ aŤ$;XQW8V==J*wRՄ#QJ0~T^[=[ /؞ÍXˍ 4QoMT?w՘AP;jѿ%s里>t /w7m yOSVW R)h`jMi P 󆋾8W䃒)'KL ŔTIˌUwey1xVĴWĝA?``kp ҁ P=`1V,gQ;ԑ2F̷eY XZc$|Gu,/~TCԾ\v>,dL6)Vv7.OLy8ܟ3 fJEMͻ0>ē?hij0zts쑓9v%rj=5iaB~M󻎞q>ܸ_w}{鷿3bАĈ$r82~nD p< I%iȼ& E0# ! %_=lK ?v|JccàW]nd7e/8K!7cʔsN=|eʸ ufLܣ[i( R0GĩL#16gP5kT[}I4 esu 5'4Cَywq)zՄk9X 1A':[30v8 Ft}N ᶛbaiKݘ-D(r&ȮPiBC8:5q`$(M%4YYFQ_S(8fIA`y8-~րoK>-y2/Ҕ.Cj.cC9(+x7lr#s?.pyMĊcn 5BDI N"ڄwj|lvYq-NȬY7tM_ʐ>KA{E47yt~mǿHeb:۱LF,dWBߋPXbG oR+;g߄[4`epE]=h*GiJ%Wj z`.4WeQ *V  ذy˝>xַ/|_ɏ`ٷXQt7fF˨6N.)S 5=nNR601bzb֔) ~WPѳNyONN9Сê=f??oҕCc87T <5':[iS0p慡wp^7\O缆p//hii)Q˟ "7%;zއ>Գ>k9tG9SAcp9-h=_f pa.q0go+3zF*AA15r8k`@HT\zy{~>Jqƿoׯ Æ_jV$! j q127B+H SˆOz@ڒԗ j%t:$' !T854L֑TR(!>{3٘wRkLD0Ë3Kyv8p6uv dҲ >"L(8$!k4AkԂ9-dȡ#F4ŝaDpf%#'hsYm+ 4[ęZ%5f{5+9d5pي0$#ʥq@5rL< ". sO!I'N<{:I&!FlgU^shǦh+l?kLʦ$GHɼZ("|fAG  _%%5(5J`oWI*){PPNgw#擟z?͟c׮w=zɧ|x괺uЏ']Ҟ+v}n{Ʌ׳l }c!b+zkc0X(9Dȱ4n˓OnkFz9׷ Y^ԣ~嗶~B}*#7 O0{zBGb#|x1;X4@>}ya`g[}7.T5ߘ:C7gKZHd LFa9h{q@f)ԀxS& *YV{d`)<Ʃ ]wɜ%#p!z -N?7J][TW !+$lW1Uڤ_Isbr8K4ELr`P2O!Lw> EN!}^y.>~|mn9$mc 1z0dH;g4WB"@5>s_RI%_?޽ :3-V7x# Kl[L?;!nWًoߕ㉏qc1I$tR"zkdi֏Ry ;vZ ,;Ҧn,q_2 !+VhHZ6CÆ4X9>'@|~oEq 3C ] V)jNuqX)4?=ԘF?  ʁM[kWW&=@Z ;IXKW^&4\|'FT, lnFeqn]$4@UYwD9qg)h8.op\h>e=G-My .P86u7?裛n-s씣N:uc$vEkH$!e ̻;# w ǘ\6#HU.]_=ZOr*ff3 kQWg^|~sXl {M㎛6abcc$~omà„R R;FM(b[=O٥=tMmٲi֝c Mݚt޹{SsbڈC:77 L`QKTqOst/bSWVQgvbٯ{a0]m~֍[lزege{ljNNr1;G߄o@Q'AC7m?ȳ,zD{bƍk7n֖]5tkiIJ--#?a܄ĵP84lo B=\ܕlЯ946d!?sJ>td1´b2V E'v3gUxؑF(%`FL[@_vnĥTJ]WHO3E2v^0r\š% ɟ9l{V*e Rf*- $y`7 U"2RJ0޳Oyfm *=3'({Z?bذ<" h.]KwaÍ2ܓ3CtpK<{vq'xsS*JvdBF `-61pKaj$,~~i~!UށYyzKȾÞ! \=R="J\t hflNiD/ovO:asS>/?{egP;v&f՚vtD%ۄz|]ps; 2!WxAjV.پ|^PPgk~ n6 7JeA *x>gtM(CeX<&fCSacNHA"dA ԃHqA kt=C?{hۧ2& &+ 8CfhD$]eN}RQAǘ.f I?1!1YgE OSSgdH'JL4Udš Adf4/ ¶OIHw(Y 9ØO^~#.y|a;=FL5VuIpaG<w/x^[|EBhsTLP"l@"ˈF3)$8 !ހ *um7t3!oa  V3.ܯ[ aIfHE=~ߊ{s@GÆ> Ц8*d 9KCpFC阮0Éie :p[ĉձHlALfփP-P(At]s9) X ` 3І'VI(|> }²Fs`AzniwU O57qzzG_yk>tܑU /%)^TKcӴ1c>g|?xW>/e/,4G=$Vg]M9e2!Lf&#@@ J"1jA*Z[(B\K*RckIKE*qYt E  g29gd{g46X?~>Ͼ{Z*VJxsO2ڮrP :Hǂ@ lh.+ʎR3`:&6%>Jg{85Vz@JԢ&;/ |H yT֯՞*?SE/GI!zP}dt `P3&V;kK5}#[H}U|_w=+&^ɥ ˳ڷFj`A~"RXQ0i#c[u`ZaְC)4w`:ZB+aV**XdM(8~0m/Z?"I"]vK6#%JɂM;5?9lfD$FcϦX p\wI8 |}ۗE3.Z E~ ӹ}A-Ja2=oݹ;4R_SFh?"e1K!oeU+kj;X7v7'(mIY b3:KJ|᫆MZ8WB̔cḮ&qB?`]-VCGwW;rydu~.˅c-և=* hC\5sqQ|ހM: x9˦4C&n\`yh0 ڮ)fpd 6+vx_4V8>_?vrk^D#m壘;a*S=lJEH!]✀r0 |'[bXpARq&yW2u%G>P7hEM긡%XTw/-#C(2gExr^LdcQ$֑Ffp8ӎC^hΒiGw P|Izث̌5~5m˰ * 6Vx;HtjUzj)@_k Skx]Jd! \eݭ2I}mo- LYוzg5GCl&\뙑7}zn%ܤh=/1FQhM/}.QbK `]ɩ|E,kI i7[͋00hz 8ճJ(MO0ip߬;i1e4~=^M=u77oaz-ԴʄRLS}LҔrv8#o~sf8MOO|[jp[mZ S[nO^kO:# qJM]O޽h?kId_ 0eS5dŧF>YÞ}@ Sć1ޫLǜ$p?b?); &;u N Fu1skY5{e'BҁȫU"qԈeacQB3vhX^SJ?oZ'otXYEظ/@>L i8lt;  n.V]{\B?˿+Zt'^o&y  ?lڷ=?zի S7m?ۻvM8 )5IDqj6$ϳP+Z$Ei/^Ͳ F`luņ 2z\q'V 6w ˊ,xɗ%_5~5mG %-ʏ۠m gL}7fQWxpzO>z'ϖq x ӡӚ{kjs`o80 sQ6l"4@\ty  ܫ ?b &OzbUye'Up?pm t3dUzF3/ny8Dkߩ r"2N FAYExQɀ;6YZ䂼W4y7Ww' ԉ7:5RڛI4,5=>PW+ܙML86Yte%/mpWנ$Kwu.X>*cƞ ̳;RI!|4B!rQBk 1K*B@Z:%<|Pw7|㋠B #29/y>6]Lidw;T(ZWb.׬Uup@yO_d9xsMTK7o2@*{C@vWOg.Y̮]v LRäگ (#9{bVn,աRX6p R5P;73.~v.-T2IS_! v9; ļQfKSL0ģ&vϡ`}xw~)O3gz5S[͘l A.^Eo}n3,ƌg:WI6ܕ3Q["SЩj$z`~!c.)Ȫ`8g9|6~fAT{ V< skf.:oh;_` |<]5lxt ;X>CXAk!ICBcY0x6HG,4"DwQ#Lh14;a;U4`M_3!'~J#gh6~%yqܲu""%$&2e{,{g{(^juf۟g0WHK٢myM|!|Q@9`eΞgO(߁e{826&:?nʲd M(`B(B ;RÉ5OȃP‰ ϽٔƏOFzdo/q~rF5<"%@e,wbqB>M7ai Uo'-S ^ 6Y9C(!qz8NE>]8e"-&`-J~M 3ˋCp",PPZڑkQ2bm :/?8Kp f4|H: ٝwk?ILʅZ.9-zL逷#84CCܗavc>=`7B1ZXÉ 'ݞ=']PHomsN|Íga/ ÔQg"㭝G%cfPXc@}.}ZK&9kc-M5?97Si]Q}Yc[x h `^EK g~-xZySd<ֳ{7X; 7Xog*\h?ZoϹΐ ]7W4tS| O;t4g}_.̌0Ac]0$tQA*)9y ٮXp}oڋG`4uG?glPDaA^̒ZT03&GMD0/\R!.r6}"S̒Pҝˆ*B|#0r !E@ FsGyesfuZVRj 2`Hb"ZK_c5z6*}Cu +Y VS~'<tApmZ`0qp|ҵ af;<ߤhLtz7Z|@#MmZg)\RpRdzɒyGe<#l&|LiERB6QywHJ/on8CJ\Rt zҲ$E3'N-Zp*~-Džc?MJpOX8')LAN:{q'7A`1Jf|@j[.b>r@.ukj*rJpZ uAP_C1[[XG֒׺(z}_~V6g#$,p ̠=huG[zRɾB8+]y7ҸRRJ ,kmYP|S&@nPD9,:CJlhRšA}5Vd!r=ʫerU$1BYPmD=⪘#~9B-Ok4a!U Z=`̂[oz>/~3:Q39^<"d7p9(iqm'ΰJʙPok~UMSy?i׏9!~Z8!Ц]? 3D(3ՎA, f0qkU\98ΗAH8Vʃ ͻDΣ-˪L{Yxv{ lVG,  j9mDYݟ7F<!2J h7e/6,B 8}T) ^*̞b14g ]?S=9$ F4H5|5)D<;6v1|[Svqr}5 ffU`>&>©>\T&l9$F̓ DҞu *W'-`$!69 vD8&9$64g,EP]lEr3Sp ^R#fG"']@ e, ͨ^.RR1(avH<=1puj(@H>Xv%^˳f12KtPpC;ju4(ްRllm1>he?ʼSGTT-D9!3եAb7;OZwx$͍ o\wCo _\u.-0:B6o&)؃r9%=AȯeX2%'6pe@xPK;ࣝG+5~pzM#-OP×H].lyRN$ #6{N@xCc pLj<y*JLxk#{ȺA?Z,R"#:fUg񣳄Dk,tF֙&S@MI,B`.fd;XfzMvR"YP]Q1 )޻ jE}㮽"|OO>^ƼȪfMKh,Ux@ CG l6c ̉pA3\n2X3ݼUs݄B0Az!mdbw5BpcKo}ҡ3} K%H:X 1 `K{E ;PfܬBcR]ɁO؀ 6у sr6c{Bʗ6RvǣC9;~8A[HOt\!t٦Gk{vD8:.)gtfm7!-lҼ)6*F**D8lD h{f NfFКi$V<ײd( 0 1)z$[6 | :zp]?cDjd;z{4[8'Y10k̈&i C)=;)7䧹K~c{;ȹ9Ǜ;`.jv5ޕztT>|N"r80l' H H94 o zx u?q#&1%IP EՍfZ ]8 i'3OCu;A(#;beXMU__4*A@ѥ3-}'CLF}IX+R#^N+Y5s4N?#Ta[<Uq⠽aeJ "\N0D},c4/_~#?=Cޯ‡tuxo}M\$Z|.uS @IJ*fkc_͍"``4YS%\+mKwPH9KLȝϣ7 4|kFDl)iB>3Kt |%׈ r%xϴ yUL9Nꋁgw̷Qr΂G4kTH1GT%.E!˖τ 6f)(Ov$ti}ΨVѾb_IYA$BF$ݫ``$,4/֢@AM ~-7>~_?ӟ~zY1`ٙ+???gG_7^ˮꊟzppRTtc9٬? \Kzo4?3iظ`%@昗p aN6JZ8nb恽 T435K4 ~VQv[B OlA= ^@x]n/1~yNL$e\ w,#V;ݭ-.7D@ Ny0:T]7ĝvǶgʑs, AW=90!ym +Fp::VT͉;'[{?O= 5=#h _Bz_mw}סKo)GVRk.:$1];>&f>l σCBD#q:b[U4eft>D[mm2ԻX* O f(cB~r+TbK!X 6v& iW4qFC/6$q, %%kk8l9ėN= I8xo+ޫyďCCT y {*,H-.jt] & x‚nx"7eՈr{1rͩU)buA&;[U#0, ځy\L*sF%h 5T믑SMG5uP?:Y7^ jSv@?UE ,MxEv [d迈rŶx2,޾^߼*_TCyI`: V)d.ĥCXF5Kad__z7zGi;z~_ZB,B_-+ZCrjzԤ,-(b- ?/Qv-d:P`ҢY$ESTIJNt%B8 SW!z巩/LXjwHeKx~볞uv}Oy~ۿo{+~ϸ㮳l/#Ͻ|ç׼˟r뭇nvdtdvܵR;OPŒW7%s8q~?1ӬER3Q" ,ؙ=}$?Js@ĿV4.O ?mX:^ H]39M'd\:|u|DF3.Ğoיޙgk[RUɃɁpBӤV |\A #(Wxu}R4-6K@!]^}vNdTdc K#P֦)۩RKTV9B9e$1~bQĨC! ^zx<̲D{qc'ju-3؂LHW# R1VOd{z{A=Y9%N >l f'<WtSw-p.nG(UKm pzA@E p~NJAYDC`K1($~0<)~/}=8@u듞|M|o~?|?{?|$zΝw؟[ ȕH ZPqɼQ TS>a?Hҟ 'XI2 z3+|2oS`OsXWQ eP:N0&c{&'.~bd!L:wZZ[kIT|S(s;P;V ?o>OoHujP g ` *BѳDÒOO__Wvݏe>;g=i?)r~7A#`l><.n!DTC^psKeγZQ? Q fBzm9P8Q3 PMkӉ=P"jQp@`L1=BXi 'rA::n>'iZ s_ؑoK$R#2  JWM:A"  `B1Ml3MQRѕ,{=6[w3M"ܫclC\#w?9/5@k&\x Bh)!@s}SV3ɠj\ p@&=:؈6WPǠ^Yj?@݂zrWC}1H`D$?ېXdu`}J}ld$$AY죭7tVt`V +ΐ) h,ׁgQ& Ь,KeN$Uv`h\5I.rѧ#pT"+opPzhS)KwIgEu"NC@$XF{Oh!8 OJm7+ r]?1Φ R8,z6)ƁڬPWq\c_/~7>l.\{2p*C^}@ǎ`JC$=5Y`埶f%B7Ii7ar~F,8nρ ]+p|iֆHsR zA3&UP$b%ɁK PЁEvoPBn{r@(B:: ι6D P! {UqQ~RO/ƛBD{H"C`&H.'6tÆ;ɼU*FcUl ;owtXߗ< 9Ȍ⒧(EF u=VxdiFKDKc-:P3oZvuZ^Dp'~bB];Pŋm3 rάSPĤd$*aHպO✧GDYn/9~u!@,4~)}| MĿdHpcie>Zq}m'3fo—r,dʩԭ$r՟xk ^E 6DA9!1UF*4;/Jʼ۽ HZ|_qeJ au'ӕK=fIJѥ8/JC\nNW >K%tHuySȓ\wOZ5) o ?50TOwqG.}tK/6 f@@9Nדn{G~P3;5_뮾ʸ ވ!{v*~aI0v;;?ex{q}@jnkqRBv_W,?o( Jb;J ÁP˿> )xb~/ozWW$19?uf}LlS0\FLIKay>.B9KL@ 4VH##kMq6\<[,l?=HA.HLG J@%N{x(ٷ[h :A |:=f]'o ]x  c7ޓS}㧡)(;o0f OH9WsGvi}jz(ZG;o_ncLś ;(w,:^\p8=l :G5|> NR>!!a >G=~refA5$/nNdgRx9iNΤdn(CWH+$qxZ°!'Hx]{TrtxyNƨG'?*[`x@ eІ8nJ!$U#){BЇ?@ Tq9u]d8tAFw' l^a=^dM7v( G+ 2BԶGM;&ņs{TtLhNX2]FAavV`79z";ih=`/GU_]pC ÿ^>%N}g^{-eq75[{na.wp>lW|M3G7 Y:2}l5Yg^#R)>c(PܭӇwo h$8M7>]& >u6:t$N2 Qo %BYhT`$;.%>GNMK +U ^}k8??K^vuךZHݮ|!?Hv5J y"V6(nBԕy$;v~z 'i?`ߡpwxӟLaР g_T s`Ni܁ěcփhş-*V^<9n]ً7Ȱw#۩ =BUJ7&=?<П7C^֯o_{իnK?7ԉQ ۩%7}h&> G'o#my; m"3eMC}d[hQ'{0"',>=I%ʸ~4vThHL,@7K5yG/l+  7bL 8 vj-я?ŇBJ2k.O[7tEyvYhKt1}u2KǚoбzQpx MC`Ém3rm0lx6Ne&oR7&rȴѢCxO uZ Aθ=zmN/77 ?~'p+Ϸ海$'W8sӈ5`]sO}c4,֭zݯ.J ÑގlP娛Ihн۹QMLqZKf]zza=n5Ǐ7j3UJzƮ=~2apkqVFK1}cx J< QU=ۦ|,~Ϗ~6k^_?n1 _GDw d7U3,&ڐ;= (|*(Rf2[x?_ݭ6/iXHur^{+%q/ ΗƵvH?KfL& /Y @0wJյԝch>#,~dvvJڛ]:G#C\HU4`:9e\YP+qox~@3Z$#%v+yh4>t!XvT-}Lx;lux͘ACkS֑kIgmߑ>|aci}1q( $ߠq452Z{u[Q%E0Qx|bmFG抟\%c?x?_G>ԧ~կyMO<ؼ{M&ϥ!zxk6ZK{ 3E]P;6t**O#zbOC$xyQyu!Aө \@>98]f8{e7dӗ(ؠx2|sHuZ?<(D: f)i_ӦVpeX%;P0Pr`~Gx3I;/}7|WtMx-?oH"2JIY: n\}(Y 02Eu`XdҠI^ 5/Yza3Nɧ}VNm65JFMϗ!,mW ݯv0;ŊY~c ёzzI)ڋ\HYs{czc9\w<^zgqshpuƹ?$Sx ]c҄X61>R_=j!$AwC8!Sl(-6R1wvCJxW)6ؘZ7+\g(S,Bza[I m?5 !yC("@mIz۰,G(XS3>n!UF2dsַ7W>?~ uĜz$~ސ"'ڷ 'Y߇pk<;v Y2">oB`xߥf D0VʡQIN~;GCv݀M[InI8bb}rOz˻xXz[@&T9Mw7iYd©J8,T[vpInG$eIhdv.QȆ&_ѿτ!?ٿ狿˞g]}U{% ֗|\^+5K"Fɰ9G# #LK4.@EfL'\>$a'f'vE ./ȷ(D.Tց{ku;z\v?Fԙd-IoxJT [Rn-K9BʝTHzq cApHG;V|VeH hdT__ܸk:醂/ꄣWGv,i~# s`])(MW?!hLiUWkofyɨj~^(0蘝co30c^w .ą uW XHx<=?m&9d͔`яү|{~W{E0ÏUqUW Ϲuz?ywaPq\-oC@.>,`-Q}زS0QJ ̢֚aa&ɼzuv r s1/h[V~bl ёCi| Cҋ !,װyQRbv҆jKB1a:Aj;[ 21b$ ϐgY|GێrIPяʻ_|;c?O}>Os>si~xrIE.?6PG'}St%ͷ3Oax\T+׿W_D͊?RsxgΦQ{|~UQfmwht}I"İhgvP} -Te{%VN*Ϥ*E| :3\su9^wK󢹩䚱3Ǜn!@v]i?ai 63q.>?{}=}xO~7'zq\wõ7<ʟoysםx퇴bֻE2#yԤ<~PmOqgP6ɑdx2 M Ib2Eݍ7KMMƥt$:躱$t1U ilrdhh1<ztY R=ߏAOa!ަ8{Ė\PwDPb+`ޚLNY`L`Bs˛t{1&,ۉy^Ww}߼+>]^}?R6<~?;wxczDH~U ~YSXP%CF@y O+nw:92}p)!|)hB(65&_IXL2C  NmbVRK}t"V8ȥz'R;]/!vT&v`?Wyib^0Gm2{p.}ro{ )as%a;Z2x2b.Pa1cƃ>%-gj 9 iv _n14 &Z H$(xTw U4 )MkYh]# &|UdJijNƌѺI_ѫ1"qI""f(敶Kf&,BRGևQ/P*b=~z .Kp{hUgM#PQ8\yeـBiGM%Inv0+ *~%\xǹEi#Iq2y;0kA7V`'T0K9;uv cIk~F' u؋}6F4Wo?Nv%ijJ hBB,6ϝmz`G8; ,بAkյGD X]9j;^>c 9’$$BWJx;O6*m_nX9*R\G4\oJ:?./2д ߘo|hF!j[,WQޞר֣AQ JDM#::C<1P&m#_OI<4m@o0{׮(--ּ ]W78~yi }+޶9,gҮ,ú=+U^<ou u!&#5ȩ q`vyT"?qSÚvwpz}'|q4Hh.~7KO;? ȵpa-Ax_z ։7AI"dž? p*#BnHzX ]<:! ϫПom8h DឝuO;(`7pB#&ͨCv܆.C$N[ǒ]Jô(d Gw¹' |px$h@mCPvȋQoowA276^-v[aC#Ֆ8zZ{0kQtor(q/ZΚ/_ D^7.[/nWu[_\r;:/c |`pqaAٍpL93KVgCmPfT]#sUh);UU8Y=F.$*9dk h7t(N!_19AuGWaܡm ѳ?@m7P뾞>3j\ǖyYT 0ad[q^?J'N \%yUsndAyfUɀ.`7(7!Fjz En&`lu3" rSzP7D8!M4u!"\-p}KYK!Mv,y(7nԝ3H1l@ύ@4U6M+VQ`[ѭΌu[o;"絝KCa4-0h7:Y"a ..Y/I//e-0k5<~ x[OY#LXY۹=/?GzG>BzpȜ=h6-Vm[P ? :{3]h3| ڠrߋOkND[6%whi -]Zj7xx[#:+{V^P QνCfvBgDn[i}>Li^> 67[z'cFJ1kх8#e_w(8;PA SwUK4(&qm۰,}t ;|g9p;WsmUa]SnX5L:Lh`–#`dP\P͏+<#WK ⬉F!Jx@nj#3Ug]PwE@DaW5\B7VBP5z0$Ib=WVkN˨3:UU-՜9NifX]n@Fc;=L76=k@5HTP0>~|lZ9{HI?RK8pF8:N0pGfXKՙU>1F );yp :(9'9~4Z< uP:Pi:_#trғ!-h2eNIo,dZ`.Z[ VipyIϠ,'\(~K)fg5]!"z5k)LFA#}Oݬ/0wg~L9W~VaDi4!]lTG(tS9@m0ww ]HZl$9k:G`*/!}Y" 3 !AV-C >2aBLG>z[&c00tFzyEU(PJJ\cBZ[EAN|y;]Mb]cF&1ܳ5s`[VH^v}"Q (Ӫ~@ FȚCOM=)ZH]ؑ@ӉP0q!ݺ/uDm#bEfz„Fc|II0>akqzDFS [o"Oxf\Y?4҇xCuKQؠ l)xkL7T?^7kIp Ŏ:;Sux$%C#?tM"I0T%I"6h"@x/؍7DFH4!Ϻ޻K̘# LbJWdL44?Pq_qtc/r@!͔\FH0CA' (F4˻vBW#oڠw Sאc>['[^ӓ)[Yv=)JzZb5)[s3axc"(YfQf9m>nM zgG6 t Do%r@C.ޱƮ+!U )ǛzJ~ Vy57 ݑ M%6o ]͡ 3릐Hvי1& "ЉOB|@1љ[r["|$ȴAĨC4' 9V=2d{iĚ#E¼1móKVĉ ~Hnݕ '5 [nj6hq22 v63/ 80uݞwu5\s+oV8TxbOHiSKz QNbgSRw4s1V@?6_`JhNre煊B=м ļ"˜ RMw'*1-gm(;\IvpE16P]Y3%DG` x<Y!hCߚ\g7=tZh9+oMI 1h0+7}bkUiU8&V$h-ۻ;U'@`FO @N]frNou8w^NYƺ~o$pY ذ̈́JU}z hB45 cb 5jYmm8(DQ lkea0.0ڠGy£΋x2bDcð +>Ə&g.yif;2_((xì %~  M%^ć*"DC4I)]f O;РI&!*]tn{X 9mML J10>L4'GzK9Ov" 5GDbK!3kP m@;!~[Db(TT )8M, &IфY -)tJ P`;wĂh(?Q8yǺ(r(ނ1TJP1N6.ŏYp U⍝2bm$ )DAi$r!(T  &N OųlGM80+~9 عE{+~PKW9 oEiR#-Z!ԩh&8'\EbɈpv5$wSkķh}-!ddXert^ E Z\ g+2Dע&Âh=;39 ʖA(#@&}`mI+TqCm@aj]O z":NcϽIkAsBM,Sz}8uh_ൈ4ϪvďS#GPpPpW1;(ry$fQ{3Y'ЋOvx?ks܏›jB@-~=F{į1~kpa\3śn(ҭA{*[e@Ҙnp:3~#o C 'y`2[%fRIs.S= iE[~B "6ȴ =c Jԉ0ilNn 6h|Az $HH*YL(9iSm)ϟU 16h 3GwJ%n| = MpOO꾅.[VWsYS.\GEܬt{,5@@VN*?dIC&<<ݪG̤w#s~Fx`~M#Ji6lt^C-;%CpKyyuXX-n ئ[7HI,ď(&gUNڡ}D璠xk ek6\I4Q*)tKl{6YT@ҤL;Mw^7ZbOI?ښ(haG1o (3L:'{N׿CT+^)GhNz6oGq1}(Oآ oM]BAQ;9.~Z^x 2Ѧnwn~ qҼ:Y 7gII!B/8Ke?Y{4iL,joi%#&D$v6wDn2.>V e(4id bW%@{pgM?H|7F(e_ًJDIAThD4t@MaXZ/G8GApTp_ 5:+fuҤBXezEfp׷1z60Btl`4m4 ?@Ď^nȔ/Oϗ<0{ID FP" |=o*119QCG޽n1av 1h3O!$C>jfBmK2V"IKIDP`BB壟>=.0TȰ!6HEv䉹њR 9S)4!vRvSH(cs"*厗OC'R8[5}Ń8EBԝmqlB9VŠYh/{0+@Pf|BF V2[~##Y "٨u<z ,Q>9`jfʴjƙE!hEA4Gxp(}?p@.\^?l6?ee|qߛvS(Il GҊuA2>0u'`<$8h4(u qX/?JHZt(ًhcԕp@n^NP5[2 S '"b%p@C)F"bBBU?Y7/*_Hsk^Ow$BxtDnmTsȹ_Z˽ OJN/r !* /p ^ |!|`>mWrLw5M|՜}z²P(3Au<?+Ñ*ݼRlRxi1*%<^/beem-${HI%$ \'aM #+ؔ xRDtP\Է,LJJZcZ5&ą%U }b~hМfio }qi϶lЈ<:b4@Ƶ ܧ:M@䍢2yޥ`g }sNӭ.cø(Ő&"#A26J(a~_|fҚ`Hl&.GYǝΦA g<M3oj!(l-(hug%Q ď놶qOW.9;IvqZ<z7oeW"蓀+lEG_`c/Dތ\@% ʖZ<Ó.Hj_&1va0vZM%a|# 䐗"rIFa[aLE\P@3-K紘M`@WFyaw0~Wq$=J,ʈӒF3hl]A{4~DA^3,Hj7ެ ]3/}?FSc hd:K&#,h-@|TT,H`?QJ]jْ8z!lS|Q*>5[@o6'H4Z'r{=@dC'HĽ kְ DQ^0_51l Eql%tWcLg^`ejѭS&iؠ'\H6c>'o-1~@Ek.oA$Q|g|M ɩ2eЯoLkA́"/?P5e߯'(>U6$ͧ6婱0Y_ M˫M/W賥Ŝ/!bjJ(Ud!|^02V1j[XɃ#2'GF*(ii_JnEbpwΣcy6W$YV]'iddDmad)nUiCMj/FiU$.`S}<o &([P7\ g:ޔBNLH+xɡ6Se8iQ{!>R@!+si:v3T~j덅gk Kl tZ쪱SԖgX@)R4r(͘W Q!PD5q +)@kSc'~+~8~2fio`G4x!~ioQM++Z"eJ4- S^r+~*Ə9ZX% Q ^$~BԆʶ/ѡ@w}^Kdi3~?VeWҴd9V. #MY %~LH+]1_?38~O20\t ,qU1+ hЊAs\xaRq̏72$ߏn#BKO#ŏM1]׈;/;O6kl;bCxqvy֕ Zc3!пs v]?:J}J-xL _lJj>(-l?eA-M0tf+";LYawWL]?~I;wV|Qƾۣܭwl7$W ]CD`?&lyT]eȔ_*ZgO|Ww#2NU9V!x!8[.-~JO850 b8lF>NdȺK>=qCR!C@+4=t B5 Yގ" Ia$bi#`KC2r4mZQb 6'mK`xs]#v=ƯxOhoCkt_gHRxB|>V,H@; /~HPdqpj3=_D P  c'NJ3*Zuk%k"N'%Ύv#m1c!HA.<49͚E@=3Spjl>O9 RfS?AP  FjBaLG@b4}j {ag1x( B0a2ե.)VQY1E4c1 3ցN`&' 51,<T=;rU ԘkJt9E+a`pfU9~xD,l T2uDO\{SR9ݡH&O N ] oƴgg`gJh0Q*<5Z,H J<)gZp 5^g"2ڱZSZpo)\L'l7ixhacۚL>_^aF`Ry 犦a@CJ@[^Ʌ$ IT3x;D ..I50XUbWHԉo,<-Ć1PdC4xCqtI$K)׻9#Y3I;f S(z@ng40Us '64\N7`ѢxO"|&-b*c- H :QKg_(hh"E˭ŏrDDSrȅzB\;5F>z;wC?Ʋ龉丝^@>]NV͙⇟$rGm1Th }+UvHX&XnP⍶e{_j9T]4?2ُ?A0vne4_tc˰ŏRv ⩠vt6&("; sDx> 첑bʝ; ?IiYx3 [uDkZ6!66=zb;-ʅj&=)yHi }d 9uX(gRX0n\TG$q7 ctq5hZqq9݉=\ݦ ?**t$.ɫ2&U;އp5 !Lr@hĪQ !Q0\Oܼ"'3 ؏掮Qf5O#ְ =I9DvR2'0#+]!Q_%Syѡg6A?[*t"~ddp:'ePM9\p2n 6"0M["-_G>sw:ސz0>k>Or=J/g{= >@%07\0G4Hj ěYoЃ&h p 0-?f_Dv4k ij;PO>(;5*K}%vś^*bњi0o?,]$?.5sάAM" oǧV(h %*!.;x? x4AX xj(?>Șe@މx#A >tE\^ gQ]Z%+iç]u ,ޑqA{ l(yuZ2 gԓ@>lt#E48؈2(t~= FmA43{M:Ua&e~ A/{5)GA*cZ'!oH_Σ'Uy2͖ZYVm#j@@qXZ$We\!-"I Q0>WyE_IzuAVQk=UNm ݶgX~隟̧Y}s>*QJf[I-~V|NZ`v("4[+wb( ;H-._yӜ?ɘOJ)V5[$.ajv͘!TKQ%0 27AALVVཹIlm'P|I !S/?2o|i@dަ9Yy纛2M4͘ZY#F3~ldx?!zV/dy^P_%JilkJzWJ ًIjG&O%p ܠNw0_>2=.XŲrFn 31_v575Ӥ Fád3+GN0V}"!BHߟSQ#hH-.Y{a} !Z+  P'I@8VV!hWk#$9vHl(LA'-ވCߕ›eP>&l'RG+WcJ TzƌAstEC.ŇebLSG^q/lJ,&J&zw洞 OKK`~1fBCnZH>0:;eɘZd/u'8u}xD ! ZE?ѓ^?S&݃^$ _MĤtSHnLX<`&3,*~"!H'̜ި);b b_*a0)O7'ek7)J@J6dᘰ󑒆"MO|MwO&Sa$^D-Hͤ8ص;BcYG(opQ[=bxkyiR?^%rx| iU0uyrHƛVj]?]U&zru[M+lՌ@ 1~D6慟m?'p{kWؚ/zܠ5qj X/4'}$ \E$PLU,ID40e`٤F.AOVpޓc G p[U'[}TLM\k[5J.﬏RλVRѤq3<,@׎J= q'id*)PQYCXU`F'\)8 l) 8*TȬnF4CcQ9dh1~Q$cZqܠO'(U0u(Q6{#c# y4.a Τ_?,t4."i`B`ZkE8DyѻY@Q>,Yxc? 1oB4Q\oiߓa\[&]MGBJ?ozƏP>S7dSv?NU2O &;̹ir>Ycss$ E+CQt?F'KMtrzhNkCGnp&$_a]zA,W4023߯$K$I$&fN+8{ܓ*O[K 26K>)^a}q/DOJFs4;]`ܣYt4]tMZW\RK'Ly_?3I UG-&! Y )Wi@Ê]/HM ~{ ?]%~QbNۂ )m:kc;MhɊ6H>٧8TR~s1/~^əĒ(<<CF/MJ³۱ +sQ HPZ dsYpRK?)H,?VhEr+z<93Di;[pXfv7jgx2~TQp S$'%]kvu[OEf\n+(G ~\O{ 0PکZ`ZtL2TMYfx $2KF7M)u,?O35^OR.͜Go+|0=/;`BYݪ7jOF1>CA@ct}}lCyy`j@\ l))FuJrI "3A!\(~p3 s7x(֥ai&ғ򙻾 pA^;#X7ܷW#ShcCb쮗eT"\_ꮕόe~:@~W@LGT ]3c?#j.[OCg")018(4t}ugspϕ`{SA羠śMO5q(+=>_Jx9:׆NhBC-,]Na (AxK   Z1XLLgU$5!U:0Ar9OURO}^v L^Ad"I]'@!+Ы^/tUbh eB}k!d'crymIPM" bgգ*mdDGafF¢+{A(&qWwPGȁ؀>k~Ol~IEX`+A0R f,|_$|UHmueg?3 O% zzS1 <`t,^ZQCr( - m.Tjm Ā^cLQ7HBU_ / ?H0tg^BvDi< oг”" !='ȏn/!DAD,C.VEԖPz8yKH? j&%jD_ab L,sLp98'P ʊS1V $aP̓+Tg|1||i\@-XqpCB3B 9xس 1TR1jJo# P /ϧħXۨ ?BEYfmn_h"u\ JJX!}<>U/TW;HypȀBa5n>t~! O/*|^5J󢹒!N#@u : &~'y3!Xr_tJuur{0>pnr Oz8 .NRŊAz/TlNXiOqyzs4C]X 5RJ 5n|8*O+@T$M)G8UZ!zc9'FC%ޑ3 MΟ9QQt}xұ߬W%<PoU>pwڏĪRR֧VTbadp`EBĵGvXJc T0_+P.b֩6)6k/[ovr %k~Raϔ+_ncԠ6J qo<[A$XDL[¤o>鶛.R|^UOɹ9UP1x7(%J3}Z Ōi0mq-mr65 eoL4%h]bW(1F lMw%##=?4OɊX 8O*fj:O#-T'f&^?],%7 A:&phkh8W'O/y(V _?I{UOMJ+BZ> [~+prz~+@"/~yD3%(gH^<amA{U^_.G@.cA}õO'Ě%vh˰SW!ā?9`,I! X,ZnA M)#f`5mZF8 l5kV"ΫE+cB͋Zhv/.% $N!5!?wۣϋcRTnfM"eN7V 2?ף.!S|D6֭ďƮhu?DCT/#T~;op_W[jg#u<{C9Q`V;p[͹,:5~.ZC)yw"K`x\~q,xًpex?_گ!>b_2?/Vxi)HeoĐËQM>1M<#p=i W؄+~ :i;K)G銷g. Q0Z>RiuF+  HPބ|-߾լt:J\RGDw&PyQWzYQ S^۳>?;SVW\{?OlT Kc+ہQQUaؾCq憆 vL ̟EZ2xS 5u1M 8ǒQXNUϞU35VLxjJϏAh3'^BT?P>Im2N3J.)-`5_ Є,ވӧ瓚D[\ocW|wهן-˜ Jʼnd:125/|ذa#7\)8dnR,$?.R?^-YWNcbxiYٯdf?zW0nOv*U*?'T@‰5>5vB)z-<~ lC3r8 $R\|X!4 EY #{43ftt.;oBeqߘ"rJx^3l1h-*@G_6Q{(X]v/ }8/USFoO ~`K,h뵛hD?$VF QxH\"2cz8ޯtj4¤OBH^ţށVR3~n@C_/DKzΊRXh=F%$=TKzU3i"XJ畂{@F2Rϊ'`<}O;LcZk'Dy9tԷwW7~ీ Ͽ֓{hf`Z:F{1`4.&cIJx E**sz},|k_:L E5&Av7qt !k<@ܜ>&񶇦 : W3SMz&aA'U>yzƛ$a2>U;~:{N>UtrقIzG,~`*OWeot?'`F^p}k.dQ0 Q{ap=#րls_Gao 9i[~(w>=qL8K7jLqܭ:|$-o0Tu.w6n{}zG^wW+*_+ⷂV?r_غEewFl7kB\js ߷K5tG*ڇ* Vo,Qh=7EђZ3JӸEfR>$3TiA %ץ *ɶSNm_{`4/ǗP4~|K<\Vlns Zg g`d3ZzV$-4guxyrCz+~JvN6Nr$Xjf§kY_yZǣ9xJRIZ~MQ |Bk\?r T!y͈WL"T4uRa!ғFs'~ U(o#*򴊧y~䣉gX/K::$+YE;R>o-{=dwA|JYSJdMCdC+_功tm@ˌSFoKJ`I!Dw1x9?ΤX` [Zw|q\b$On-hWv0(>>۟ůNcZ|0@Ⱥp;6xUU!qM:eVT"crNCB"!#<%pT$TT"fg}rhi:pQKI3o>$*01PփZo?x0o,ŏ\tQ wf^_GLvJ9Bń8IZ.aܙVIɿ+B~(PG2Ghr08֌?r/x&\3)KxzI5 eY~e}ɯф%~*zcEK{ANPF??Jpě'ܯ~2\f$ޞ럎ÎOZ6-zODd|VV2aK~%ΣZ۾ z̟L2% axoGDVÙUSLϣΣR~)y o&)"ifW~Rd)oK7cɈ/#Gqz5]]* lpk™zu~\nNI/{'Bh7n^iR&ZcSփGD(8QMSY=$Zv/68CT]?_q:R䜘B5Lꅝѐ +#~Jf1adY Oºpj V`ᨬ$B>SxTGGkΗ9 qCbV$(l5ԉ_!ΐ@ƓYF\2 Pi̥+&   DW0 Uro\74~.+ 뿐:&ciQg HZ dc6^G&o|vƒ0I7n!ƁyЗxSX=/)!;Ȱn_BЯ9HU }{@7X=a;• Eo6/+Hb=/z7# ݵn򕈽7PmJA䒑.. 4=r=$ ^~]}$x_n7f.oX\-Mzw(rz)=y{P }nsL(7x{O"o'aq%F!5Fu$ ]"/u=MiVbN &B۫C_/|/HR*|ỒaoG}_jLX6>GS︂K!S`>=կώBۏ G^{+!EYhXPk4%,THz h5q3 + ОӔc,SWQ >4y n$\%zr;@qu@_Ij4nVRz&s+BC5#lB*E*'?Qó:#"\n~"F,]hKndƏmɔK󕙤G=h-Wk|h GƏa2t>pVW(hNnWhUs3)`^^=gpqt%1+oI7!4+cCx{{A'EYoYo*L;XW(DβO3_34sNSm ][뽔"oªk'Dj2~f>!:1&S\ zX56㷤\ȗx:7sg~[5{\N%H_Tڅ*]^8<=A9 Ke_r)l[B X?'܍\=>鎌;;A}TvًdP`st 劷J7U3fWf|Oˑ tع HWBj a,͈./X޿M! DZ׆~_,X\Q{:v`INF8͋.pL&D inU ۞ri(Q@l갻:{lүRb+Ι6E'1/2oˋXe^}ۋnO7u[yIyOBj?;P̌_ gDx oK|D7%~^W5Jxo09 첖Q6i}?IUo67;~P{@6ư(A)d-ECas%|CX78uPNCM5Į>~ٯWYLH Z1Ď#H`##ݮ?%+E; _,'. myx'd]"^Eͩ|Ǟrb`x(@ѽUnʶ-74 -8ۇ%7oJgH$|7t .*rI,OZn T:du&cz%πcJ<-/5z#-;:oZ/[}$x_i}TyQ e;!2|0?R^%vy&(}Dx\ DRګ<*&]g%XGvǟ)~R2̾(TqAk&EctTEilsQ45@6۠M $nŠW8/jc]+JX̒qq\f]^A͢pYFv$RU~Q(>npҴJshbXZ7E]n:Ev=2= Dzo e _oY-j>O R€Q{*z)">'PG\'%AcwT+DI=R 7qmeu vZ䇎X{SgΗ Etõ$sWvq$:,cjcvTP-_^ˆpúR;Ĺ喙-гkfmx5?I F(-{)6&ŕ*.ηSB L$f,$.Vc;v87HzS< cKUE58.WѮ z(t.фR7J]lf'=/|bD͚: b+` 1|` +gKEͶ).SK8Pen+ TٽM'Řr ;ނ6wfD.|xoOb fS: =]ď)s5 ?cO_nNyydU&mMzQGxDp%fpOC垦<?]!~4D(#SdH (`F,:~qҒ3R' P+?b9-$%b%!>ڥr{;CbK; J@WDIqCRϿӫ!\`^LыR:j" >dO=1Z!PX> ;={3fȊpo=]Z>ͅWo(qFfC]kD{bdL<1pffo@PH)Ӄ$UNf]g֒o7PM|1ˈAj3TCwƯ-Q0n}sb 䰍]؜ ??e#2ל?;欢lC2)?o3 tX6Yt'{U t򆽔y\,*>k5Eš/H4PJOzH|ҙ%"2Η`$ǹ&Fby= zlө'G#f5X&=#VՑ -RgYg.]! ݫ&m@`*C)}6u?ym()Ld'ިz MEԚ,DF V2`8ڈTBh8l`¶l@d9@| fdz7f9jf 3ʞ܏YzQS H Ҥ)iVNcOBƏ4tWPi %)Kb!E-^Q =J' C[ 0F7~MZy=Hh #@5ަ&E8PnL*3vx+12((!Kr#7)-^|W7,ҾwEPJLwj׳&䖐2=PɞQKۜ|8S2b/);PjZz_F.BrM2 p]˃0(R^J䀎[/U<Ҩ8J- RKflj*_G5:"ki ܁4G:,¡SKXL{?A3Ư, xzX1.{P"@Y{{9_%~\1劷T0nxG`1OV_H~x'LsyX Kysl N%7 A(M8zm'q{QK o4sط7.Zk~4%3/ۿc U|E3忽˃:–k9$`}ʣF7qo$6bSCR!+~2q 754rl+Pc_BN U@{aOEFU!%#z4uM$fcKέ_;ptx: 7̖{:^V&wK)`Vl 0t|822Q\C0XRhzĹ(8zc7z:AϜG>묦#^|]{y|f vߓU溸X~ЯI٘rCg }/{#JX KG@}NSRzBO) 62Iu9g+C00kn@ЄNJ#u˫vK(L/Si̐c T2,q!F̻: 3k?).JZR@ QJ{m'j g]NoGB9M! h‡d=ZhGnoxZKֺDY?=NQ!26[ 3oIHdA^OP怦r;H%oi'ZIKIm 1U5x#Ư&?#zImhް-_hmЍOXjKHj1tݡ^Z>OxN^pU#Riq CfSnLoa2:KHqTdva?+_ܯ܌2CPI#Yb8,RT uwM X瑈e~BNgPTiʶA94Kȃyۈ{tXnBig +nRp G +FlmMkk-OFH_}Zw0P;)*:~2Z~+;tr ۠Kt) & aPB(to+bW\> n" w&g ^/n H='R(xa:&N! 9,f{.>*F[J-Kn8<4bHR[,LPbc1z o@N `Ņ1*iY? T[>jh5Y~{'c v0?,.> M|j4Ɏ6)>r?<_ ڈD9nS-m[Crq +H&$UE\s_=W|! ("Q |rF@م;GoP/ lISX5"p?).>jΗ w>;]NueI /QPVH }qLҗWZ81o{ﱼWTۖq'GcB 礼 +e\9ˣEJ)0JaP+`~m$jO]W2F<,N~ -{*d6S+̽C)9'. g`j VP[&:BHRF 4 ֻUƬqg?!! 1H,uи28h4ArGSy҃g,XRA<ڐ(%-r' J(nEn?wAb66Zu-U02ɇ x;t2B bCN S{5tHK~ w#TKŜ %7m㙀e6? ˷/mtgz!g|_y%Ī*ftMy]Nk^t(UE̢`h{毯-_b>Is-3TIԖEXf1"PeCKªwź{ rv [dp̹`YdžDG+g) FaWhT'4J!T,ú/fi1ˈ)  DK4Ts`](J(+͕55RQTש [#VRP7`<q f$d491ƏQtv7͡o Lhi @=(72b+ܛՠS0_qM8e hM0]7@o|R-2 z#Gt!V{Q#nZCsu\#_U'OT%w=[Ő X6!5:0L|8`ֹoK3luf.i.ݯ9o2foq팤IEr ?jyA%Õ$^q,2Ej<3WV79:,׽#OU,J]%/jó8d_2t>!3#n='Ln?7-缫T+}C@Lpop9Ƣ?IŒpաg! _@y <<fD/c Lbޅ[Ax`:b|x=ռ'?WW1ޅVll޾&Wq:^1971y^'<|^eKooTs-«kȅN>g%_|19o>m?gcǷD쬀q KH=m6 -izx'p};#ZF#Ҍ7E935eރ i6K /lMt 9&oTL~MuGdn8/ϏH ~y`X0ޯH(\`,{ ق\37 u?; jn YE\T '7lnſ{}}92P7ychv~C[K?Ҍp DNȾ.oν׎YѵPKWѮw|~ `J//d~ Pw$ȗ9S."WIO3x~,V"yC=Z =/Op'XwB'\'EK$$* P%\pŸٚ6-ZLQ ycjHPDM9{8Rpf2۰EK4f\>Ҋ2շrŰFQ*>1{ >0ٍ_!5h=4H݇VI7>`x*HA¥$Eh̍sR{ŏR ItNDhhRXtښHxROyď}hgk1`C8ghHP:]<'~OkhG!g7sؕ m7  &{xZ8_W{X~†BFv ZH-N.ch?3`,Q ⅸď1C~94z,Ii &?^>]b&! 5 u!DFaES8IHUjTL8:7GP+olkAZ'4k*5Hx i9oˆP]+BTEF@hߚx|L;u鞘T$1^% Oz[3P灵˽UBE4><O.)|_m'VNl #{١` R ^@5Uq+Q|V /aL ^,& `>]C=~KgOEZRfI߁m摆 7pn}FVNJolr˪Gϐ}_ a/MA MgErOxoWuA?1|c=\+~oJoE4(kEMT$XʅBL.x1ep^-[Lsgm# ?0CxL*~Xwrw[nakOSCdU /(;H!jp`?$8@k.{W5~jWss_cEBMFwPě_H9?Uc:V'e<`kj'|nS6c U|c_΋.l6Ki\֖FHϰSHn M}?_R^E?>6\)C^%[p<_w5y1 3_m  IϏ~ ;01-g$_5B?OV=TJO=@jNjß[_Kc Sp<<8vGRiO]yv`گ>*{1d􁫷+lDZՊ}LZo -$^<@lεIrDhdpWBC!: .Tcϲ`7΄E]1ԜWE?`-X]%(x~ʆ˦TV]8 yd]6萱M)SOZY[J%L\v5/5!Jܒz Q,oéC_b_}ǀ i>:P SrĈ@流">.)oF << uwY!"~y{PD|?>d]Ű jN!~U&˼.g[QAcSow< W_;~l'7])O$4Ͽ?pۖ|y>M%`#R7Ki:J ?/ 5]|~%vZC0Sz*c\'xH^ij0-D~Cr1Fo/Km{ǛnoWaH[m|)H:M|/sDy _m_dΒo'105!8Kwҳjqm20oYogu#j^rqa)/3;X/ى4|dTnCev}|i؆oo)DƮH(s]wd~%B.9K/ՃBO mj2 }@_@ݦ"IЃ햍ieQ6٢ u]jF[4h )Քn(37x"A}*-MGr6yJ_YSJv MpC4!VB|15mjSWάhZ^K2\Ėe (ɝy+8ƕ];R;[Ů_1$kށx,_][/571/^'<0"]\-)ZVjKۃx-QNvZ`/Mşb!AuWD@ 옠AWDEx&misTA3C1͘0\(ۏ3e3\')<;l) b]P[`GT4;uU-n-c>8PG񱊏> OWld,o2X 9y}&}"~n (G_ jQ7ܲYWCQlbyǛw_e#T>S8n-#ԥޯ+]!HEQ=yGKϫfEAxt9rQK{Bo&~+܊^Q1?>T lXj$3 _b^Q+b]7tm^R\%$T4(B LT9:qL/1thhydI BU~F*'=Iv嫹Lc^X?ݻ|[{ZGc@ӆS&R^η}>ƨccjU\Tޡ`W/ uG#*q!>|.`dr \lsXU0{{ՂS}(r@C߷$?pٱFKI;O-ôh@kiFزAӚz6{B9xQ@ >,kˡzo(D^^u\b=:h%9icJ :SpHx,xg>ji͆q<&446>^֘J5 T7?F$\;̡Io%Qx %~JMJFkY{<+(ljN] HIǟVRo!\{ oDF~?R g93CVh*ӊ&~2Y>Jz/s+1U+ܝ|6G8ݟy6Ai>`8/>Vϣv*= 6M {  ̡&viiO!y?Y5z<#\:MkLzoC-.[s\ Y9#2-jޭ?c<`W-/bnDwt.DS,.c#~jŏ䫖> ] Z}o5b&ލ>~>|= Α?4^쉷l UʁVߤ`jO'<~ANI vUQؘ_")wSO^AuyfT8l+纝Ojh )z.4W@$%$Ci2fc;7c/|^Z߄Sas$xq38m}[OxC?=[XD٥IL;JId%lZo,h dQ `?cyp tpʤ֜]O+uY9CX>Qz#1TUEBacyOA後ј?9K1c)β0z6;Էgmꡔc(سR#$;8Nڴtן| afrSJamIKOMُ ;EoPxCvT\I]gg_=B^Hbtie%db9;;E_{$;ޒ]Q=ĚC*hox?g\47 O"E}%~ޱkO*ŸH5DB'qk&Ēk!KgF bW|dEx*05T1e`% ~,?#C=ijxOh9ܜևk$l|a-lFc!K>OJ1``G` r:dAAӸ)Zڄ&*x!0/tA'~"#ZH~^2Ĭ4?k=k󰙸FM ےѲ Xb1-xMb`JL$~܉gATa8 A @[$'҆=zcE[cD[×FOۋs: B?eCW[,OZ[d [b {IP0=KGƣ{IJ.g!JK׳e[T9&?M|ro n9sK9\$UBJ#B/ ^:t(?cM˧ٍٞ?~楠'#.,eAs=SBuݳFn LOzW>>ӧP;O$ \~Yq= .XÜph'!S'J%ܩ!S~+F =S&ߨ얍nuR|زa24~xC j,8Y"sFu٧SAqۜ` c?EXE.ہ}h NA}KFWpjZ`WkZk@i͂0:KZU0v6NYBrGxY|4Jcꝩeaq:%?xǷ՘O?S|܂>}Q> U6_e},,~hޯ} ޔ>Y}LF>M ƛ5zD{Xsb<ҥ,㠸|f闰<'_-GCV G<fdaoRlRR mvlX^rl %uK*EC,=Ozm;3>:C.hw4_G<Fo-uiN^Ļ$q _L+Ϗa#v+k;Ե^*B1kJ?F2|I@J%H~,(&hJqS$AL\ۛh 2dQg!ta*OBf抰xP"yhj!(sPqA"eҚjq| r?BS"D*P A@(|^?s46_@O1 !_7I)dA@mS?aO@5l͹>h(^^n"-o/"fl,0zʿ21n*oi1[!+s+D̡ _f";cnQP( Ldfs:/fKbܙo *5{z1 ;Zz&<-)X -v"F%ɯӷOA} y@n|x%qK ; naҷ;T๒\2ACGq5 \<(48,3!VTO'7 M…NÛezAz| ă0Sx1&# ? "EܴdzRiAncsWxSC79/Xo=( zF oh4>UP7s1G*Q(AɕϠ>RkDS10'] 34DǍr?T /=nF"W V-R$,'Y{ca ʽY 0% iEaF6&gY$ܓ:];Z = [v5ɠ݃{TʪfHz2zhNxE,bC-i ,wyɮ+r>)Cnrk->/z>Mb}v-,4.܇׸wt ZM`z,GjUjLINhpl>i2~X(Z) }3E)]Mnt&ga理T*q,v>qQbBDNiLkHBҰcU{g)7z^e#~Dׄ2tin'$cd}8x$~T'Qbm&t9SS^K^Y HdWj:yUl݅gWEmVW(Ȯ\ UzF6}sX?kŭkyC,7K yŒpWĈA}vYk)/o.㧶E~85L4Ww=~-Z[w33=*p b Sh:[aX%tG(>)+$/Nд`IX%!NEHb!f5#g6|FMI)zT\aLnpZ3ηR K<|Zڐ48zQ%=)#;F"10kmTi}[ 3kcVHJrJ@ZHZ43.kKy"\x˛aasfZJ$џ@N[Yr? I΅-!9z I BT\#8FLw%~#4 Շ$ C(s#"&.(rg[J!$&V(:_d- ^?wEuBd2i- r۷ƞoZ񨐆35T~gy d|GApcdىOxPXS=+}q`/H4`yWաGYʑ]dJLň' 7Em޼* }>bRp֞ xE7J˿: *q*8h 3t{^++|gog, ⭮ x%&QNJ՘&7d~Bv,D^izuŏ_2 %qG7fKvK 5˶tNZx":_,Jd8<ޖEByA 12$qb|a++j)I[$PG~_d ίȉNXffvg]^ 껌B8%nV"Ûlǥ _p2܏:b\D*~H~Tv:B⎷Jt^G,E\G33=cKn7.iEϫ!?ULx-_]Q6[r_Q[b݆j?rX( BszG+wEU%AAlt9;2-ZWZg(G!$_ +yV @Dd~?a-xڨ؜Lw-rAyc?Qv-|v%*P?i\Nj8 iP \Mt>2ƶ70(<;&А9)]Sb2~7U˽,^$A[ ~,4C7SwZ x Cq,4no>!bG0gDЄDXTז ,{VVt#  Ay{QC F BtZ{ҭU{G;nb*:+VO(ֶU}t_Ͽx0s+\˯o/n*>Bpaᵠ`r]9' ZM=8f0|GTy3 \ (<}(3"V[2ǎb0a R?3?p[z ?OpQ ~``xFie<{7x3[ NҵR?Vুcʔ?Xlh3H й*bYxXT寭X}>rOx< gPC2}% a oCXMJԷh l_FiK]wrL_Oo?/KF"_:P@#'x^3\\$̏ 8Al'=k/R $(?w=1㭌cuy )EN^?dנjKM^W،cm|ayFяVb:~zR> YXCi-jg|UcsX|KJ$Bj./6lRUؚ[[EəR*p|dؔa) ?}८:|5+5rN@?TQY-liy]6ǴIع_u"]w<6ϪѴ&yJ܍4rj(d_a|kynj7To[ΈO/&x /GۏTx|Ȼ4 |?Qjc+"6  z.ϟ|'l!; u}`]V}Èa*GoյQ~-c;]DdJZT٭F&e-%x8tSȚRԱHk ڬyO4^[ ΛψQx}W}I=Re3&Fa] `*}]Mʮ>tMƋ;d U4z??=DEj`x:JGK+ITYUVGG<⧽2oB]~QMJX鐳H?t^q^ߣoI2|G F{'#~JBoyIjM,}7߫HWx5=8oyqv9rrch۽$jdۈgye&=ވV:EҖGАNOc9OĈϥO5[P7r Zb~G/ӆ{C8KdB@TrdϷ#[$H/vԊ[k^BB`a[9 P"C׶uhґ0ވ@ RQԑpl{F٭oC̘Aвp:f8(ʀ^ʦa[DM.v°j;Oz/}C\YS*7K}@h TX/P[|P3ʍ-M1Lֹh/C9ɼce(ꅨ& cy_?یE׿@u98 x {<VtueٶDnQʸlY|_gc13~m3m^9NފdPV+׿xK%۫"a,m_ϥoFrG<|=G5%`_`wQW\> &v2~n\Dۃv|J A l ?W7zuo' OS*}+k'%~]v1"U"=,U.g {}TGˑX/ ̻3Hw=Y[E ^ѨQ|Z/W+a#`!FaWբ{ L/[},;?L_v{G@O[:7>U_,<5|ƭF~}H {d3p%}G(u]PNc#hFl"0WJ]uE' HrPѤ5?^aƒ*|q.9`;fFe83{94).1[2al]O^_'/rgU`8zvǸ F=NęjQwb/H},/A˨zc)?^T,^ݟ7QL_ﳫD0 ,F3-ߠz`x:qvB.LƯͳ^$\)6ۀjS|~I[8@tx{Z؍È Ѭ0TߌrUsRz/gzw~)&{  êi>-Ui-H(Ĉ^w0 ҵ!k[;teM%&5vDWUk>?n[xۗݻ.0IodPdReO3l&x@ _rޚ ޫ?`[hJNK6T|9p%~:$N!+ zn"|qY1^NtWŜW{XV_|-3P+=η=o6Yo^7*1 nk%ȅ>zyvUJ9X~G/Azi(n0̀[t=+/T~D^86V Ա,hk# J} ,ӅZ]g2UVnx4-M:ۋ@z 7*H1bܟҕ{t( . pQe-VmBL[^h%^zvH_g:Xq]:gR `ԕ(4cNCqbRQՌZ'DZ( ⼑ސҬTPOPMRa} Ww֝٭xFb#ުtWϓn%[?ӯ3?* ,&~eSUDD  !+Q2Fd-=G2E,2aa?y r/:g!$KՌ7JiJZ,דJ_z|'Q'k#<9x4lǿNIC"ae͖e15P2OB83=ߧt vdTjo.2^P& yi?b2ԼvW s?Vl-]weږRz[B]׆d&W&\yݔ4 kF-{h@FB\vW<9)ǟ2M5 QP9dx!^Tg4{}z_ *Eq&:jŠ |聘PFcx.*SA2 NP^Q6w_H_kQ$)_JS0VIUnXM1zwhLG-b~c{쪕4cDǩLWd⼾ RIo4M=x҃b7D ShC#DT­^"ֶ\G;4͂r[ޗN9~9)=yuEmV?^1WQpPaڜ]2+F˱:7NsjOeP<Ǒ7,󭿲vf3u~ݾ9n,ڤFi\;!o)Jϭu twfEX` 6ďMDK> W}UW b1cC+*s9];*x)Wㆽ3x<ނ;=!G-T05fB+~_XZ}9ZF)?Ci:>  vj~K;X,>Bݷvaפ +htqIX>82BVA%߫#o+/rNr<n D:v|ܾCεޏ&vd8jᮏ.c!'L3^}Stˎ@g%_0izAujR,_o{}|ifZ"ANH-}znZBH,k&ޓp.ӟFnV/L> _-d BBO9=RsW6 CA?.` 5/0T 1wT6n'S>MV: v&AOO}߫S[n_m^oGUF,&2K1vi02U/?.V ZISM:S"V~0( `)} kKޗ}Fzo:0b mXpea@%N.B-Մ(x”TH^]'5ޚfN lJUx|BpݯO6#̜pFha ke w2Iw^'d*XUPz<@|";TQ(o>4x3x*t\. e Xv,~6rM@!q5[)]) m\8=[("gSv,^iiq6na ^6H N/v.>x+ ^"QXIߢ/^HBM"$j7KB2&- B8Spt'!R@-ʽ!NCG;j3Rm?^yzi}F͹82dq@sp L2O_mka\cFBbl&97z?:n ӀCJDbhj72rt wY~>:ܪϏc.34[>*@; 髂\Zb_vLש)`Bdf]݄hI$ך7h͡:؜fL% f9@tF!Exe!zIn%XU]uQ3 ((9Z~:Ɋ (.tw) (vOwtrX;W+WZd.8I=ɞ)38@n5'TvR'\׀0sQ:zTiXVDQL{-e|ef46G^#i);-~TG? ]۝b&'Ԧw3Kzbm1!&R]ˎ >ߡq٬rteN(bPLI _x/qܙuZDNlޕ,#J[jU_:  @(᭠jzLP2ug14{MHJwoXِæ^1vC N|>#&;2Z% Oq$40o(>>f_D΀xz9rZ3@S/WbnFE9bA?-T}w8`O Q ff-N HP,=S!(}e*'&񆌷Lv:]懹&zG'+ 45ȭY@;CӱK Ap604d;:cZ[뒟<@44z/Po'ۧ1di7}R(؟ݐ<9ˁȈ~p^MkMP:3R=Bob@$0 %4W7n<:ˋ0>Dž!>PUQC~|~qAmqԘ>M+d/v?:ĠWEh(JG7Zg*8! ǔEQVpUb3|fBPNco?٣EoUKEJ1wOj g?䫾|/jTBxqzN}l wp}ynJ宾_ +=nHQ4k晠-CKB c`/xYb5YvݬfU?׿W&><ej=txD>5!7fQUǠMk~-BSX( >h/o1z#YZŏ .uL{{s+\ tƦcXklP;&B@3Q0P̀.V rDxfQD ~/ib.Q>GЧzAj?ތ}@Bn,g17%Z7azՖ\oݲF{>PaYki/_܅î&@⭌R?@_ |,?+&ޕ{ )B5go}-4!?bBKC c.-I%`|'ߙwYr@'9fL+{APqqմj /2xco߆ء*"ٕ?m3lڇp#,I 7YtexR#~{T aX# E etfc,_Bj#;:۠ r"R`V: W%ްLQ{BN e&*>̣2P%+Cͼ Hm "UH0H $~s)^/Ȩw0'py{z*yH5>G^07X'3Β7{ WN G 0J}=}0{\L&1`Pda w0K!`i}!^=S7e%WJV.L^-ȎMv$TeP ܘ}S2zv3{~9v0W"(6K^F# v'f6O6:#Q5x]j p'k-$޺c˓6@Á '+"0!'2̿k R:M˚;r6L|ߝ e LzG vyuJ= Z`To? f3)߽ad0+F ДPi "r9q(4%ELv\+nW$%~("r^뻬ۧv}"oU,$ުDa^$HgI#=6(*:RkCS9G@Yz5oF!01N7 &2ut?p7|=;?'?cg7)~ [X.WCsɒo)ᑨ$VMCquti)f")p-5G5N^#wj`/>ƳCdb&7Q%t*A ~W%w6a*CoJfA i!PBUPaCQFdhΣ3Ss|8=2[ G;з)mUΨ:})kdE% o"UndeR8'&Āy.$ 0ʁȼwlq3V5 eOkJd7xFA(Ei ޾f{Olo_i*B,WR+5A0U VEo Dk@kO.4HvWLaP춆pH=C1'a{N=P{*t(wk-/`P<9'Au2Cv77]TK'MQ0y*wXޱ`j^h wѨH3hח??Jfob1*LDO^]أhrďx^9OlUV@R}ܷ8GTǛMp6GK(e+MX8hΟaE?Q0y?E\7vo_K|vWG?;Q8'?X9vnwTf*\;?bw3wS,D/>Jx[)Z t iwLoO]hTF@6F 'm0 Ʈ5/Pq<:tAG7v,Ga5»Vxz#QBh@\lmP1&0J; ?LX*0\ii&J os}<,!@kZMGUP5,-4a4 .$#ϡJz-M*vyAշZi; ǠJ|GGl_VZ~A|񋠃{oZvbsɸɡ4BK\lV-Ȍtͷx뷸0bOK~%pY^ǡ ΰcn*tWARD.nÝW?{|y^mO${mpkQqKP.Hψ_efQc=fE풯U#|STzVUz ~Ϣc;HD_τ8^hJ${_ch&Xrms, Mnu$O΋h!qYD,_%X9._jqiJ uQԇq_Ɓ7]U^# X.*];*$iJPHkCP(_B4pSh^GpE(U:ӛPԃa54~e5~d-\i7Bg x}̋uTy&Nu'Ҝ"Pi 1 VHI1S/#BϏr-~TE=c0;a8Ƭ2+[ .R/R+!*1aژCNZ~M&j`ּn5H?Їpκ^ÎQM(׼7K29\'~t;*K1io[zHUBRwpoX菼PaWi4F#EؾMcă6e|ĉb>Mіx+TJ~9]煝%IB#ϳ#kTm'f^|%`GW'] ~aиe}ޒ#L~< R1u;)Ϸv?5D>8-=Ak;z2H,~)q|@2eǡ[>6ߟq[BXxD؍@6Ra^!I`0H.iR =w}6E8MBc)" 1ݷ֪}+=U I-Q,PU;3cͣZ:нN {Yo2u\f$0<N .'nz6Ie6#<}%z:pc} _lH?}_LĨz (+|kuX@:ź|[:EpO5wo󈗿E2, 6x  2WB8w2)<6[ l:p':%WtH&-|lC@`a<,ψG[/Z)}ex ~^u#If-[S/63\1}dl_P !`rj?ϯ6l:~_/_Gpe p2(;`a]6k@,s> ?~R2x #wWs}%_jkW _Ywwܸc ~W1FOC {26dmI+ 5ѺxK#̴NSZD݀æQ񖯚T q-*?QB ێbh> YNy!> #BD^(w,`7%,wi#ƕx]؛BocB| 6b'&bO{[Bp?!?|Ӧ{G:\-L\է3_1t_6C@H(߿{!6H^z`4Ec\UeqG96P>+dk]9$*o{LSw/PZ͟?Ί0\(Fc'kLWX3|bKט0Zʖ~@ u,c D((e~֫R{!mEOlH`?xn::zЊ(rET& aCa;NAǏ"W80q+uGUPފz)kT/OykT:Tg᜛NkWwD vM I+e& ˆCb aLwM4&=9{쳅NWO PMt[|oF+O \*çJVLAG?&2]lmiLηlQƋqUǃT]6]\pnLx HBf5PkD K/0vsn%_D08@6+HrhKǚ ~=z6x& (+hgo#~3w# (_E\ =]ot+R3gBlR!2#T/͑qЮ. ǪçD 4/( 5[$H跷2/5ӢBAe9 *?J9kRQԨ NdM0 fٜ0Ҕ#@:Fv6]C( Kx9DzeN1Bhx?;B%_! o.v%F.xIQӪϼg{~vg!}~s5{~sePx;h0jxd+鯧Ut_V-"y^-IƹKi+V.$P[}+:ԇ`&Nk&Nxc?m~⧥87Fm3ΫOBWyb3w~^+@~)?O^C B՚gkfnPTLtJ9~-ɱ^eo3~^ dzPॵ$7g?XgKګqᅫfHW?%_C|\tƏ|FT>Q/=3H%x[zՒd+gd\5?dY-SL{Tgo |88Dwz%5<~sX~>@C 1SxD%Kq%V_*' n4PÒKW4wS6rp%(EhB:~[}qP"^?3,J/z ָ uy RgI+%wƨ^|h,X}T&l+wsB)!!V6{p6kMn"fjx.7x=`0|cWbn'tPhcP)]1ߊ>F\:63~#f̹*Ŵ+ l\L=oWnYI$vAFv,x|zrʥ؎a0y`{ɪYJ _.,0H flQɞmEnp|T?Lqww`vM:jэM4הy|' Qet#2_ ,'Hhx8 E;N4bzagdѐ%Z)-4gA#A-ؗwD?nn+d}D7U| r$߶I#Qm^ +-2+G:)HC6zU5nNѐ/.{ǔR;/ 04A_qU(2hPt:k+t&ZjD̓M#|$;)煺pkY敺支oS_ F,B akت}蟧$7̚EY@^† ^qƏio#~P 㦦6ē҄1mI:Ccw|x:|I?4yѱ3~˧ۈFZQJS%񺗡t+b ƛ!4 :?5nͫp}-ȇZcB> 2*?Sm8L.Qeۼ2~>X>AJZĘs?fZ$Å TU@ x{YHw"7i.@އˀ c<&$TEs͟ nݵ8X-Z{Ou5~^fhk}=fRף?`c~}b`S6,~ rdPq1f<9k>n&f&d|u/6Y-KL[lǕxP4CBC0H*Nw P|v;Qg;G*UxK̋WSfrx= C=6 yBg7Z2q:~4g\YE[i <|Ȅ]|0Hhhz_CwG WsxYmUii%>ntK|(DԆcMp#I8͐Ub8;ӫ?T:,_ᵪ KS]o.] XsLHU/CtCQO=]^"hf4Cc{Xlȟ6|'i-F9=v,*p6##]o~,cE h< 7|#P8Moڗt*Y()1geA>&)@{oW"u5JXsTD!CdStDRQ.M! "Zu`HubUvlE,{ ҩNͯ&S-J7~t0+b8ey1~ F`9e]HjX?JKz_g{ @f'mJs1<|$~|6 >dx~S$N)],~Ź"acwtY vUS|Ǧu|pѾT2,l7Eo=J>2frKPáؕH F>Xм+쾋 q-!7ϫW#9D.t^ٞ^pTՍP8淐ޓaɟ[.#Sۥ砑o+(?ۂ9$ljv>F>C8Н(e2myu҂d$XAtۦR+m@ )N!Xi7G.QJ|OУ"~wZ6p}vLUTtG>/ShQ>qZIB<|ۗp+D1+y9`GoÐwlַ u8Pz(F;kq@8|u0? G3[")`#~ QGvlPWn2:dDCBM U+ M 4LjSXR}a'x! ( ~%dhپ oAquc.nVQ] $C_I'd0q*mR&TatM wC p8d'lZv꼔|po`%+Ġn[P}j9拲w f{W߰KU9x P{RYYV QoK :ڞ TLAEM"Kt1x6=3^-xvZ:00Z$9?u*P\io'(JX+j4B񓛫H a4BF ÐcPMojtzYtZ3YVMuܑN}Zac\bÕ))~7GVlS}ިtg=0V6HtBFg* yc:#Ɯק[04x[3'[_uBONbKI iDr(tV"'8Up 5p> L=-8&|>yeB9.!p%!!QW4q|+N`)SJLvG-Q=8 -奈ch îJ?N!K}Y-+\(R>$PUaBN7};n.=?)?v66I5"vx1RUj﫸#+= vv^/ G)J~Gb\uEU6bzGyo@wrr̆۹&aL[ ~>,=|P q ;p&Ğ&Bj=76bOx?eF[AumzG|Y%eRZe{D6fUU5yJ—vsNlد=TB!GFMg:|GC\&^b[`K!zY{|0_:T&OôE:ΐoZ#guW zpa{n e+ʎq1{; EdƏg}sA,n@h[:?g,.׃"."8/Ƙ2Ň9Ѡqh?AbnTcqa*W˛UbY6AAاɊ*@>;}I/d$Rvh`CK OyԀ謽 ߫wvN}Q`oh Lۗ2Rr@gW r%4)=>>˅ܵ(3fNa{-:~\pov 6c_p5ר0E46f""mI1%=ZmntsJGL8o!xut gdŷN[ira(1{ڮ6gXL /_P̚q~atuCGZ mMpYmٹT\<LpG{wuuXIa{8@}Z3]L>q|ſP8U+o¿,$oxf'] tRQ~ EQp4 QQ&SKB ;.K3Z bdIY_;j % ۆz툚n`%0fĖ9,,`Tdl S]ʹ@[ r>Q&a)}Q,.72tRV帼GSBQOt #'!te҃PKXa*-ϯ_G|g7aJm j<,o#~wzc-0b=k2n8P=~P5;E}Z<,v;cFGD71VvrAۚT-tv\y*oU KKx7nSIRo?>2VWxՓx{H0?Ո#! P%/ߎ*.r]iR ϔ3r/%6=("x"Slx|cXͼq^e 7=!Q"jb֦US|D ^n4K[;xsƈ#_vK=ey5mϾ-g|U{{6ڛq7Z^ԡbO>+=ꏕbx5׋0?fg[t+,Lp|c;/uo7i<MzsJ 8<~B V@kZ岁=%g$L恻0r#מ M}{VPY>_½c` ZݠgbdߖrCфak iji1zkؔM!)P#C{(o c߿ѹgd`ε+loZtAlQ$bbZJL} 0/D(AHTLaW+4$ jnI8:lӣѪ Be0@"+LAf!IYT<O`/fbRDA m3eRFPBsv^~= CPvo1O#&S; (LMKu{tlg ~Bw?X@RƧ Zikd(C$@/?wMH'(% 67_bs{k:1ҍS?*Tv> @(h&|OWee:!R:VA_uĐ 1KV(q 4j =cCg6F\I=5>oDF}tP(=+xkz';;Dg#CU"DK•g.N>Clò.# arD^BF)C s/={V5} "9| jr.EQ%.2!3(+:.˳ ӼI<R,Se.gv/xR*2jTE m'7g8Y_KC ŕ(9gߨO^i&|\m mi\*RYAvqkzLj);^y]O1GGW͔7z/&-~YJePBxDًcUDAiT҉r^:zB*LPl]:e~0; soCko-RIэoĘ65؎hr aP&kQbVZTśW!y S[H)0xc[2&mhlKb"bJ9hFuĠIrYUCiy+QK,ͽ* 3I@XBqu2T ",-Q0J//`yE4-/2\'|N,\ <3#ҊnT|I;DmVpF}Ȉx¬Rc_dTCZ!FWАAr(/NcE /K DNƎ^޿N\lA(ZWc}s HI`Nucٛ~T@m<[ԄM(7+LJCM[O_aU sTǏJ*ϏVץwy!0h>x+Y {=?-0)~ -t{_?W4D%hT#ҀtGwPk|SIz  x7 fmaF_Ǎxsj\YԜV+?;Aڀ bGpIŷ{" U-uc/D'y)ai%TY,jr qO`'T1HOsî!Pp$'3(j e5y’>J{F (l`K? ,1»h˟xOn@?|y* ͓ݷ[G/x'wM_3 zGE!l#N)=Ffw5/ C!Fa!w8|cۃz??}Ah/@- Я$b(WSѮw?+Z5Dҁ=pf_j28v5Ld+~(M?SI@ "1 9ˈ d8(f}в>|( ȳ]sz$ʈ{CXù8_a¨3_ρxN}|5hi>1s$!C|uuyyy.O[/EQʚ5HkITrkbX%ҩ+~ $*Dθ<]Yc|!5X1$~>+kll2 q x=qWɶL_袺ǛQS/Z;1%8(~@Wt(8x`OZ-&kCAW&z_tFr 5vl~wUu]h[x)26GK廾y9voCa,{zezb䫮PY#YU_w9F;fI[ۜ+NOegGl C; +ױZ= NS~p\FۏԺW왯.;I<@0.L2%i\X Y {U(!Pr r$(vCG~r`H;ѹ"M) -t~l)y}dCFL8()-Wh-+\WQH$4V۰sꜥ p8^R4`i"Vm;"tгhd0j U5?F~>Ò?HBwV>0q1{:}@EI'>'iiaqUDŽcZyxK"Ysc  /ϟD=H{/CPh,@%Dy7,ڌA M&-> !cpp{cxgd97QE p*ʀVM4-R1:W(?M?H};>GC?& ,CC:$ k%>Q*Nˆu]'4U;ONoIX2*=]]u)C[^A-Nq!ݒCD_2>5oP`Cwf#s?:U2P2>r"~jHq Q2xS}Ճ/fLZ`ljCטvLN"P/ 5Ԟb"i#!xh 0,3&yPS`¶{f8x]1ӟ2eߨ*oě__BksLլaР$߰,274~0̤Cs 4LX^^(śpGd.oZ(x m]RWE$@mgNEP-0&Gp W 1ȿ6$X aMqBzޖ(fEx NCl6"6]?3C/;osդnF ͒` ^/WxԣDn-LЁIҖ}1y6]KnZe31ql=>?!Җ?!kBG .<3Uk9{uL7t:V YKQ\b{A+_~W ?8F+*a晍oK6lśw2dmWӆfO|ua?QqM_sŊ8xcXq|̕`= M]|9ϯ֭:(1Y*sqmb{-mѱ3xo߳9FXQCebAGj#:Ň b|O*!/ @͚T|΂SFp ~Z~Lk3516|X~1~.'⑯j+RQy%Bp6lgTEvbݴш_}M^LJ"8 [2Rl;Ѭ#!ϙU1dM#J<@ _#a/JUߚ4'@k͝VCIsm^WݚǨ鴢_X7–Q]zF5k_](XT1BD~LA:Nz("yǛWD&^~DÌ o0r_V]o{ e?h 1c"]/f|v=MC:]%~M9G.(VeeK6m gNC t:3vTgdO.Ĺ#F3@Æ1sQ>ܸhuՇRy[Fďj]z(@_q[|u+&a}֔}5P{VJ,kڢ_)^0ۙn@"驣Wq}GsK&YP!RW01b-#q]cBJT4ͭeUdQ<*\7Ӛccϟ ~1LQiq8&KD :/x! p]##f%Ma[ꞇGUOjp^W98٩vULqHTh50$O.e 0h!_2zIIa&ڧ}\@@U-=oש~蔏޼mP.dcncIT~P^=SJ@H Xnl kTE R  HZ.Ȭ ~ᕡ!Jr$:UݹJfBZ@+ۛ|xj+y!Wtg,C*UYFF1{(!lBM'MKF}#O~JZij޻==+01&=EL JSoL}I>A8Ej#/ z 2lGR\WIol{:)6)(RұmXb,]/Kֈعśi{?v$Pg|! ҵA1#~En_؆5\K}tOA1p{Ҝ^ma5}0j$Fo0X%i2ژZ?]i#r}mW{h*In<"~_&0Ǡe[KJ^"I!Ȕ-~H}T&`"Y)oy #.xq>e?NkRS `YZ^K+j%X#By0t{ti%]В:&{Y>Ę37<7q/]MߊG~'O(EM>/^q9KȀӧ&Lf=վǏRehImQiZ9Bz$XA>u7O,  (F5$%!2忯-39%nMbC6ST S%jR_Xb wmlu􇢍x섅OK7[ZMz HQrnn/w>O'M\;ppxďN&k3yޓo d o6j3&wPOBEN-NPZtq?>䈟 >P=nwN{+/z^xZm}Yoe2oSrfJeI='l':eF /V 8z_H+kUM/@b_ *f6^OSB裊hhڲ~kmxhb}%Iϵu9 8C5ocWKCWba2>lcbh)'#&L7!w3?N)S=d^#.^{O>BN59Z$~;޼>ZGWooW q7'hOɝ)`1WF=Cgs_UICZ^ dpYXFUqO\f1aefsWvhD;mba-S@y,[" G w-g o*OYONOuYt(\Z~m*Uʋ>NSx%ZO_:IxW"3=I?T}oW\lVv<3@^#,q eC6޳-G7й=~ňK쏲##5m%-ϓ[Sb(Q2xьEW)cuL{f=FPH] HZluR$3o)~9\ϟ3 ޒ`E~2.YVΈn!#J'a0-\@AWQ&K!B{) me N2J4euȄnСiIQy1wY S н/F 2@C5~ >U4PbM#E^SkӚ,08Y;\`_: * f-Ga4"~$\%b*K$:7 8:K+żN$4 6URUJ`}~5S&x#W%fǭP#GFl.|IRe @,d?Y^wm$#Վʖ 8W9Bou pMe g/vBLh:wi,O UQ3pϽlt[m~u:T`5̭0v03']_\MpOT(ibįTHJC8Na-؂Z75~}e¸{3/j6 Qa 9Z+$̣ T#!y8(0:iRSwDUr %bR" gE(1;YzSC22p;RVqfC[9S7];.]Nt+_~_89o괴ec8q./ h.nPЪGun &;rlaHH?X_h( wHd04 \Dq \ ny+++%r7Vik2!5K;ѳ?[ZSR<|OLj%P,C-~ծxU┦f;! ORhyPx#4%O2[ :F9"j1#1u>8RVΕA %#3{JnWwjv7NciH\3h$Ο6j0L\K =hh ?"~5TG)i1\=gm3KH%!(u{/Ҕ/|_~ P_/b_eZIPb#%E|#xOWSLC׽NP$#G4/ q'X JoH-:z)}u Pq"F"oT Nb>?.fQ4e;CqaH){'j6u z`P4J?[ p;P4V sc%=Es * ^(kgjS+LԐ^? =|#,p|eQ?4aOHloY!ܮ_Hpn#$RVW }q.jw #AO < 2E FUf0⭁vNEVm)ы%\`ɼNZ9?p06)TK@,\ V|r9P{ozUMnMt7 M$5DXsvPoY8Z?`F(Bxo83w_Q#|ccg]_6&Rs="UV`Zn!k~d.PK0ݳ?ĊrJ\P_0Pu-cq.4[qe2x.xGR190~<^ǏϾ3~c|2{{%;NfӻmG3B1 ~N,~#N lV97C'n˥)NyadXҟxc an!3I@LyY}IHU[nohl5ߟ-7^[JP~er~<"nN {C:xi\wz/T6&,E1#9zӠm^ PyVś!}^pQ6Ho'Ė`UKhzB+̼?/$YtE6w,! :r>m`%xFYZͬퟹ$` di49̇*5)7i7<%30UM˜Q;W7"x:mq@\%oچ0aE@BmxOh8(丵`X]>S ˗dOe'osv7ž+[0FwUq/Ɉf>/MzX(-#y7GP6TP MϹsmѯwϮ}V_[76jO~B?O {A<ݚۑ RY!DK8ƥ7yaB ?%f;ozG#@aǭE7 ^'?E_]M(Q\Կt/ }/%_qUR;oPT{ϻC?k'òL+T?PjPbEQ0}|/mǏw-_P(;)$ӫno2%˸)l׻⺶՗T [CϫY[[?&RK>:#~k\2ⴧƞ9-ۈΞƟ1OC2@;hжz,¸ztw\wy:0Z|JW}(w/tBϛܶ 1SZ #1A56d& &Fbxf{I/7. LD3j/ڢ/B,sFSV^fGZ^ ~Gn0V%g/y~=jz8NVxـ}~6@-䥩g3"AJLSZ?6>Z8 PEDH@{$ 3 敊/Qsm'_֋gDWw4[B9O\قu}M籑!E4e?1fvbm[mChБxq2*%,$%8#ڣi,с\eN{MRh[&4ѡ0;&sCEٗk ҜVUPL?r3p#UQItBZ0OD58r}a݈x3+¯ 6P2<(g ÅbrYHY+~a>70>tklb#$>I8b>CD~6غuAOIus14AM5{p%'v;&R؄N!}&^1<+*Q=B][䊟,U|qR * 'nnVL8]"-DLsY WܘvI@&ެ,󋼋ď*͏P>"zCz@Geǃ#އE?NK&rD Si>̓XqԺۥ?*_4,bF=Yf=z XQ,|'(2 |5Ѐ(kV0R?|mf0*/5xcDž<ؐCrY:An+ 5sf' &z$X6+).xrx#' (u]iڿ?4J^}\o, YIQ#-)$tHՑ35N҄:CNRe ggFmf7 {|*hh7> qyBPBu,( w0 t>ZFD\i}`N>zguRNnh^+%[}=6>?n:gѕS!ݐo{U}`FtyQ[D6d3oŚ:< |L vܢ&_]ފ7/"? i+G:N?ƌN:N[ ś8 7e@5\t!`+g}0 kϩqEuO+qD$O[bɋI~{'[j q a6onqbQNߌ!"y(= [?hn2_g$_ǟH5 5Ԝ|795~1_M:+OmL,V(:xǛkVP^{: 1%|.~XnTB;?vHk۝&̒`5T%{pU\9&,[lF5hw ͝`o+!_ OuU@5E}ӯhZ1_g~IV*\LǍU5hł3(F¤w;#|8"*DoIU1Tmq7nT'#/{Zi'rM]~FtZOz P2M@QSټ * ?{z7"2G葂sS˄icK(yz4) BI}F׫5S̨v=% &Q89T?(T;;ri4C@uδ-)0(:yxB6 gKi{?#ڷ$-"~.dF)v^ij 1=O dhWT$843 ߽s/ºm{RyN.mZAhZuph=l% uÒ#!ݢΉ!a +TeF8y@fskTP Z[1E&V_-\*wT"_?4 {>KBw=ZBbU-}{ʴC$`#}K ´jIܣ oM+[mӯ8>j5!0# ׳fgV#;;;T*ņ :ʑ+~|ot!WϿNWt9JOP;?6dODh:G{ƻ m oO2<v@ѓ:cն  `GY0ýD iykC@0D%ǾXCQ_;! +P޿ tѩ4J^?%""clNPSJyӒuSVϋk@o1J@tn&A"Ev (`nelC=F׍Cc2~z](0.A?G0*ὗzџ_?OxSDgN{ MٝSn$)E,o: ďBY#ct'ɷMo?GbOotƄ~^{|vO{Y}~>"7#$5>iڍ*~^I=ިKs8qQTcw=Yrtw xx:>BX܋3f[HrSx(Dy? (!߂r tN|FooE~98[r+P~GN @?pʇrBC&b/6R: (D(Mϵ %uД.)BqzMJl_k؄#=OfA63sXz~+PB)D?h.=?=4 Q:TEN*pQ[Lgsp,_msVO y!##,^f@ m lޗ77 {}=\K}Ě?)9MKf(?6n-~R1ތ3 S Y/ gP(phxJs%vor%ś8Ū"4q?#ر0_y iB U/\6 %iŘQ7g(~IF9I]xT2Z>8@CԱ:M%m@OS^ WB?2TԨH̹/=M9 (idds?w.A97a،h,ۊ%K`/T.W"KHh+".(?뺘LA){僫=Js> 'DGdvjVމg0[&Pl*5Ye@mX#/bx19>gA{lt`aȞxqdLtj~!rϻ*'>IuJSm`+pn6% f |z*LXKol '~ K.|@&M$)(Ez;K0f_\ 20BBp?q;^"ᙩAU|; yﶲQCCmB > !*=!+wֵzZV!F7CjN/toԓ2b%!nHc}dBTLh dBaD= `xzJ05$Ixd'_I_ϛ PKڪ+:Ne3z("̥FGN1Dg阹z=Tܹ5_ 8`9Kq{'إZ'[&i]o1vzeoA?jۊx Eg@ x8C.zU>.B tioU: J%TB_D^>: M`vƏ'z %/ %[#6vbx2 Ǘ!O7eԨdY!~{qV_@ 1/eViS([{WynY7px?u~>\#tBT-A+NQ>!^c?`/'O:@IC?XbBjrPWs;\3o3~PʏU|UMPkWrBׂV= 5sG; `PL bG4:=7km.;,NkӌT.3:c2NFD\`́{&pQOhVPE﫠6t9@5i G^'D?LNSjSTn\- By?}+S<F!笭 3m"/݆`L'|5=c_gÌRW4KER (Az_/uƛu3 qчi/J"9Tf&Ooxk;G]ʦK4fڋo?D`/ޤO.逤0mZ$&ވ"8_n8oa AS(S\jͺ˩XEU Ue? s%]Rw4ePGGL܎zb^4`#2W踙/}y6yp8&n]R=@G~>DzBjA9{חd?4R&vv1YBw%_*Q >Iʖ&4Né2Vp!e( jS uPw9 S zc:X` %OAYPE^^&e)F /yp:isS̩V&FR*gT*F}0Y;Бcj.̖JQE-q5z[UЊ$u8lY;ccFQ4ᩡŏJ֭x+L!@hU`F[Q2'/ 3\#}&PC +gg0CrKN*⇽^5}( Qň9-wbď2:ztyKA3x~CMH{ĄR&i1|$0QULlD_13y7;[i1K\4X[7tX:sg/S ̿0DeFSpe'U0 l MUG ?ǔL<{9R PItH|^a쁙VBW*0mdl q;I! %5 | CEBqne PW Z9\(sBB-4~$p//<;^>RτsTxNjejܾo:^-Οߊf2`[~O10u3GtX޼=xa ?^5zA*-q}7NPK<Ѹ|LFӔcF y^cV9mxCUN RTU(xQСV ؕtmE=,`Q ^ Zݭdl^' X[XcQgz]m'\IeJJ(6G+KHWxO?9ݲtZ00S1ra˥b g5hA5-> 2|2r>.>6ErJLVrU_RytmHYU!1Êh#fáug44i\r{6Af)4j< d<8Asyjb\C؜(A!'=EЄmR=5i;C0<1l㖍؀|-am\bOW9bf A #M~ΠX:gBeD=2گlT .JKSSЎGhX.>{֓H`DԛpzjA';QeW.ZK W=N$[TQV,"3"P2Ц{qkcڮRd=t)G! Jv<|gr_&~,@?LmWT4xڢՔIo? onLZEcٔD >Q6BtU8 q4HrH+CRߖ3_zb??a3m'،*?3Dv(rAhrF.vv 5 ݑ?)RLZm4iMrT'w!H{2Ma2kj87D}**bדBdM:`lVJ;D:K@=#w+$7n&M=MMBjnDU{yEN`f4ʩBOqB+pd05gupG}[ 2YRUByN[EC(`i ^6דq\! R(̡ yrP(P-=ί;y~ĆEMc|Cj5{d(Nt5:3ï_2ʕj_5WBvct,?-4'"ͬ@j[{GL_Md  ^C[,nL{Mi!fJuu6v3Sa[8/+ h(&$ys#HW5x Ax ,`qMTёy䲳m ၳeoK#/ iRԙ"ސB%^-PRƠ?Xs4􈁌 8QR('uF2χ2д-JA0¿@e{q_z <։"- 83rV֮zm}pҌ7yr>$Jژ!ND=g(=n&֑x>r]UJB1OG(m' u;޴:yC+Dz%-M$ `0ĉбRfzHdBձ*7p'ď]R,qi$J$ˈ͂p mݨ+RØ8wfs{QJGd(}ohy6hM*LC=* N&0L{jsݘKc;%D-Uy&^aR#/o<6I! ˝ƤTK1;7 Z^"?ͪo@ ?"9Z땰F|W(aZLib9 iSY2hśt0R+ VbН~Onp65@H*z-|[L;J ?)5*[zl?wF~LP P<ؐqHQ1MEJ㺜$FLF 9C?;J$*wś&dբB#6WʹyX?";ޡ_ys" A"5(f2-z?o+EA`bN˱;y}m;TDPo o o // // Types and structures... // typedef enum _pappl_http_chunk_e // HTTP chunk phases { _PAPPL_HTTP_CHUNK_HEADER, // Reading chunk header (lengths) _PAPPL_HTTP_CHUNK_DATA, // Reading chunk data _PAPPL_HTTP_CHUNK_TRAILER // Reading chunk trailer (hashes, etc.; not generally used) } _pappl_http_chunk_t; typedef enum _pappl_http_phase_e // HTTP state phases (sub-states) { _PAPPL_HTTP_PHASE_CLIENT_HEADERS, // Headers going to server _PAPPL_HTTP_PHASE_CLIENT_DATA, // Data going to server _PAPPL_HTTP_PHASE_SERVER_HEADERS, // Headers coming back from server _PAPPL_HTTP_PHASE_SERVER_DATA // Data coming back from server } _pappl_http_phase_t; typedef struct _pappl_http_buffer_s // HTTP data buffer { size_t used; // Bytes used in buffer char data[HTTP_MAX_BUFFER]; // Data in buffer } _pappl_http_buffer_t; typedef struct _pappl_http_monitor_s // HTTP state monitoring data { http_state_t state; // Current HTTP state _pappl_http_phase_t phase; // Current HTTP state phase http_status_t status; // Status of most recent request const char *error; // Error message, if any http_encoding_t data_encoding; // Chunked or not off_t data_length, // Original length of data/chunk data_remaining; // Number of bytes left _pappl_http_chunk_t data_chunk; // Phase for chunked data _pappl_http_buffer_t host; // Data from client/host _pappl_http_buffer_t device; // Data from server/device } _pappl_http_monitor_t; // // Functions... // extern const char *_papplHTTPMonitorGetError(_pappl_http_monitor_t *hm) _PAPPL_PRIVATE; extern http_state_t _papplHTTPMonitorGetState(_pappl_http_monitor_t *hm) _PAPPL_PRIVATE; extern void _papplHTTPMonitorInit(_pappl_http_monitor_t *hm) _PAPPL_PRIVATE; extern http_status_t _papplHTTPMonitorProcessDeviceData(_pappl_http_monitor_t *hm, const char *data, size_t datasize) _PAPPL_PRIVATE; extern http_status_t _papplHTTPMonitorProcessHostData(_pappl_http_monitor_t *hm, const char **data, size_t *datasize) _PAPPL_PRIVATE; #endif // !PAPPL_HTTPMON_PRIVATE_H pappl-1.4.9/pappl/httpmon.c000066400000000000000000000513001476704353100156230ustar00rootroot00000000000000// // Private HTTP monitor implementation for the Printer Application Framework // // Copyright © 2021 by Michael R Sweet. // Copyright © 2012 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "httpmon-private.h" // // Local functions... // static size_t http_buffer_add(_pappl_http_buffer_t *hb, const char **data, size_t *datasize); static size_t http_buffer_consume(_pappl_http_buffer_t *hb, const char **data, size_t *datasize, size_t bytes); static char *http_buffer_line(_pappl_http_monitor_t *hm, _pappl_http_buffer_t *hb, const char **data, size_t *datasize, char *line, size_t linesize); // // '_papplHTTPMonitorGetError()' - Get the current HTTP monitor error, if any. // // This function returns the current error message for the monitor. If there // is no error, `NULL` is returned. // const char * // O - Error message or `NULL` for none _papplHTTPMonitorGetError( _pappl_http_monitor_t *hm) // I - HTTP monitor { return (hm->error); } // // '_papplHTTPMonitorGetState()' - Get the current state of the HTTP monitor. // // This function returns the current HTTP state of the HTTP monitor. The // value `HTTP_STATE_WAITING` specifies that there is no active HTTP request or // response traffic. // http_state_t // O - HTTP state _papplHTTPMonitorGetState( _pappl_http_monitor_t *hm) // I - HTTP monitor { return (hm->state); } // // '_papplHTTPMonitorInit()' - Initialize a HTTP monitoring structure. // // This function initializes a `_pappl_http_monitor_t` structure to the // `HTTP_WAITING` state. Each connection needs an instance of this structure. // // When data comes in from the client/USB host, call the // @link _papplHTTPMonitorProcessHostData@ function. Similarly, when data // comes in from the printer/USB device, call the // @link _papplHTTPMonitorProcessDeviceData@ function. // // To get the current HTTP state, call the @link _papplHTTPMonitorGetState@ // function. // void _papplHTTPMonitorInit( _pappl_http_monitor_t *hm) // I - HTTP monitor { memset(hm, 0, sizeof(_pappl_http_monitor_t)); hm->status = HTTP_STATUS_CONTINUE; } // // '_papplHTTPMonitorProcessHostData()' - Process data from the USB host. // // This function processes data provided by the HTTP client/USB host, // returning the current HTTP status for the "connection". // // `HTTP_STATUS_ERROR` is returned for errors in the HTTP client request. // `HTTP_STATUS_CONTINUE` is returned when there is no error. // http_status_t // O - Current HTTP status _papplHTTPMonitorProcessHostData( _pappl_http_monitor_t *hm, // I - HTTP monitor const char **data, // IO - Data from USB host size_t *datasize) // IO - Number of bytes of data { char line[2048], // Header line *ptr; // Pointer into line size_t bytes; // Bytes remaining while (hm->status != HTTP_STATUS_ERROR && (hm->host.used > 0 || *datasize > 0)) { switch (hm->state) { case HTTP_STATE_WAITING : // Get request: "METHOD PATH HTTP/major.minor" if (!http_buffer_line(hm, &hm->host, data, datasize, line, sizeof(line))) return (hm->status); // Split the leading request method from the line... if ((ptr = strchr(line, ' ')) == NULL) { // No whitespace, so the request line is probably malformed hm->status = HTTP_STATUS_ERROR; hm->error = "Bad request line."; break; } *ptr = '\0'; // Update the state based on the method... hm->status = HTTP_STATUS_CONTINUE; hm->data_encoding = HTTP_ENCODING_LENGTH; hm->data_length = hm->data_remaining = 0; if (!strcasecmp(line, "OPTIONS")) { hm->state = HTTP_STATE_OPTIONS; } else if (!strcasecmp(line, "GET")) { hm->state = HTTP_STATE_GET; } else if (!strcasecmp(line, "HEAD")) { hm->state = HTTP_STATE_HEAD; } else if (!strcasecmp(line, "POST")) { hm->state = HTTP_STATE_POST; } else if (!strcasecmp(line, "PUT")) { hm->state = HTTP_STATE_PUT; } else if (!strcasecmp(line, "DELETE")) { hm->state = HTTP_STATE_DELETE; } else { hm->status = HTTP_STATUS_ERROR; hm->error = "Unknown request method seen."; break; } break; case HTTP_STATE_OPTIONS : case HTTP_STATE_GET : case HTTP_STATE_HEAD : case HTTP_STATE_POST : case HTTP_STATE_PUT : case HTTP_STATE_DELETE : switch (hm->phase) { case _PAPPL_HTTP_PHASE_CLIENT_HEADERS : /* Waiting for blank line */ if (!http_buffer_line(hm, &hm->host, data, datasize, line, sizeof(line))) return (hm->status); if (!line[0]) { // Got a blank line, advance state machine... if (hm->state == HTTP_STATE_POST || hm->state == HTTP_STATE_PUT) { hm->phase = _PAPPL_HTTP_PHASE_CLIENT_DATA; } else { hm->phase = _PAPPL_HTTP_PHASE_SERVER_HEADERS; return (HTTP_STATUS_CONTINUE); } break; } // Try to get the "header: value" bits on this line... if ((ptr = strchr(line, ':')) == NULL) { hm->status = HTTP_STATUS_ERROR; hm->error = "No separator seen in request header line."; break; } *ptr++ = '\0'; // Nul-terminate header name while (isspace(*ptr & 255)) ptr ++; // Skip whitespace if (!strcasecmp(line, "Transfer-Encoding") && !strcasecmp(ptr, "chunked")) { // Using chunked encoding... hm->data_encoding = HTTP_ENCODING_CHUNKED; hm->data_length = hm->data_remaining = 0; hm->data_chunk = _PAPPL_HTTP_CHUNK_HEADER; } else if (!strcasecmp(line, "Content-Length")) { // Using fixed Content-Length... hm->data_encoding = HTTP_ENCODING_LENGTH; hm->data_length = hm->data_remaining = strtol(ptr, NULL, 10); if (hm->data_length < 0) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (negative) Content-Length value."; break; } } break; case _PAPPL_HTTP_PHASE_CLIENT_DATA : // Sending data if (hm->data_encoding == HTTP_ENCODING_CHUNKED) { // Skip chunked data... switch (hm->data_chunk) { case _PAPPL_HTTP_CHUNK_HEADER : if (!http_buffer_line(hm, &hm->host, data, datasize, line, sizeof(line))) return (hm->status); // Get chunk length (hex) if (!line[0]) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (empty) chunk length."; break; } hm->data_length = hm->data_remaining = strtol(line, NULL, 16); if (hm->data_length == 0) { // 0-length chunk signals end-of-message hm->data_chunk = _PAPPL_HTTP_CHUNK_TRAILER; } else if (hm->data_length < 0) { // Negative lengths not allowed hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (negative) chunk length."; break; } else { // Advance to the data phase of chunk processing hm->data_chunk = _PAPPL_HTTP_CHUNK_DATA; } break; case _PAPPL_HTTP_CHUNK_DATA : if (hm->data_remaining > 0) { bytes = http_buffer_consume(&hm->host, data, datasize, (size_t)hm->data_remaining); hm->data_remaining -= (off_t)bytes; } if (hm->data_remaining == 0) { // End of data, expect chunk trailer... hm->data_chunk = _PAPPL_HTTP_CHUNK_TRAILER; break; } break; case _PAPPL_HTTP_CHUNK_TRAILER : // Look for blank line at end of chunk if (!http_buffer_line(hm, &hm->host, data, datasize, line, sizeof(line))) return (hm->status); if (line[0]) { // Expected blank line... hm->status = HTTP_STATUS_ERROR; hm->error = "Expected blank line at end of chunk."; break; } // Change states... if (hm->data_length == 0) { // Got a 0-length chunk, transition to the server headers phase hm->phase = _PAPPL_HTTP_PHASE_SERVER_HEADERS; hm->status = HTTP_STATUS_CONTINUE; hm->data_encoding = HTTP_ENCODING_LENGTH; hm->data_length = hm->data_remaining = 0; return (HTTP_STATUS_CONTINUE); } else { // Normal chunk, look for the next one... hm->data_chunk = _PAPPL_HTTP_CHUNK_HEADER; } break; } } else { // Skip fixed-length data... if (hm->data_remaining > 0) { bytes = http_buffer_consume(&hm->host, data, datasize, (size_t)hm->data_remaining); hm->data_remaining -= (off_t)bytes; } if (hm->data_remaining == 0) { // End of data, expect server headers in response... hm->phase = _PAPPL_HTTP_PHASE_SERVER_HEADERS; hm->status = HTTP_STATUS_CONTINUE; hm->data_encoding = HTTP_ENCODING_LENGTH; hm->data_length = hm->data_remaining = 0; return (HTTP_STATUS_CONTINUE); } } break; default : /* Expecting something from the server... */ hm->status = HTTP_STATUS_ERROR; hm->error = "Client data sent while expecting response from server."; break; } break; default : /* Error out if we get here */ hm->status = HTTP_STATUS_ERROR; hm->error = "Unexpected HTTP state."; break; } } return (hm->status); } // // '_papplHTTPMonitorProcessDeviceData()' - Process data from the USB device. // // This function processes data provided by the HTTP server/IPP Printer/USB // device, returning the current HTTP status for the "connection". // // `HTTP_STATUS_ERROR` is returned for errors in the HTTP server response. // `HTTP_STATUS_CONTINUE` is returned when there is no error. // http_status_t // O - Current HTTP status _papplHTTPMonitorProcessDeviceData( _pappl_http_monitor_t *hm, // I - HTTP monitor const char *data, // I - Data size_t datasize) // I - Number of bytes of data { char line[2048], // Header line from server *ptr; // Pointer into line size_t bytes; // Bytes consumed while (hm->status != HTTP_STATUS_ERROR && (hm->host.used > 0 || datasize > 0)) { switch (hm->state) { case HTTP_STATE_OPTIONS : case HTTP_STATE_GET : case HTTP_STATE_HEAD : case HTTP_STATE_POST : case HTTP_STATE_PUT : case HTTP_STATE_DELETE : switch (hm->phase) { case _PAPPL_HTTP_PHASE_SERVER_HEADERS : /* Waiting for blank line */ if (!http_buffer_line(hm, &hm->host, &data, &datasize, line, sizeof(line))) return (hm->status); if (!line[0]) { if (hm->status) { // Got a blank line, advance state machine... if (hm->state != HTTP_STATE_HEAD && (hm->data_remaining > 0 || hm->data_encoding == HTTP_ENCODING_CHUNKED)) { hm->phase = _PAPPL_HTTP_PHASE_SERVER_DATA; } else if (hm->status != HTTP_STATUS_CONTINUE) { hm->state = HTTP_STATE_WAITING; hm->phase = _PAPPL_HTTP_PHASE_CLIENT_HEADERS; } } break; } // See if the line has a status code value... if (hm->status == HTTP_STATUS_CONTINUE && !strncmp(line, "HTTP/", 5)) { // Got the beginning of a response... int intstatus; // Status value as an integer int major, minor; // HTTP version numbers if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3) { hm->status = HTTP_STATUS_ERROR; hm->error = "Malformed HTTP header seen in response."; break; } hm->status = (http_status_t)intstatus; if (hm->status < 100) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad HTTP status seen in response."; } break; } // Try to get the "header: value" bits on this line... if ((ptr = strchr(line, ':')) == NULL) { hm->status = HTTP_STATUS_ERROR; hm->error = "No separator seen in response header line."; break; } *ptr++ = '\0'; // Nul-terminate header name while (isspace(*ptr & 255)) ptr ++; // Skip whitespace if (!strcasecmp(line, "Transfer-Encoding") && !strcasecmp(ptr, "chunked")) { // Using chunked encoding... hm->data_encoding = HTTP_ENCODING_CHUNKED; hm->data_length = hm->data_remaining = 0; hm->data_chunk = _PAPPL_HTTP_CHUNK_HEADER; } else if (!strcasecmp(line, "Content-Length")) { // Using fixed Content-Length... hm->data_encoding = HTTP_ENCODING_LENGTH; hm->data_length = hm->data_remaining = strtol(ptr, NULL, 10); if (hm->data_length < 0) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (negative) Content-Length value."; break; } } break; case _PAPPL_HTTP_PHASE_SERVER_DATA : // Receiving data if (hm->data_encoding == HTTP_ENCODING_CHUNKED) { // Skip chunked data... switch (hm->data_chunk) { case _PAPPL_HTTP_CHUNK_HEADER : if (!http_buffer_line(hm, &hm->host, &data, &datasize, line, sizeof(line))) return (hm->status); // Get chunk length (hex) if (!line[0]) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (empty) chunk length."; break; } hm->data_length = hm->data_remaining = strtol(line, NULL, 16); if (hm->data_length == 0) { // 0-length chunk signals end-of-message hm->data_chunk = _PAPPL_HTTP_CHUNK_TRAILER; } else if (hm->data_length < 0) { // Negative lengths not allowed hm->status = HTTP_STATUS_ERROR; hm->error = "Bad (negative) chunk length."; break; } else { // Advance to the data phase of chunk processing hm->data_chunk = _PAPPL_HTTP_CHUNK_DATA; } break; case _PAPPL_HTTP_CHUNK_DATA : // Consume chunk data... if (hm->data_remaining > 0) { bytes = http_buffer_consume(&hm->host, &data, &datasize, (size_t)hm->data_remaining); hm->data_remaining -= (off_t)bytes; } if (hm->data_remaining == 0) { // End of data, expect chunk trailer... hm->data_chunk = _PAPPL_HTTP_CHUNK_TRAILER; break; } break; case _PAPPL_HTTP_CHUNK_TRAILER : // Look for blank line at end of chunk if (!http_buffer_line(hm, &hm->host, &data, &datasize, line, sizeof(line))) return (hm->status); if (line[0]) { // Expected blank line... hm->status = HTTP_STATUS_ERROR; hm->error = "Expected blank line at end of chunk."; break; } // Change states... if (hm->data_length == 0) { // Got a 0-length chunk, transition to the waiting state hm->phase = _PAPPL_HTTP_PHASE_CLIENT_HEADERS; hm->state = HTTP_STATE_WAITING; break; } else { // Normal chunk, look for the next one... hm->data_chunk = _PAPPL_HTTP_CHUNK_HEADER; } break; } } else { // Skip fixed-length data... if (hm->data_remaining > 0) { bytes = http_buffer_consume(&hm->host, &data, &datasize, (size_t)hm->data_remaining); hm->data_remaining -= (off_t)bytes; } if (hm->data_remaining == 0) { // End of data, expect new request from client... hm->phase = _PAPPL_HTTP_PHASE_CLIENT_HEADERS; hm->state = HTTP_STATE_WAITING; break; } } break; case _PAPPL_HTTP_PHASE_CLIENT_HEADERS : // Expecting headers from the client... hm->status = HTTP_STATUS_ERROR; hm->error = "Server cannot respond while client is sending request headers."; break; case _PAPPL_HTTP_PHASE_CLIENT_DATA : // Server may send failure response before client completes POST/PUT if (!http_buffer_line(hm, &hm->host, &data, &datasize, line, sizeof(line))) return (hm->status); if (!strncmp(line, "HTTP/", 5)) { // Got the beginning of a response... int intstatus; // Status value as an integer int major, minor; // HTTP version numbers if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3) { hm->status = HTTP_STATUS_ERROR; hm->error = "Malformed HTTP header seen in early response."; break; } hm->status = (http_status_t)intstatus; if (intstatus != 100 && (intstatus < 400 || intstatus >= 500)) { hm->status = HTTP_STATUS_ERROR; hm->error = "Bad server status code seen during client data phase."; } else if (hm->status != HTTP_STATUS_CONTINUE) hm->phase = _PAPPL_HTTP_PHASE_SERVER_HEADERS; } else if (line[0]) { hm->status = HTTP_STATUS_ERROR; hm->error = "Unexpected server response seen during client data phase."; } break; } break; default : hm->status = HTTP_STATUS_ERROR; hm->error = "Unexpected HTTP state."; break; } } return (hm->status); } // // 'http_buffer_add()' - Add bytes to the buffer from the data stream. // static size_t // O - Number of bytes added http_buffer_add( _pappl_http_buffer_t *hb, // I - HTTP buffer const char **data, // IO - Pointer to data size_t *datasize) // IO - Bytes of data (remaining) { size_t bytes = 0; // Bytes to add if (*datasize > 0 && hb->used < HTTP_MAX_BUFFER) { // Copy more data into client_data if ((bytes = HTTP_MAX_BUFFER - hb->used) > *datasize) bytes = *datasize; memcpy(hb->data + hb->used, *data, bytes); (*data) += bytes; (*datasize) -= bytes; hb->used += bytes; } return (bytes); } // // 'http_buffer_consume()' - Consume bytes from the buffer or data stream. // static size_t // O - Total bytes consumed http_buffer_consume( _pappl_http_buffer_t *hb, // I - HTTP buffer const char **data, // IO - Pointer to (new) data size_t *datasize, // IO - Bytes of (new) data size_t bytes) // I - Bytes to consume { size_t total = 0; // Total bytes consumed // Consume first from the buffer if (hb->used > 0) { if (bytes >= hb->used) { // Consume all of the buffer bytes -= hb->used; total += hb->used; hb->used = 0; } else { // Consume part of the buffer and move things around memmove(hb->data, hb->data + bytes, hb->used - bytes); hb->used -= bytes; total += bytes; bytes = 0; } } if (bytes > 0 && *datasize > 0) { // Didn't consume everything requested, pull from the data stream if (bytes >= *datasize) { // Consume all of the data stream (*data) += *datasize; total += *datasize; *datasize = 0; } else { // Consume part of the data stream (*data) += bytes; (*datasize) -= bytes; total += bytes; } } // Return the total number of bytes consumed return (total); } // // 'http_buffer_line()' - Copy a single line from the buffer or data stream, // stripping CR and LF. // static char * // O - Pointer to line or `NULL` if none http_buffer_line( _pappl_http_monitor_t *hm, // I - HTTP monitor _pappl_http_buffer_t *hb, // I - HTTP buffer const char **data, // IO - Pointer to data size_t *datasize, // IO - Number of bytes of data char *line, // I - Line buffer size_t linesize) // I - Size of line buffer { char *lineptr, // Pointer into line buffer *lineend; // Pointer to end of line buffer const char *dataptr, // Pointer into data buffer *dataend; // Pointer to end of data buffer bool eol = false; // EOL seen? // See if the buffer or data stream contains a newline... if ((hb->used == 0 || !memchr(hb->data, '\n', hb->used)) && (*datasize == 0 || !memchr(*data, '\n', *datasize))) { // No, try to add the data stream to the buffer and return... http_buffer_add(hb, data, datasize); *line = '\0'; if (*datasize > 0) { // Line is too long... hm->status = HTTP_STATUS_ERROR; hm->error = "Line too large for buffer."; } return (NULL); } // Grab one line from the input buffer lineptr = line; lineend = line + linesize - 1; dataptr = hb->data; dataend = hb->data + hb->used; while (!eol && dataptr < dataend) { if (*dataptr == '\n') eol = true; else if (*dataptr != '\r' && lineptr < lineend) *lineptr++ = *dataptr; dataptr ++; } // If we consumed any data in the buffer, move the remainder to the front // of the buffer... if (dataptr < dataend) memmove(hb->data, dataptr, dataend - dataptr); hb->used -= (size_t)(dataptr - hb->data); if (!eol) { // Didn't get the whole line in our buffer, grab the rest from the data // stream... dataptr = *data; dataend = *data + *datasize; while (!eol && dataptr < dataend) { if (*dataptr == '\n') eol = true; else if (*dataptr != '\r' && lineptr < lineend) *lineptr++ = *dataptr; dataptr ++; } *data = dataptr; *datasize = (size_t)(dataend - dataptr); } // Add a trailing nul and return the line... *lineptr = '\0'; return (line); } pappl-1.4.9/pappl/icon-lg.png000066400000000000000000000313421476704353100160300ustar00rootroot00000000000000PNG  IHDRxiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*i(0eiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image Sve*IDATx }'J@  c6&c+8EK 悃r y\*IL"6v`DɕmH8rSs."D@F VZIUvG433ӟO2#vf6hP.@@@@@@@@@^W @@@@@@u}sLzWJկ~H+Wt2Sկ~@(~_G@gկ~#@~_Vկ~@(կ~hnnjIƍKcǎM]]]kzHﷀZĉԩSӴiҔ)Sɓ&M񼧧g#~o„ ~?>:CٺukzGg?Y (DW E~xooW>}z5kV9sf1cF3^GtC~gjo7q?`W^ ҩ<餓҉'_osחvؑ^{Ǯ]Fzٳ#ݻc߾}#+Vhp@ѢE㬳||#:m۶۷kCGg:iFSNIg}v836Gt/bڴiSؼys8{-Ey??moG׏ӆ 7n;g^;r . ?_8Ϧgy&=i# tr}{_ZdI~ha׮]ѯZ*=syW?-(.a{׻ޕs=.i۽{wz'Қ5k?||Pe˖x>UTk;f~n5www?ῑ8|c;c潡P٭AٖC;z _eg*n=NK/MW_}Gػw?^~厨*(TMLaZy[ޒ>O?O tT$nWhq^p8\1]_ PV;I{?c;O_y7|s~Mz(-_<7˿&O淴)~/~ӟ믿?@iָi}700>ώ/PZߘ8z|Z`A1-Z4y?27?cիW??hsCP!sO?tя~x&˨Yz{{Az7nܸӓf͚ϟ%QEv-[nժUTӖW~WK[rZaWn (E?dɒ?Ϥ+Vx|pߡ޽{~կ~5=smWњY3ҥKe]w& qwygG56D7Vlvm+W:Z䇟|Ʌ}I C|C9s'NLwqGZ`A}׿Lj[_fֿ{Oo~yviiڴi'gN<}!kb[k}ߕ_Jpӱ{c~i-‘O-pNx /ww_C=QߴiS~ϯ7" >]'mٮ . W!ƘGin+2{C Wq>xH~_kuY51@)YΨ]LŸo}[͝;7M^ꪫ*lw@/U]tшaɓ'ƍoZStxe2iΏbΝy؋Ie`1(4޷5feS֑d\fT[oXcY2՚5kiei/uԧ^G4b+u,шId+G iK*|ߨˡ8_ /o떩N|p =yOsX S_W 7pK.$}_>|3oV[jGh?wwuy8/]1mbƲeH˾Zq91LtmЂmsk?\=bƲ=ҲV FVN,3R )SE7ԯQl+}-xGjj3gZmH["0q7y\W^]:rc۷4D܎-!!Q}^z=Q*z F<_~Fau֍x~Ϸ_mLl|O=sʛDF["PE=Temݺuʁqod[j6UNd G FFΟ?_pubƍ}W@-\BĆ ,V{9*;V7H岭`ubڵ}W@-Z(͘1ne˖O8 A*m岯E N zj :q/rҥu{{l=i\7lƲ=ҲE Ï,[.m۶Nte׷RtI'9P2ie_Xb]Сt[iQ1/N+W{=;N G ;͞=;?ނ/Fǀ8?3~{キ-Bt&1`͛7I@Zs|X'n64FWtMipppDu7iӦY8.8zaXbصkH(P!;sk1[o;mq.:QۿJoO>A!`a:Kime@ @(8}.=rK>L.4 -M+hX*__%\ aW]uUg[ihhhhͣc:9l˿}\#~ 7䷆kMƝ1 nݚ޽{-&C===i֬Yy,\0op_Kb#ô(pG>tԑ3$?(x#o|#)K.IVv4tc  Pv /:/| _ri}qz&:V (@{3g @3~_PWկ~@@ F_W? QWՏ(`_G20 XW:.s˖-|hTj幩F]п7˹zQ6__v]c Xbŋ"6_+Wl>0N(`_G@`.p_G20 XW3~_PF_W?  tկ~(`_G@`կ~#@~_Vկ~@(կ~:QWՏe`կ~# @g0 XW Vկ~m0dŊl_x g,Bgcw~_~_PF_W?  tկ~(`_GԷ^lوC*i#_.sțT[Qˡ_z[m/u?)ue2/>{W ^tES]|ʕ+[.S2 XW Vկ~@@ F_W? QWՏ(`_G20 XW3~_PF_W?  tկ~(`_GF<7nr({zz,Pw@x>k, :T]#DEݸq/Ueor%aÆ.\h@ܾ+Qk׮s)Ueor%z-Zf̘a@:#mȶmҺu<;vlZt&ؾv?%vx~e. :Dlϱ]iGZal|۷)|;؞_{+W,V~\s5fqlϕ(ػ+߿y+4߹vc{bB{wkW\qE:3-hSv<\lEO@Җ-[<ßӜ9s,h3sͷ#cFصkW馛7ߜMfA//Fb:Ah6 vժU;Z[r$(pb;rخcߞ|Bˍ gllϱ]BZql*>~[n%]}uD(pb{28?\ EW]uU7k@(PlC{ 8\KZ}\W| 7W`ė=ܓ?" sq`ʔ)[XP|M___wckڸ-Jx@ԯ~< LBWկ~@(s_W?  tկ~h ࿡{,[쐉rt׽ވׇO(^<]e_nԯ~̀ @C~_PWկ~@@ F_W?4Aq s=闶l{fJJcƤmǥ-現q-W᜴sW>?x5K-hjR{6bo&ӟz[3cjZ?y?muOogɾ`>-S/-\~M-[G>5m߾tSO=kL׮{&?la _Z\YP{`._Nm\Ex1G9trM{sX_Lr~4`o}z(-FYS} Ц<{Kau|җlv{nH7~ٹFxg6@3jО {h MY5ڒɂopt,k]_]OCϿ۰}i7<}L DsS}P=3FsaqǦtAO&F]~l6g{<.:Z=nO;!\ʖTn9&-|mŽqZ[=Y;p/o^zaRψfd(V5.T{KvӘuUK!JV{6=VԃSo:*4bZݸ7di}6/+UfIL >h1[&LH_8}aꌽҩٍYmqUpfϬȂFٸTm 翞65}o}O;j3*@׿Nizg+U t;Xtrʽ?yt?fIS} ̅; kuq {?T#ɇjVY뫫 @6T.d*xs `;ffiGZ=ocOm_c뷊eG_~wUĉ]65?A#[=m`BLW9֗'TM{P{UQ v{ƎϊOS>ܨivnzg+ߌU,|O_w'=we_kٳb1pS} R8F}װf׻=eKߵ~Ҥ/&~vmzg߬Uhc/ҏ?LͿnQ { _7/О6[<~aGm:we#_8a]&npV:p,Lؿ_{:/)_C]];j^3l}*o`6>(Gveޝ~h i(oџ#v;ܣ?6iz#۳/r}uںK}Ξ?۽;/ۋ:{O69G>^=ޏvC̪:]0u|>>J(FK ^LmrKQ=}7Xwu~jf{(Gs? cНuD,x+g#vX_]pmdּݻY١ewdתW1olaXKT @Z]ٗ5>\W ^,L tF6-]@{2q'S;4rwd@(!Fzi„t5?^|*;8o3UYRg]_]O2Ȯó~!mD*kq5'r`AvI;wiOP6!?G=Q?ۓ{tìTm~}jѴgZ_]h0{kOHxaoSTk;f̏T8x);=c4'XTtS=}{=uśk߫Iz{/#xԶo姞 67H~urFL73_}-ɦ{m'g-??F{#p@[4a|Xiiv?z}l:`;vT7cm۳gTeNsa?0wN΃]w6?(K3@#ڳV 2@:ƹ^]YpP ݮwn٦11{n'Y!^t;Խ{I @s.a-:]®W;"l~E vw+[~/sҎq bOtտwf6-lz`wx?MӨ6n?=]u0ih^8O mmnvI7n❾šӚh8J˖-|hTj幩F>|6f|;kZV=nRjy[uֵ OMd7j?>5?:u4?{:i~n|4QѮXu[;vlڽ緼8q{o9ؖ\nE/N _ώjKrIԪ҂ =տmoߝGk-ۏbywZ{ZkkK.{#\) `tutLM{y%U@\AzPmxKc:W6iN̿!nۘP6kg@޲/KޤskAƍwc.1:{^h.k!YA7stNph?{/@+mW|qsdY34/I@8o{5;y͘v:WggLmڻ߿_w W @*9o!{fnq-4: Pn7{~_vhj`@`j={lk*&xH|I eٕ{{vz$1n.120pɦL 4ԯ~:{_W? QWՏ(`_G20 XW3~_@t0@@@@@@@Z^E@uYh"@@@@@@@<؄ntIENDB`pappl-1.4.9/pappl/icon-md.png000066400000000000000000000072431476704353100160310ustar00rootroot00000000000000PNG  IHDRiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*ikF&MeiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image SvemPLTE@??@@@A??AAAB??BBBC>>CCCD>>DDDE>>EEEF==FFFG==GGGH==HHHIIIJ<(~a>sg<")c 0Swf_Z7.whM !y t¶_(1c\/mn(k$-?}M [\鮅V.~>OSAl{{}L 3:SϰkVVL8ˏmtJwɶjcHL'}n_#ctY5@ >@qh$Dkع¯7p3k>sM |,,ÐM-֞ p@[ Su=##Ɉ@=fќj)1/T  vM M4`pYXOJ 8l,gņ䈦r@爆i Phh80@ Sd:$&&vI 8ݘPDUaG.eu. Z8 CL0yįtBU4|C$}UҠ*' 室# U<p9_*xg@hT9*3@KB%n"tP j=<²). <mjt@ɮ1I֎],:SGi?Pa1duQXdejץ6:_x8;"?xZC?F  U~ܹIENDB`pappl-1.4.9/pappl/icon-sm.png000066400000000000000000000055061476704353100160500ustar00rootroot00000000000000PNG  IHDR00` iCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x c8eXIfMM*i00N6eiTXtXML:com.adobe.xmp New Image Copyright 2020 Michael Sweet Michael Sweet New Image SvezPLTE<<<@@@AAAC>>CCCD>>DDDEEEF==HHHJ<;=9:&(&(79%'%'$&!$!$03!# " ""! (+%(#& #!           YtRNS@fIDATHՖgW0@*q8popO.[h5(P*$=s|?MmFuJT#R+ w]^(Z3b$,ߙ{|5ßeeѓY%‹H9鿻O9+P{% &P߉ms>s '\ )b@\c|8ۦ!_"Ħ"qR D쒆)`$rT 6WD (0&}Iw>yF)=# =MFʹHK^(6V$~ڤ: g99Oxu 83q3VJ"j:s }葊ZϣM\gTB'$\V(#KOKUWxg6NIENDB`pappl-1.4.9/pappl/ipp.strings000066400000000000000000000526721476704353100162060ustar00rootroot00000000000000/* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Number of Copies"; "finishings" = "Finisher"; "finishings.10" = "Fold"; "finishings.100" = "Z fold"; "finishings.101" = "Engineering Z fold"; "finishings.11" = "Cut"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Staple top left"; "finishings.21" = "Staple bottom left"; "finishings.22" = "Staple top right"; "finishings.23" = "Staple bottom right"; "finishings.24" = "Edge stitch left"; "finishings.25" = "Edge stitch top"; "finishings.26" = "Edge stitch right"; "finishings.27" = "Edge stitch bottom"; "finishings.28" = "2 staples on left"; "finishings.29" = "2 staples on top"; "finishings.3" = "None"; "finishings.30" = "2 staples on right"; "finishings.31" = "2 staples on bottom"; "finishings.32" = "3 staples on left"; "finishings.33" = "3 staples on top"; "finishings.34" = "3 staples on right"; "finishings.35" = "3 staples on bottom"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind left"; "finishings.51" = "Bind top"; "finishings.52" = "Bind right"; "finishings.53" = "Bind bottom"; "finishings.6" = "Cover"; "finishings.60" = "Cut after every page"; "finishings.61" = "Cut after every document"; "finishings.62" = "Cut after every set"; "finishings.63" = "Cut after job"; "finishings.7" = "Bind"; "finishings.70" = "Punch top left"; "finishings.71" = "Punch bottom left"; "finishings.72" = "Punch top right"; "finishings.73" = "Punch bottom right"; "finishings.74" = "2-hole punch left"; "finishings.75" = "2-hole punch top"; "finishings.76" = "2-hole punch right"; "finishings.77" = "2-hole punch bottom"; "finishings.78" = "3-hole punch left"; "finishings.79" = "3-hole punch top"; "finishings.8" = "Saddle stitch"; "finishings.80" = "3-hole punch right"; "finishings.81" = "3-hole punch bottom"; "finishings.82" = "4-hole punch left"; "finishings.83" = "4-hole punch top"; "finishings.84" = "4-hole punch right"; "finishings.85" = "4-hole punch bottom"; "finishings.86" = "Multi-hole punch left"; "finishings.87" = "Multi-hole punch top"; "finishings.88" = "Multi-hole punch right"; "finishings.89" = "Multi-hole punch bottom"; "finishings.9" = "Edge stitch"; "finishings.90" = "Accordion fold"; "finishings.91" = "Double gate fold"; "finishings.92" = "Gate fold"; "finishings.93" = "Half fold"; "finishings.94" = "Half Z fold"; "finishings.95" = "Left gate fold"; "finishings.96" = "Letter fold"; "finishings.97" = "Parallel fold"; "finishings.98" = "Poster fold"; "finishings.99" = "Right gate fold"; "job-state.3" = "Pending"; "job-state.4" = "Held"; "job-state.5" = "Processing"; "job-state.6" = "Stopped"; "job-state.7" = "Canceled"; "job-state.8" = "Aborted"; "job-state.9" = "Completed"; "job-state-reasons.aborted-by-system" = "Stopping."; "job-state-reasons.compression-error" = "Decompression error."; "job-state-reasons.document-format-error" = "Document format error."; "job-state-reasons.document-password-error" = "Document password error."; "job-state-reasons.document-permission-error" = "Document permission error."; "job-state-reasons.document-unprintable-error" = "Document unprintable error."; "job-state-reasons.errors-detected" = "Errors detected."; "job-state-reasons.job-canceled-at-device" = "Canceled at printer."; "job-state-reasons.job-canceled-by-user" = "Canceled by user."; "job-state-reasons.job-completed-successfully" = "Printed."; "job-state-reasons.job-completed-with-errors" = "Printed with errors."; "job-state-reasons.job-completed-with-warnings" = "Printed with warnings."; "job-state-reasons.job-data-insufficient" = "Insufficient data."; "job-state-reasons.job-fetchable" = "Fetchable."; "job-state-reasons.job-incoming" = "Incoming."; "job-state-reasons.job-printing" = "Printing."; "job-state-reasons.job-queued" = "Preparing to print."; "job-state-reasons.job-spooling" = "Spooling."; "job-state-reasons.none" = "Pending."; "job-state-reasons.printer-stopped" = "Printer offline."; "job-state-reasons.printer-stopped-partly" = "Printer partially stopped."; "job-state-reasons.processing-to-stop-point" = "Stopping."; "job-state-reasons.queued-in-device" = "Ready."; "job-state-reasons.warnings-detected" = "Warnings detected."; "media" = "Media"; "media-col" = "Media"; "media-size" = "Media Size"; "media-size-name" = "Media Size"; "media-source" = "Input Tray"; "media-source.alternate" = "Alternate"; "media-source.alternate-roll" = "Alternate roll"; "media-source.auto" = "Automatic"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Multipurpose tray"; "media-source.center" = "Center"; "media-source.disc" = "Disc"; "media-source.envelope" = "Envelope"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Large capacity"; "media-source.left" = "Left"; "media-source.main" = "Main"; "media-source.main-roll" = "Main roll"; "media-source.manual" = "Manual"; "media-source.middle" = "Middle"; "media-source.photo" = "Photo"; "media-source.rear" = "Rear"; "media-source.right" = "Right"; "media-source.roll-1" = "Roll 1"; "media-source.roll-10" = "Roll 10"; "media-source.roll-2" = "Roll 2"; "media-source.roll-3" = "Roll 3"; "media-source.roll-4" = "Roll 4"; "media-source.roll-5" = "Roll 5"; "media-source.roll-6" = "Roll 6"; "media-source.roll-7" = "Roll 7"; "media-source.roll-8" = "Roll 8"; "media-source.roll-9" = "Roll 9"; "media-source.side" = "Side"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Media Tracking"; "media-tracking.continuous" = "Continuous"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Media Type"; "media-type.aluminum" = "Aluminum"; "media-type.auto" = "Automatic"; "media-type.back-print-film" = "Back print film"; "media-type.cardboard" = "Cardboard"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuous"; "media-type.continuous-long" = "Continuous long"; "media-type.continuous-short" = "Continuous short"; "media-type.corrugated-board" = "Corrugated board"; "media-type.disc" = "Optical disc"; "media-type.disc-glossy" = "Glossy optical disc"; "media-type.disc-high-gloss" = "High gloss optical disc"; "media-type.disc-matte" = "Matte optical disc"; "media-type.disc-satin" = "Satin optical disc"; "media-type.disc-semi-gloss" = "Semi-gloss optical disc"; "media-type.double-wall" = "Double wall"; "media-type.dry-film" = "Dry film"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Embossing foil"; "media-type.end-board" = "End board"; "media-type.envelope" = "Envelope"; "media-type.envelope-archival" = "Archival envelope"; "media-type.envelope-bond" = "Bond envelope"; "media-type.envelope-coated" = "Coated envelope"; "media-type.envelope-cotton" = "Cotton envelope"; "media-type.envelope-fine" = "Fine envelope"; "media-type.envelope-heavyweight" = "Heavyweight envelope"; "media-type.envelope-inkjet" = "Inkjet envelope"; "media-type.envelope-lightweight" = "Lightweight envelope"; "media-type.envelope-plain" = "Plain envelope"; "media-type.envelope-preprinted" = "Preprinted envelope"; "media-type.envelope-window" = "Windowed envelope"; "media-type.fabric" = "Fabric"; "media-type.fabric-archival" = "Archival fabric"; "media-type.fabric-glossy" = "Glossy fabric"; "media-type.fabric-high-gloss" = "High gloss fabric"; "media-type.fabric-matte" = "Matte fabric"; "media-type.fabric-semi-gloss" = "Semi-gloss fabric"; "media-type.fabric-waterproof" = "Waterproof fabric"; "media-type.film" = "Film"; "media-type.flexo-base" = "Flexo base"; "media-type.flexo-photo-polymer" = "Flexo photo polymer"; "media-type.flute" = "Flute"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "Full cut tabs"; "media-type.glass" = "Glass"; "media-type.glass-colored" = "Glass colored"; "media-type.glass-opaque" = "Glass opaque"; "media-type.glass-surfaced" = "Glass surfaced"; "media-type.glass-textured" = "Glass textured"; "media-type.gravure-cylinder" = "Gravure cylinder"; "media-type.image-setter-paper" = "Image setter paper"; "media-type.imaging-cylinder" = "Imaging cylinder"; "media-type.labels" = "Labels"; "media-type.labels-colored" = "Colored labels"; "media-type.labels-glossy" = "Glossy labels"; "media-type.labels-high-gloss" = "High gloss labels"; "media-type.labels-inkjet" = "Inkjet labels"; "media-type.labels-matte" = "Matte labels"; "media-type.labels-permanent" = "Permanent labels"; "media-type.labels-satin" = "Satin labels"; "media-type.labels-security" = "Security labels"; "media-type.labels-semi-gloss" = "Semi-gloss labels"; "media-type.laminating-foil" = "Laminating foil"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal glossy"; "media-type.metal-high-gloss" = "Metal high gloss"; "media-type.metal-matte" = "Metal matte"; "media-type.metal-satin" = "Metal satin"; "media-type.metal-semi-gloss" = "Metal semi gloss"; "media-type.mounting-tape" = "Mounting tape"; "media-type.multi-layer" = "Multi layer"; "media-type.multi-part-form" = "Multi part form"; "media-type.other" = "Other"; "media-type.paper" = "Paper"; "media-type.photographic" = "Photo paper"; "media-type.photographic-archival" = "Photographic archival"; "media-type.photographic-film" = "Photo film"; "media-type.photographic-glossy" = "Glossy photo paper"; "media-type.photographic-high-gloss" = "High gloss photo paper"; "media-type.photographic-matte" = "Matte photo paper"; "media-type.photographic-satin" = "Satin photo paper"; "media-type.photographic-semi-gloss" = "Semi-gloss photo paper"; "media-type.plastic" = "Plastic"; "media-type.plastic-archival" = "Plastic archival"; "media-type.plastic-colored" = "Plastic colored"; "media-type.plastic-glossy" = "Plastic glossy"; "media-type.plastic-high-gloss" = "Plastic high gloss"; "media-type.plastic-matte" = "Plastic matte"; "media-type.plastic-satin" = "Plastic satin"; "media-type.plastic-semi-gloss" = "Plastic semi gloss"; "media-type.plate" = "Plate"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "Pre cut tabs"; "media-type.roll" = "Roll"; "media-type.screen" = "Screen"; "media-type.screen-paged" = "Screen paged"; "media-type.self-adhesive" = "Self adhesive"; "media-type.self-adhesive-film" = "Self adhesive film"; "media-type.shrink-foil" = "Shrink foil"; "media-type.single-face" = "Single face"; "media-type.single-wall" = "Single wall"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Stationery"; "media-type.stationery-archival" = "Stationery archival"; "media-type.stationery-coated" = "Coated paper"; "media-type.stationery-cotton" = "Stationery cotton"; "media-type.stationery-fine" = "Vellum paper"; "media-type.stationery-heavyweight" = "Heavyweight paper"; "media-type.stationery-heavyweight-coated" = "Stationery heavyweight coated"; "media-type.stationery-inkjet" = "Stationery inkjet paper"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Lightweight paper"; "media-type.stationery-preprinted" = "Preprinted paper"; "media-type.stationery-prepunched" = "Punched paper"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transfer"; "media-type.transparency" = "Transparency"; "media-type.triple-wall" = "Triple wall"; "media-type.wet-film" = "Wet film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 or US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Envelope"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Envelope"; "media.iso_c10_28x40mm" = "C10 Envelope"; "media.iso_c1_648x917mm" = "C1 Envelope"; "media.iso_c2_458x648mm" = "C2 Envelope"; "media.iso_c3_324x458mm" = "C3 Envelope"; "media.iso_c4_229x324mm" = "C4 Envelope"; "media.iso_c5_162x229mm" = "C5 Envelope"; "media.iso_c6_114x162mm" = "C6 Envelope"; "media.iso_c6c5_114x229mm" = "C6/C5 Envelope"; "media.iso_c7_81x114mm" = "C7 Envelope"; "media.iso_c7c6_81x162mm" = "C7/C6 Envelope"; "media.iso_c8_57x81mm" = "C8 Envelope"; "media.iso_c9_40x57mm" = "C9 Envelope"; "media.iso_dl_110x220mm" = "DL Envelope"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Envelope Chou 2"; "media.jpn_chou3_120x235mm" = "Envelope Chou 3"; "media.jpn_chou40_90x225mm" = "Envelope Chou 40"; "media.jpn_chou4_90x205mm" = "Envelope Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Envelope Kahu"; "media.jpn_kaku2_240x332mm" = "Envelope Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Reply Postcard"; "media.jpn_you4_105x235mm" = "Envelope You 4"; "media.na_a2_4.375x5.75in" = "Envelope A2"; "media.na_c5_6.5x9.5in" = "Envelope C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "US Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "Statement"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US Letter (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US Letter (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Envelope Monarch"; "media.na_number-10_4.125x9.5in" = "Envelope #10"; "media.na_number-11_4.5x10.375in" = "Envelope #11"; "media.na_number-12_4.75x11in" = "Envelope #12"; "media.na_number-14_5x11.5in" = "Envelope #14"; "media.na_number-9_3.875x8.875in" = "Envelope #9"; "media.na_personal_3.625x6.5in" = "Envelope Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Envelope Invitation"; "media.om_italian_110x230mm" = "Envelope Italian"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389mm"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Envelope chinese #10"; "media.prc_16k_146x215mm" = "Chinese 16k"; "media.prc_1_102x165mm" = "Envelope chinese #1"; "media.prc_2_102x176mm" = "Envelope chinese #2"; "media.prc_32k_97x151mm" = "Chinese 32k"; "media.prc_3_125x176mm" = "Envelope chinese #3"; "media.prc_4_110x208mm" = "Envelope chinese #4"; "media.prc_5_110x220mm" = "Envelope chinese #5"; "media.prc_6_120x320mm" = "Envelope chinese #6"; "media.prc_7_160x230mm" = "Envelope chinese #7"; "media.prc_8_120x309mm" = "Envelope chinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Landscape"; "orientation-requested.5" = "Reverse landscape"; "orientation-requested.6" = "Reverse portrait"; "orientation-requested.7" = "None"; "output-bin" = "Output Tray"; "output-bin.auto" = "Automatic"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Face down"; "output-bin.face-up" = "Face up"; "output-bin.large-capacity" = "Large capacity"; "output-bin.left" = "Left"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Middle"; "output-bin.my-mailbox" = "My mailbox"; "output-bin.rear" = "Rear"; "output-bin.right" = "Right"; "output-bin.side" = "Side"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Print Mode"; "print-color-mode.auto" = "Automatic"; "print-color-mode.auto-monochrome" = "Auto monochrome"; "print-color-mode.bi-level" = "Text"; "print-color-mode.color" = "Color"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monochrome"; "print-color-mode.process-bi-level" = "Process Text"; "print-color-mode.process-monochrome" = "Process monochrome"; "print-content-optimize" = "Optimize For"; "print-content-optimize.auto" = "Automatic"; "print-content-optimize.graphic" = "Graphics"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text and graphics"; "print-darkness" = "Print Darkness"; "print-quality" = "Print Quality"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Best"; "print-scaling" = "Scaling"; "print-scaling.auto" = "Automatic"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Fill"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "None"; "print-speed" = "Print Speed"; "printer-resolution" = "Resolution"; "printer-state-reasons.cover-open" = "Cover open."; "printer-state-reasons.door-open" = "Door open."; "printer-state-reasons.identify-printer-requested" = "Identify printer."; "printer-state-reasons.input-tray-missing" = "Paper tray missing."; "printer-state-reasons.marker-supply-empty" = "Out of ink."; "printer-state-reasons.marker-supply-low" = "Low ink."; "printer-state-reasons.marker-waste-almost-full" = "Waste bin almost full."; "printer-state-reasons.marker-waste-full" = "Waste bin full."; "printer-state-reasons.media-empty" = "Out of paper."; "printer-state-reasons.media-jam" = "Paper jam."; "printer-state-reasons.media-low" = "Replace paper soon."; "printer-state-reasons.media-needed" = "Load paper."; "printer-state-reasons.none" = "Ready."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "See printer."; "printer-state-reasons.spool-area-full" = "Printer busy."; "printer-state-reasons.toner-empty" = "Out of toner."; "printer-state-reasons.toner-low" = "Toner low."; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "sides" = "2-Sided Printing"; "sides.one-sided" = "Off"; "sides.two-sided-long-edge" = "On (portrait)"; "sides.two-sided-short-edge" = "On (landscape)"; pappl-1.4.9/pappl/job-accessors.c000066400000000000000000000343721476704353100167010ustar00rootroot00000000000000// // Job accessor functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local globals... // static const char * const pappl_jreasons[] = { "aborted-by-system", "compression-error", "document-format-error", "document-password-error", "document-permission-error", "document-unprintable-error", "errors-detected", "job-canceled-at-device", "job-canceled-by-user", "job-completed-successfully", "job-completed-with-errors", "job-completed-with-warnings", "job-data-insufficient", "job-incoming", "job-printing", "job-queued", "job-spooling", "printer-stopped", "printer-stopped-partly", "processing-to-stop-point", "queued-in-device", "warnings-detected", "job-hold-until-specified", "job-canceled-after-timeout", "job-fetchable", "job-suspended-for-approval" }; // // 'papplJobGetAttribute()' - Get an attribute from a job. // // This function gets the named IPP attribute from a job. The returned // attribute can be examined using the `ippGetXxx` functions. // ipp_attribute_t * // O - Attribute or `NULL` if not found papplJobGetAttribute(pappl_job_t *job, // I - Job const char *name) // I - Attribute name { ipp_attribute_t *attr = NULL; // Attribute if (job) { _papplRWLockRead(job); attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO); _papplRWUnlock(job); } return (attr); } // // 'papplJobGetCopies()' - Get the number of copies in the job. // // This function returns the number of copies to produce of the job's document // data. // int // O - Number of copies papplJobGetCopies(pappl_job_t *job) // I - Job { int ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->copies; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetCopiesCompleted()' - Get the number of completed copies. // // This function returns the number of copies that have been completed. // int // O - Number of completed copies papplJobGetCopiesCompleted( pappl_job_t *job) // I - Job { int ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->copcompleted; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetData()' - Get per-job driver data. // // This function returns the driver data associated with the job. It is // normally only called from drivers to maintain state for the processing of // the job, for example to store bitmap compression information. // void * // O - Per-job driver data or `NULL` if none papplJobGetData(pappl_job_t *job) // I - Job { void *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->data; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetJobFilename()' - Get the job's filename. // // This function returns the filename for the job's document data. // const char * // O - Filename or `NULL` if none papplJobGetFilename(pappl_job_t *job) // I - Job { const char *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->filename; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetFormat()' - Get the MIME media type for the job's file. // // This function returns the MIME media type for the job's document data. // const char * // O - MIME media type or `NULL` for none papplJobGetFormat(pappl_job_t *job) // I - Job { const char *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->format; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetId()' - Get the job ID value. // // This function returns the job's unique integer identifier. // int // O - Job ID or `0` for none papplJobGetID(pappl_job_t *job) // I - Job { int ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->job_id; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetImpressions()' - Get the number of impressions (sides) in the job. // // This function returns the number of impressions in the job's document data. // An impression is one side of an output page. // int // O - Number of impressions in job papplJobGetImpressions(pappl_job_t *job)// I - Job { int ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->impressions; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetImpressionsCompleted()' - Get the number of completed impressions // (sides) in the job. // // This function returns the number of impressions that have been printed. An // impression is one side of an output page. // int // O - Number of completed impressions in job papplJobGetImpressionsCompleted( pappl_job_t *job) // I - Job { int ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->impcompleted; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetMessage()' - Get the current job message string, if any. // // This function returns the current job message string, if any. // const char * // O - Current "job-state-message" value or `NULL` for none papplJobGetMessage(pappl_job_t *job) // I - Job { const char *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->message; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetName()' - Get the job name/title. // // This function returns the name or title of the job. // const char * // O - Job name/title or `NULL` for none papplJobGetName(pappl_job_t *job) // I - Job { const char *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->name; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetPrinter()' - Get the printer for the job. // // This function returns the printer containing the job. // pappl_printer_t * // O - Printer papplJobGetPrinter(pappl_job_t *job) // I - Job { pappl_printer_t *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->printer; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetReasons()' - Get the current job state reasons. // // This function returns the current job state reasons bitfield. // pappl_jreason_t // O - IPP "job-state-reasons" bits papplJobGetReasons(pappl_job_t *job) // I - Job { pappl_jreason_t ret = PAPPL_JREASON_NONE; // Return value if (job) { _papplRWLockRead(job); ret = job->state_reasons; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetState()' - Get the current job state. // // This function returns the current job processing state, which is represented // as an enumeration: // // - `IPP_JSTATE_ABORTED`: Job has been aborted by the system due to an error. // - `IPP_JSTATE_CANCELED`: Job has been canceled by a user. // - `IPP_JSTATE_COMPLETED`: Job has finished printing. // - `IPP_JSTATE_HELD`: Job is being held for some reason, typically because // the document data is being received. // - `IPP_JSTATE_PENDING`: Job is queued and waiting to be printed. // - `IPP_JSTATE_PROCESSING`: Job is being printed. // - `IPP_JSTATE_STOPPED`: Job is paused, typically when the printer is not // ready. // ipp_jstate_t // O - IPP "job-state" value papplJobGetState(pappl_job_t *job) // I - Job { ipp_jstate_t ret = IPP_JSTATE_ABORTED; // Return value if (job) { _papplRWLockRead(job); ret = job->state; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetTimeCompleted()' - Get the job completion time, if any. // // This function returns the date and time when the job reached the completed, // canceled, or aborted states. `0` is returned if the job is not yet in one of // those states. // time_t // O - Date/time when the job completed or `0` if not completed papplJobGetTimeCompleted( pappl_job_t *job) // I - Job { time_t ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->completed; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetTimeCreated()' - Get the job creation time. // // This function returns the date and time when the job was created. // time_t // O - Date/time when the job was created papplJobGetTimeCreated(pappl_job_t *job)// I - Job { time_t ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->created; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetTimeProcessed()' - Get the job processing time. // // This function returns the date and time when the job started processing // (printing). // time_t // O - Date/time when the job started processing (printing) or `0` if not yet processed papplJobGetTimeProcessed( pappl_job_t *job) // I - Job { time_t ret = 0; // Return value if (job) { _papplRWLockRead(job); ret = job->processing; _papplRWUnlock(job); } return (ret); } // // 'papplJobGetUsername()' - Get the name of the user that submitted the job. // // This function returns the name of the user that submitted the job. // const char * // O - Username or `NULL` for unknown papplJobGetUsername(pappl_job_t *job) // I - Job { const char *ret = NULL; // Return value if (job) { _papplRWLockRead(job); ret = job->username; _papplRWUnlock(job); } return (ret); } // // 'papplJobIsCanceled()' - Return whether the job is canceled. // // This function returns `true` if the job has been canceled or aborted. // bool // O - `true` if the job is canceled or aborted, `false` otherwise papplJobIsCanceled(pappl_job_t *job) // I - Job { bool ret = false; // Return value if (job) { _papplRWLockRead(job); ret = job->is_canceled || job->state == IPP_JSTATE_CANCELED || job->state == IPP_JSTATE_ABORTED; _papplRWUnlock(job); } return (ret); } // // '_papplJobReasonString()' - Return the keyword value associated with the IPP "job-state-reasons" bit value. // const char * // O - IPP "job-state-reasons" keyword value _papplJobReasonString( pappl_jreason_t reason) // I - IPP "job-state-reasons" bit value { if (reason == PAPPL_JREASON_NONE) return ("none"); else return (_PAPPL_LOOKUP_STRING(reason, pappl_jreasons)); } // // 'papplJobSetCopiesCompleted()' - Add completed copies to the job. // // This function updates the number of completed impressions in a job. An // impression is one side of an output page. // void papplJobSetCopiesCompleted( pappl_job_t *job, // I - Job int add) // I - Number of copies to add { if (job) { _papplRWLockWrite(job); job->copcompleted += add; _papplRWUnlock(job); } } // // 'papplJobSetData()' - Set the per-job driver data pointer. // // This function sets the driver data for the specified job. It is // normally only called from drivers to maintain state for the processing of // the job, for example to store bitmap compression information. void papplJobSetData(pappl_job_t *job, // I - Job void *data) // I - Data pointer { if (job) job->data = data; } // // 'papplJobSetImpressions()' - Set the number of impressions (sides) in a job. // // This function sets the number of impressions in a job. An impression is one // side of an output page. // void papplJobSetImpressions( pappl_job_t *job, // I - Job int impressions) // I - Number of impressions/sides { if (job) job->impressions = impressions; } // // 'papplJobSetImpressionsCompleted()' - Add completed impressions (sides) to // the job. // // This function updates the number of completed impressions in a job. An // impression is one side of an output page. // void papplJobSetImpressionsCompleted( pappl_job_t *job, // I - Job int add) // I - Number of impressions/sides to add { if (job) { _papplRWLockWrite(job); job->impcompleted += add; _papplRWUnlock(job); } } // // 'papplJobSetMessage()' - Set the job message string. // // This function sets the job message string using a `printf`-style format // string. // // > Note: The maximum length of the job message string is 1023 bytes. // void papplJobSetMessage(pappl_job_t *job, // I - Job const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { if (job) { char buffer[1024]; // Message buffer va_list ap; // Pointer to arguments va_start(ap, message); vsnprintf(buffer, sizeof(buffer), message, ap); va_end(ap); _papplRWLockWrite(job); free(job->message); job->message = strdup(buffer); _papplRWUnlock(job); } } // // 'papplJobSetReasons()' - Set the job state reasons bit values. // // This function updates the job state reasons bitfield. The "remove" bits // are cleared first, then the "add" bits are set. // void papplJobSetReasons( pappl_job_t *job, // I - Job pappl_jreason_t add, // I - IPP "job-state-reasons" bit value(s) to add pappl_jreason_t remove) // I - IPP "job-state-reasons" bit value(s) to remove { if (job) { _papplRWLockWrite(job); job->state_reasons &= ~remove; job->state_reasons |= add; _papplRWUnlock(job); } } // // '_papplJobSetState()' - Set the IPP "job-state" value. // void _papplJobSetState(pappl_job_t *job, // I - Job ipp_jstate_t state) // I - New IPP "job-state" value { if (!job) return; _papplRWLockWrite(job); if (job->state != state) { job->state = state; if (state == IPP_JSTATE_PROCESSING) { job->processing = time(NULL); job->state_reasons |= PAPPL_JREASON_JOB_PRINTING; } else if (state >= IPP_JSTATE_CANCELED) { job->completed = time(NULL); job->state_reasons &= (unsigned)~PAPPL_JREASON_JOB_PRINTING; if (state == IPP_JSTATE_ABORTED) job->state_reasons |= PAPPL_JREASON_ABORTED_BY_SYSTEM; else if (state == IPP_JSTATE_CANCELED) job->state_reasons |= PAPPL_JREASON_JOB_CANCELED_BY_USER; if (job->state_reasons & PAPPL_JREASON_ERRORS_DETECTED) job->state_reasons |= PAPPL_JREASON_JOB_COMPLETED_WITH_ERRORS; if (job->state_reasons & PAPPL_JREASON_WARNINGS_DETECTED) job->state_reasons |= PAPPL_JREASON_JOB_COMPLETED_WITH_WARNINGS; } } _papplRWUnlock(job); } pappl-1.4.9/pappl/job-filter.c000066400000000000000000000700231476704353100161720ustar00rootroot00000000000000// // Job MIME filter functions for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl.h" #include "job-private.h" #include "system-private.h" #ifdef HAVE_LIBJPEG # include # include #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG # include #endif // HAVE_LIBPNG // // Local types... // #ifdef HAVE_LIBJPEG typedef struct _pappl_jpeg_err_s // JPEG error manager extension { struct jpeg_error_mgr jerr; // JPEG error manager information jmp_buf retbuf; // setjmp() return buffer char message[JMSG_LENGTH_MAX]; // Last error message } _pappl_jpeg_err_t; #endif // HAVE_LIBJPEG // // Local functions... // #ifdef HAVE_LIBJPEG static void jpeg_error_handler(j_common_ptr p) _PAPPL_NORETURN; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG static void png_error_func(png_structp pp, png_const_charp message); static void png_warning_func(png_structp pp, png_const_charp message); #endif // HAVE_LIBPNG // // 'papplJobFilterImage()' - Filter an image in memory. // // This function will print a grayscale or sRGB image using the printer's raster // driver interface, scaling and positioning the image as necessary based on // the job options, and printing as many copies as requested. // // The image data is an array of grayscale ("depth" = `1`) or sRGB // ("depth" = `3`) pixels starting at the top-left corner of the image. // // The image resolution ("ppi") is expressed in pixels per inch and is used for // some "print-scaling" modes. Pass `0` if the image has no explicit resolution // information. // bool // O - `true` on success, `false` otherwise papplJobFilterImage( pappl_job_t *job, // I - Job pappl_device_t *device, // I - Device pappl_pr_options_t *options, // I - Print options const unsigned char *pixels, // I - Pointer to the top-left corner of the image data int width, // I - Width in columns int height, // I - Height in lines int depth, // I - Bytes per pixel (`1` for grayscale or `3` for sRGB) int ppi, // I - Pixels per inch (`0` for unknown) bool smoothing) // I - `true` to smooth/interpolate the image, `false` for nearest-neighbor sampling { bool started = false;// Have we started the job? pappl_pr_driver_data_t driver_data; // Printer driver data const unsigned char *dither; // Dither line int ileft, // Imageable left margin itop, // Imageable top margin iwidth, // Imageable width iheight; // Imageable length/height unsigned char white, // White color *line = NULL, // Output line *lineptr, // Pointer in line byte, // Byte in line bit; // Current bit const unsigned char *pixbase, // Pointer to first pixel *pixline, // Pointer to start of current line *pixptr, // Pointer into image *pixend; // End of image int pixel0, // Temporary pixel value pixel1, // ... img_width, // Rotated image width img_height, // Rotated image height x, // X position xsize, // Scaled width xstart, // X start position xend, // X end position y, // Y position ysize, // Scaled height ystart, // Y start position yend; // Y end position int xdir, // X direction xerr, // X error accumulator xmod, // X modulus xstep, // X step yerr, // Y error accumulator ymod, // Y modulus ystep, // Y step ydir; // Y direction // Images contain a single page/impression... papplJobSetImpressions(job, 1); if (options->print_scaling == PAPPL_SCALING_FILL) { // Scale to fill the entire media area... ileft = 0; itop = 0; iwidth = (int)options->header.cupsWidth; iheight = (int)options->header.cupsHeight; } else { // Scale/center within the margins... ileft = options->media.left_margin * options->printer_resolution[0] / 2540; itop = options->media.top_margin * options->printer_resolution[1] / 2540; iwidth = (int)options->header.cupsWidth - (options->media.left_margin + options->media.right_margin) * options->printer_resolution[0] / 2540; iheight = (int)options->header.cupsHeight - (options->media.bottom_margin + options->media.top_margin) * options->printer_resolution[1] / 2540; } papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "ileft=%d, itop=%d, iwidth=%d, iheight=%d", ileft, itop, iwidth, iheight); if (iwidth <= 0 || iheight <= 0) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Invalid media size"); return (false); } // Figure out the scaling and rotation of the image... if (options->orientation_requested == IPP_ORIENT_NONE) { if (width > height && options->header.cupsWidth < options->header.cupsHeight) { options->orientation_requested = IPP_ORIENT_LANDSCAPE; papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Auto-orientation: landscape"); } else { options->orientation_requested = IPP_ORIENT_PORTRAIT; papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Auto-orientation: portrait"); } } if (options->print_scaling == PAPPL_SCALING_AUTO || options->print_scaling == PAPPL_SCALING_AUTO_FIT) { if (ppi <= 0) { // No resolution information, so just force scaling the image to fit/fill xsize = iwidth + 1; ysize = iheight + 1; } else if (options->orientation_requested == IPP_ORIENT_PORTRAIT || options->orientation_requested == IPP_ORIENT_REVERSE_PORTRAIT) { xsize = width * options->printer_resolution[0] / ppi; ysize = height * options->printer_resolution[1] / ppi; } else { xsize = height * options->printer_resolution[0] / ppi; ysize = width * options->printer_resolution[1] / ppi; } if (xsize > iwidth || ysize > iheight) { // Scale to fit/fill based on "print-scaling" and margins... if (options->print_scaling == PAPPL_SCALING_AUTO && options->media.bottom_margin == 0 && options->media.left_margin == 0 && options->media.right_margin == 0 && options->media.top_margin == 0) options->print_scaling = PAPPL_SCALING_FILL; else options->print_scaling = PAPPL_SCALING_FIT; } else { // Do no scaling... options->print_scaling = PAPPL_SCALING_NONE; } } else if (options->print_scaling == PAPPL_SCALING_NONE && ppi <= 0) { // Force a default PPI value of 200, which fits a typical 1080p sized // screenshot on a standard letter/A4 page. ppi = 200; } switch (options->orientation_requested) { default : case IPP_ORIENT_PORTRAIT : pixbase = pixels; img_width = width; img_height = height; xdir = (int)depth; ydir = (int)depth * (int)width; if (options->print_scaling == PAPPL_SCALING_NONE) { // No scaling xsize = img_width * options->printer_resolution[0] / ppi; ysize = img_height * options->printer_resolution[1] / ppi; } else { // Fit/fill xsize = iwidth; ysize = xsize * height / width; if ((ysize > iheight && options->print_scaling == PAPPL_SCALING_FIT) || (ysize < iheight && options->print_scaling == PAPPL_SCALING_FILL)) { ysize = iheight; xsize = ysize * width / height; } } break; case IPP_ORIENT_REVERSE_PORTRAIT : pixbase = pixels + depth * width * height - depth; img_width = width; img_height = height; xdir = -(int)depth; ydir = -(int)depth * (int)width; if (options->print_scaling == PAPPL_SCALING_NONE) { // No scaling xsize = img_width * options->printer_resolution[0] / ppi; ysize = img_height * options->printer_resolution[1] / ppi; } else { // Fit/fill xsize = iwidth; ysize = xsize * height / width; if ((ysize > iheight && options->print_scaling == PAPPL_SCALING_FIT) || (ysize < iheight && options->print_scaling == PAPPL_SCALING_FILL)) { ysize = iheight; xsize = ysize * width / height; } } break; case IPP_ORIENT_LANDSCAPE : // 90 counter-clockwise pixbase = pixels + depth * width - depth; img_width = height; img_height = width; xdir = (int)depth * (int)width; ydir = -(int)depth; if (options->print_scaling == PAPPL_SCALING_NONE) { // No scaling xsize = img_width * options->printer_resolution[0] / ppi; ysize = img_height * options->printer_resolution[1] / ppi; } else { // Fit/fill xsize = iwidth; ysize = xsize * width / height; if ((ysize > iheight && options->print_scaling == PAPPL_SCALING_FIT) || (ysize < iheight && options->print_scaling == PAPPL_SCALING_FILL)) { ysize = iheight; xsize = ysize * height / width; } } break; case IPP_ORIENT_REVERSE_LANDSCAPE : // 90 clockwise pixbase = pixels + depth * (height - 1) * width; img_width = height; img_height = width; xdir = -(int)depth * (int)width; ydir = (int)depth; if (options->print_scaling == PAPPL_SCALING_NONE) { // No scaling xsize = img_width * options->printer_resolution[0] / ppi; ysize = img_height * options->printer_resolution[1] / ppi; } else { // Fit/fill xsize = iwidth; ysize = xsize * width / height; if ((ysize > iheight && options->print_scaling == PAPPL_SCALING_FIT) || (ysize < iheight && options->print_scaling == PAPPL_SCALING_FILL)) { ysize = iheight; xsize = ysize * height / width; } } break; } // Don't rotate in the driver... options->orientation_requested = IPP_ORIENT_PORTRAIT; xstart = ileft + (iwidth - xsize) / 2; xend = xstart + xsize; ystart = itop + (iheight - ysize) / 2; yend = ystart + ysize; xmod = (int)(img_width % xsize); xstep = (int)(img_width / xsize) * xdir; ymod = (int)(img_height % ysize); ystep = (int)(img_height / ysize) * ydir; if (xend > (int)options->header.cupsWidth) xend = (int)options->header.cupsWidth; if (yend > (int)options->header.cupsHeight) yend = (int)options->header.cupsHeight; papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "xsize=%d, xstart=%d, xend=%d, xdir=%d, xmod=%d, xstep=%d", xsize, xstart, xend, xdir, xmod, xstep); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "ysize=%d, ystart=%d, yend=%d, ydir=%d, ymod=%d, ystep=%d", ysize, ystart, yend, ydir, ymod, ystep); papplPrinterGetDriverData(papplJobGetPrinter(job), &driver_data); if ((line = malloc(options->header.cupsBytesPerLine)) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for raster line."); goto abort_job; } // Start the job... if (!(driver_data.rstartjob_cb)(job, options, device)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to start raster job."); goto abort_job; } started = true; if (options->header.cupsColorSpace == CUPS_CSPACE_K || options->header.cupsColorSpace == CUPS_CSPACE_CMYK) white = 0x00; else white = 0xff; pixend = pixels + width * height * depth; // Print every copy... while (papplJobGetCopiesCompleted(job) < papplJobGetCopies(job)) { if (papplJobGetState(job) != IPP_JSTATE_PROCESSING || papplJobIsCanceled(job)) break; if (!(driver_data.rstartpage_cb)(job, options, device, 0)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to start raster page."); goto abort_job; } // Leading blank space... memset(line, white, options->header.cupsBytesPerLine); for (y = 0; y < ystart; y ++) { if (!(driver_data.rwriteline_cb)(job, options, device, (unsigned)y, line)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } } if (ystart < 0) { pixline = pixbase - (ystart * ymod / ysize) * ydir; yerr = -ymod / 2 - (ystart * ymod) % ysize; } else { pixline = pixbase; yerr = -ymod / 2; } // Now RIP the image... for (; y < yend && !job->is_canceled; y ++) { pixptr = pixline; if (xstart < 0) { pixptr -= (xstart * xmod / xsize) * xdir; x = 0; xerr = -xmod / 2 - (xstart * xmod) % xsize; } else { x = xstart; xerr = -xmod / 2; } if (options->header.cupsBitsPerPixel == 1) { // Need to dither the image to 1-bit black... dither = options->dither[y & 15]; for (lineptr = line + x / 8, bit = 128 >> (x & 7), byte = 0; x < xend; x ++) { // Dither the current pixel... if (*pixptr <= dither[x & 15]) byte |= bit; // Advance to the next pixel... pixptr += xstep; xerr += xmod; if (xerr >= (int)xsize) { // Accumulated error has overflowed, advance another pixel... xerr -= xsize; pixptr += xdir; } // and the next bit if (bit == 1) { // Current byte is "full", save it... *lineptr++ = byte; byte = 0; bit = 128; } else bit /= 2; } if (bit < 128) *lineptr = byte; } else if (options->header.cupsColorSpace == CUPS_CSPACE_K) { // Need to invert the image... for (lineptr = line + x; x < xend; x ++) { // Copy an inverted grayscale pixel... if (smoothing && yerr >= 0 && xerr >= 0) { const unsigned char *rt = pixptr + xdir, *dn = pixptr + ydir, *dnrt = pixptr + xdir + ydir; // Pointers to adjacent pixels if (rt < pixels || rt >= pixend) rt = pixptr; if (dn < pixels || dn >= pixend) dn = pixptr; if (dnrt < pixels || dnrt >= pixend) dnrt = pixptr; pixel0 = ((xsize - xerr) * *pixptr + xerr * *rt) / xsize; pixel1 = ((xsize - xerr) * *dn + xerr * *dnrt) / xsize; *lineptr++ = (unsigned char)(255 - ((ysize - yerr) * pixel0 + yerr * pixel1) / ysize); } else { *lineptr++ = ~*pixptr; } // Advance to the next pixel... pixptr += xstep; xerr += xmod; if (xerr >= (int)xsize) { // Accumulated error has overflowed, advance another pixel... xerr -= xsize; pixptr += xdir; } } } else { // Need to copy the image... int bpp = (int)options->header.cupsBitsPerPixel / 8; for (lineptr = line + x * bpp; x < xend; x ++) { // Copy a grayscale or RGB pixel... if (smoothing && yerr >= 0 && xerr >= 0) { int j; // Looping var const unsigned char *rt = pixptr + xdir, *dn = pixptr + ydir, *dnrt = pixptr + xdir + ydir; // Pointers to adjacent pixels if (rt < pixels || rt >= pixend) rt = pixptr; if (dn < pixels || dn >= pixend) dn = pixptr; if (dnrt < pixels || dnrt >= pixend) dnrt = pixptr; for (j = 0; j < bpp; j ++) { pixel0 = ((xsize - xerr) * pixptr[j] + xerr * rt[j]) / xsize; pixel1 = ((xsize - xerr) * dn[j] + xerr * dnrt[j]) / xsize; *lineptr++ = (unsigned char)(((ysize - yerr) * pixel0 + yerr * pixel1) / ysize); } } else { memcpy(lineptr, pixptr, (unsigned)bpp); lineptr += bpp; } // Advance to the next pixel... pixptr += xstep; xerr += xmod; if (xerr >= (int)xsize) { // Accumulated error has overflowed, advance another pixel... xerr -= xsize; pixptr += xdir; } } } if (!(driver_data.rwriteline_cb)(job, options, device, (unsigned)y, line)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } pixline += ystep; yerr += ymod; if (yerr >= ysize) { pixline += ydir; yerr -= ysize; } } // Trailing blank space... memset(line, white, options->header.cupsBytesPerLine); for (; y < (int)options->header.cupsHeight; y ++) { if (!(driver_data.rwriteline_cb)(job, options, device, (unsigned)y, line)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } } // End the page... if (!(driver_data.rendpage_cb)(job, options, device, 0)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to end raster page."); goto abort_job; } papplJobSetImpressionsCompleted(job, 1); papplJobSetCopiesCompleted(job, 1); } // End the job... if (!(driver_data.rendjob_cb)(job, options, device)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to end raster job."); goto abort_job; } // Free memory and return... free(line); return (true); // Abort the job... abort_job: if (started) (driver_data.rendjob_cb)(job, options, device); free(line); return (false); } // // '_papplJobFilterJPEG()' - Filter a JPEG image file. // #ifdef HAVE_LIBJPEG bool _papplJobFilterJPEG( pappl_job_t *job, // I - Job pappl_device_t *device, // I - Device void *data) // I - Filter data (unused) { const char *filename; // JPEG filename FILE *fp; // JPEG file pappl_pr_options_t *options = NULL;// Job options struct jpeg_decompress_struct dinfo; // Decompressor info int xdpi, // X pixels per inch ydpi; // Y pixels per inch _pappl_jpeg_err_t jerr; // Error handler info unsigned char *pixels = NULL; // Image pixels JSAMPROW row; // Sample row pointer bool ret = false; // Return value (void)data; // Open the JPEG file... filename = papplJobGetFilename(job); if ((fp = fopen(filename, "rb")) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to open JPEG file '%s': %s", filename, strerror(errno)); return (false); } // Read the image header... jpeg_std_error(&jerr.jerr); jerr.jerr.error_exit = jpeg_error_handler; if (setjmp(jerr.retbuf)) { // JPEG library errors are directed to this point... papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_FORMAT_ERROR, PAPPL_JREASON_NONE); papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to open JPEG file '%s': %s", filename, jerr.message); ret = false; goto finish_jpeg; } dinfo.err = (struct jpeg_error_mgr *)&jerr; jpeg_create_decompress(&dinfo); jpeg_stdio_src(&dinfo, fp); jpeg_read_header(&dinfo, TRUE); // Get job options and request the image data in the format we need... options = papplJobCreatePrintOptions(job, 1, dinfo.num_components > 1); dinfo.quantize_colors = FALSE; if (options->header.cupsNumColors == 1) { dinfo.out_color_space = JCS_GRAYSCALE; dinfo.out_color_components = 1; dinfo.output_components = 1; } else { dinfo.out_color_space = JCS_RGB; dinfo.out_color_components = 3; dinfo.output_components = 3; } jpeg_calc_output_dimensions(&dinfo); papplLogJob(job, PAPPL_LOGLEVEL_INFO, "JPEG image dimensions are %ux%ux%d", dinfo.output_width, dinfo.output_height, dinfo.output_components); if (dinfo.output_width < 1 || dinfo.output_width > (JDIMENSION)job->system->max_image_width || dinfo.output_height < 1 || dinfo.output_height > (JDIMENSION)job->system->max_image_height || ((size_t)dinfo.output_width * (size_t)dinfo.output_height * (size_t)dinfo.output_components) > job->system->max_image_size) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "JPEG image is too large to print."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_jpeg; } if ((pixels = (unsigned char *)malloc((size_t)dinfo.output_width * (size_t)dinfo.output_height * (size_t)dinfo.output_components)) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for %ux%ux%d JPEG image.", dinfo.output_width, dinfo.output_height, dinfo.output_components); papplJobSetReasons(job, PAPPL_JREASON_ERRORS_DETECTED, PAPPL_JREASON_NONE); goto finish_jpeg; } jpeg_start_decompress(&dinfo); while (dinfo.output_scanline < dinfo.output_height) { row = (JSAMPROW)(pixels + (size_t)dinfo.output_scanline * (size_t)dinfo.output_width * (size_t)dinfo.output_components); jpeg_read_scanlines(&dinfo, &row, 1); } switch (dinfo.density_unit) { default : case 0 : // Unknown units xdpi = ydpi = 0; break; case 1 : // Dots-per-inch xdpi = dinfo.X_density; ydpi = dinfo.Y_density; break; case 2 : // Dots-per-centimeter xdpi = dinfo.X_density * 254 / 100; ydpi = dinfo.Y_density * 254 / 100; break; } papplLogJob(job, PAPPL_LOGLEVEL_INFO, "JPEG image resolution is %dx%ddpi", xdpi, ydpi); if (xdpi != ydpi) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "JPEG image has non-square aspect ratio - not currently supported."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_jpeg; } ret = papplJobFilterImage(job, device, options, pixels, (int)dinfo.output_width, (int)dinfo.output_height, dinfo.output_components, xdpi, true); jpeg_finish_decompress(&dinfo); finish_jpeg: papplJobDeletePrintOptions(options); free(pixels); jpeg_destroy_decompress(&dinfo); fclose(fp); return (ret); } #endif // HAVE_LIBJPEG // // 'process_png()' - Process a PNG image file. // #ifdef HAVE_LIBPNG bool // O - `true` on success and `false` otherwise _papplJobFilterPNG( pappl_job_t *job, // I - Job pappl_device_t *device, // I - Device void *data) // I - Filter data (unused) { const char *filename; // Job filename FILE *fp; // PNG file pappl_pr_options_t *options = NULL;// Job options png_structp pp = NULL; // PNG read pointer png_infop info = NULL; // PNG info pointers png_bytep *rows = NULL; // PNG row pointers png_color_16 bg; // Background color int i, // Looping var color_type, // PNG color mode width, // Width in columns height, // Height in lines depth, // Bytes per pixel xdpi, // X resolution ydpi; // Y resolution unsigned char *pixels = NULL; // Image pixels bool ret = false; // Return value // Open the PNG file... (void)data; filename = papplJobGetFilename(job); if ((fp = fopen(filename, "rb")) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to open PNG file '%s': %s", filename, strerror(errno)); return (false); } // Setup PNG data structures... if ((pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)job, png_error_func, png_warning_func)) == NULL) { papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_FORMAT_ERROR, PAPPL_JREASON_NONE); papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for PNG file '%s': %s", job->filename, strerror(errno)); goto finish_png; } if ((info = png_create_info_struct(pp)) == NULL) { papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_FORMAT_ERROR, PAPPL_JREASON_NONE); papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for PNG file '%s': %s", job->filename, strerror(errno)); goto finish_png; } if (setjmp(png_jmpbuf(pp))) { // If we get here, PNG loading failed and any errors/warnings were logged // via the corresponding callback functions... papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_FORMAT_ERROR, PAPPL_JREASON_NONE); goto finish_png; } // Start reading... png_init_io(pp, fp); # if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && defined(PNG_SET_OPTION_SUPPORTED) // Don't throw errors with "invalid" sRGB profiles produced by Adobe apps. png_set_option(pp, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON); # endif // PNG_SKIP_sRGB_CHECK_PROFILE && PNG_SET_OPTION_SUPPORTED // Get the image dimensions and depth... png_read_info(pp, info); width = (int)png_get_image_width(pp, info); height = (int)png_get_image_height(pp, info); color_type = png_get_color_type(pp, info); if (color_type & PNG_COLOR_MASK_COLOR) depth = 3; else depth = 1; papplLogJob(job, PAPPL_LOGLEVEL_INFO, "PNG image dimensions are %dx%dx%d", width, height, depth); if (width < 1 || width > job->system->max_image_width || height < 1 || height > job->system->max_image_height || (size_t)(width * height * depth) > job->system->max_image_size) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "PNG image is too large to print."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_png; } xdpi = (int)png_get_x_pixels_per_inch(pp, info); ydpi = (int)png_get_y_pixels_per_inch(pp, info); papplLogJob(job, PAPPL_LOGLEVEL_INFO, "PNG image resolution is %dx%ddpi", xdpi, ydpi); if (xdpi != ydpi) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "PNG image has non-square aspect ratio - not currently supported."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_png; } // Set decoding options... if (png_get_valid(pp, info, PNG_INFO_tRNS)) { // Map transparency to alpha png_set_tRNS_to_alpha(pp); color_type |= PNG_COLOR_MASK_ALPHA; } #ifdef PNG_TRANSFORM_SCALE_16 if (png_get_bit_depth(pp, info) > 8) { // Scale 16-bit values to 8-bit gamma-corrected ones png_set_scale_16(pp); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Scaling 16-bit PNG data to 8-bits."); } #else if (png_get_bit_depth(pp, info) > 8) { // Strip the bottom bits of 16-bit values png_set_strip_16(pp); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Stripping 16-bit PNG data to 8-bits."); } #endif // PNG_TRANSFORM_SCALE_16 if (png_get_bit_depth(pp, info) < 8) { // Expand 1, 2, and 4-bit values to 8 bits if (depth == 1) png_set_expand_gray_1_2_4_to_8(pp); else png_set_packing(pp); } if (color_type & PNG_COLOR_MASK_PALETTE) { // Convert indexed images to RGB... png_set_palette_to_rgb(pp); } // Remove alpha by compositing over white... bg.red = bg.green = bg.blue = 65535; png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); // Allocate memory for the image... if ((pixels = (unsigned char *)calloc(1, (size_t)(width * height * depth))) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for PNG image: %s", strerror(errno)); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_png; } if ((rows = (png_bytep *)calloc((size_t)height, sizeof(png_bytep))) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for PNG image: %s", strerror(errno)); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); goto finish_png; } for (i = 0; i < height; i ++) rows[i] = pixels + i * width * depth; // Read the image... for (i = png_set_interlace_handling(pp); i > 0; i --) png_read_rows(pp, rows, NULL, (png_uint_32)height); // Prepare options... options = papplJobCreatePrintOptions(job, 1, depth == 3); // Print the image... ret = papplJobFilterImage(job, device, options, pixels, width, height, depth, (int)png_get_x_pixels_per_inch(pp, info), false); // Finish up... finish_png: if (pp && info) { png_read_end(pp, info); png_destroy_read_struct(&pp, &info, NULL); pp = NULL; info = NULL; } fclose(fp); fp = NULL; papplJobDeletePrintOptions(options); options = NULL; free(pixels); pixels = NULL; free(rows); rows = NULL; return (ret); } #endif // HAVE_LIBPNG #ifdef HAVE_LIBJPEG // // 'jpeg_error_handler()' - Handle JPEG errors by not exiting. // static void jpeg_error_handler(j_common_ptr p) // I - JPEG data { _pappl_jpeg_err_t *jerr = (_pappl_jpeg_err_t *)p->err; // JPEG error handler // Save the error message in the string buffer... (jerr->jerr.format_message)(p, jerr->message); // Return to the point we called setjmp()... longjmp(jerr->retbuf, 1); } #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG // // 'png_error_func()' - PNG error message function. // static void png_error_func( png_structp pp, // I - PNG pointer png_const_charp message) // I - Error message { pappl_job_t *job = (pappl_job_t *)png_get_error_ptr(pp); // Job papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "PNG: %s", message); } // // 'png_warning_func()' - PNG warning message function. // static void png_warning_func( png_structp pp, // I - PNG pointer png_const_charp message) // I - Error message { pappl_job_t *job = (pappl_job_t *)png_get_error_ptr(pp); // Job papplLogJob(job, PAPPL_LOGLEVEL_WARN, "PNG: %s", message); } #endif // HAVE_LIBPNG pappl-1.4.9/pappl/job-ipp.c000066400000000000000000000624021476704353100154770ustar00rootroot00000000000000// // Job IPP processing for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local type... // typedef struct _pappl_attr_s // Input attribute structure { const char *name; // Attribute name ipp_tag_t value_tag; // Value tag int max_count; // Max number of values } _pappl_attr_t; // // Local functions... // static void ipp_cancel_job(pappl_client_t *client); static void ipp_close_job(pappl_client_t *client); static void ipp_get_job_attributes(pappl_client_t *client); static void ipp_hold_job(pappl_client_t *client); static void ipp_release_job(pappl_client_t *client); static void ipp_send_document(pappl_client_t *client); // // '_papplJobCopyAttributesNoLock()' - Copy job attributes to the response. // void _papplJobCopyAttributesNoLock( pappl_job_t *job, // I - Job pappl_client_t *client, // I - Client cups_array_t *ra) // I - requested-attributes { _papplCopyAttributes(client->response, job->attrs, ra, IPP_TAG_JOB, false); if (!ra || cupsArrayFind(ra, "date-time-at-creation")) ippAddDate(client->response, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(job->created)); if (!ra || cupsArrayFind(ra, "date-time-at-completed")) { if (job->completed) ippAddDate(client->response, IPP_TAG_JOB, "date-time-at-completed", ippTimeToDate(job->completed)); else ippAddOutOfBand(client->response, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-completed"); } if (!ra || cupsArrayFind(ra, "date-time-at-processing")) { if (job->processing) ippAddDate(client->response, IPP_TAG_JOB, "date-time-at-processing", ippTimeToDate(job->processing)); else ippAddOutOfBand(client->response, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-processing"); } if (!ra || cupsArrayFind(ra, "job-impressions")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions", job->impressions); if (!ra || cupsArrayFind(ra, "job-impressions-completed")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", job->impcompleted); if (!ra || cupsArrayFind(ra, "job-printer-up-time")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-printer-up-time", (int)(time(NULL) - client->printer->start_time)); _papplJobCopyStateNoLock(job, IPP_TAG_JOB, client->response, ra); if (!ra || cupsArrayFind(ra, "time-at-creation")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)(job->created - client->printer->start_time)); if (!ra || cupsArrayFind(ra, "time-at-completed")) ippAddInteger(client->response, IPP_TAG_JOB, job->completed ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE, "time-at-completed", (int)(job->completed - client->printer->start_time)); if (!ra || cupsArrayFind(ra, "time-at-processing")) ippAddInteger(client->response, IPP_TAG_JOB, job->processing ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE, "time-at-processing", (int)(job->processing - client->printer->start_time)); } // // '_papplJobCopyDocumentData()' - Finish receiving a document file in an IPP // request and start processing. // void _papplJobCopyDocumentData( pappl_client_t *client, // I - Client pappl_job_t *job) // I - Job { char filename[1024], // Filename buffer buffer[4096]; // Copy buffer ssize_t bytes, // Bytes read total = 0; // Total bytes copied cups_array_t *ra; // Attributes to send in response // If we have a PWG or Apple raster file, process it directly or return // server-error-busy... if (!strcmp(job->format, "image/pwg-raster") || !strcmp(job->format, "image/urf")) { _papplRWLockRead(job->printer); if (job->printer->processing_job) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BUSY, "Currently printing another job."); _papplRWUnlock(job->printer); goto abort_job; } else if (job->printer->hold_new_jobs) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, "Currently holding new jobs."); _papplRWUnlock(job->printer); goto abort_job; } _papplRWLockWrite(job); job->state = IPP_JSTATE_PENDING; _papplRWUnlock(job); _papplRWUnlock(job->printer); _papplJobProcessRaster(job, client); goto complete_job; } // Create a file for the request data... if ((job->fd = papplJobOpenFile(job, filename, sizeof(filename), client->system->directory, NULL, "w")) < 0) { papplClientRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); goto abort_job; } papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Created job file \"%s\", format \"%s\".", filename, job->format); while ((bytes = httpRead(client->http, buffer, sizeof(buffer))) > 0) { if (write(job->fd, buffer, (size_t)bytes) < bytes) { int error = errno; // Write error close(job->fd); job->fd = -1; unlink(filename); papplClientRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); goto abort_job; } total += (size_t)bytes; } if (bytes < 0) { // Got an error while reading the print data, so abort this job. close(job->fd); job->fd = -1; unlink(filename); papplClientRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to read print file."); goto abort_job; } if (close(job->fd)) { int error = errno; // Write error job->fd = -1; unlink(filename); papplClientRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); goto abort_job; } papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Received %lu bytes of document data.", (unsigned long)total); job->fd = -1; // Submit the job for processing... _papplJobSubmitFile(job, filename); complete_job: // Return the job info... papplClientRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-message"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); _papplRWLockRead(job); _papplJobCopyAttributesNoLock(job, client, ra); _papplRWUnlock(job); cupsArrayDelete(ra); return; // If we get here we had to abort the job... abort_job: papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Aborting job."); _papplClientFlushDocumentData(client); _papplRWLockWrite(client->printer); _papplRWLockWrite(job); job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); cupsArrayRemove(client->printer->active_jobs, job); cupsArrayAdd(client->printer->completed_jobs, job); _papplRWLockWrite(client->system); if (!client->system->clean_time) client->system->clean_time = time(NULL) + 60; _papplRWUnlock(client->system); ra = cupsArrayNew((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); _papplJobCopyAttributesNoLock(job, client, ra); cupsArrayDelete(ra); _papplRWUnlock(job); _papplRWUnlock(client->printer); } // // '_papplJobCopyStateNoLock()' - Copy the job-state-xxx attributes. // void _papplJobCopyStateNoLock( pappl_job_t *job, // I - Job ipp_tag_t group_tag, // I - Group tag ipp_t *ipp, // I - IPP message cups_array_t *ra) // I - Requested attributes { if (!ra || cupsArrayFind(ra, "job-state")) ippAddInteger(ipp, group_tag, IPP_TAG_ENUM, "job-state", (int)job->state); if (!ra || cupsArrayFind(ra, "job-state-message")) { if (job->message) { ippAddString(ipp, group_tag, IPP_TAG_TEXT, "job-state-message", NULL, job->message); } else { switch (job->state) { case IPP_JSTATE_PENDING : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job pending."); break; case IPP_JSTATE_HELD : if (job->fd >= 0) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job incoming."); else if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_ZERO)) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job held."); else ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job created."); break; case IPP_JSTATE_PROCESSING : if (job->is_canceled) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job canceling."); else ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job printing."); break; case IPP_JSTATE_STOPPED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job stopped."); break; case IPP_JSTATE_CANCELED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job canceled."); break; case IPP_JSTATE_ABORTED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job aborted."); break; case IPP_JSTATE_COMPLETED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job completed."); break; } } } if (!ra || cupsArrayFind(ra, "job-state-reasons")) { if (job->state_reasons) { size_t num_values = 0; // Number of string values const char *svalues[32]; // String values pappl_jreason_t bit; // Current reason bit for (bit = PAPPL_JREASON_ABORTED_BY_SYSTEM; bit <= PAPPL_JREASON_WARNINGS_DETECTED; bit *= 2) { if (bit & job->state_reasons) svalues[num_values ++] = _papplJobReasonString(bit); } ippAddStrings(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", IPP_NUM_CAST num_values, NULL, svalues); } else { switch (job->state) { case IPP_JSTATE_PENDING : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "none"); break; case IPP_JSTATE_HELD : if (job->fd >= 0) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-incoming"); else ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-data-insufficient"); break; case IPP_JSTATE_PROCESSING : if (job->is_canceled) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "processing-to-stop-point"); else ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-printing"); break; case IPP_JSTATE_STOPPED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-stopped"); break; case IPP_JSTATE_CANCELED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-canceled-by-user"); break; case IPP_JSTATE_ABORTED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "aborted-by-system"); break; case IPP_JSTATE_COMPLETED : ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-completed-successfully"); break; } } } } // // '_papplJobProcessIPP()' - Process an IPP Job request. // void _papplJobProcessIPP( pappl_client_t *client) // I - Client { switch (ippGetOperation(client->request)) { case IPP_OP_CANCEL_JOB : ipp_cancel_job(client); break; case IPP_OP_CLOSE_JOB : ipp_close_job(client); break; case IPP_OP_GET_JOB_ATTRIBUTES : ipp_get_job_attributes(client); break; case IPP_OP_HOLD_JOB : ipp_hold_job(client); break; case IPP_OP_RELEASE_JOB : ipp_release_job(client); break; case IPP_OP_SEND_DOCUMENT : ipp_send_document(client); break; default : if (client->system->op_cb && (client->system->op_cb)(client, client->system->op_cbdata)) break; papplClientRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } } // // '_papplJobValidateDocumentAttributes()' - Determine whether the document // attributes are valid. // // When one or more document attributes are invalid, this function adds a // suitable response and attributes to the unsupported group. // bool // O - `true` if valid, `false` if not _papplJobValidateDocumentAttributes( pappl_client_t *client) // I - Client { bool valid = true; // Valid attributes? ipp_op_t op = ippGetOperation(client->request); // IPP operation const char *op_name = ippOpString(op); // IPP operation name ipp_attribute_t *attr, // Current attribute *supported; // xxx-supported attribute const char *compression = NULL, // compression value *format = NULL; // document-format value // Check operation attributes... if ((attr = ippFindAttribute(client->request, "compression", IPP_TAG_ZERO)) != NULL) { // If compression is specified, only accept a supported value in a Print-Job // or Send-Document request... compression = ippGetString(attr, 0, NULL); supported = ippFindAttribute(client->printer->attrs, "compression-supported", IPP_TAG_KEYWORD); if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetGroupTag(attr) != IPP_TAG_OPERATION || (op != IPP_OP_PRINT_JOB && op != IPP_OP_SEND_DOCUMENT && op != IPP_OP_VALIDATE_JOB) || !ippContainsString(supported, compression)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s \"compression\"='%s'", op_name, compression); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "compression-supplied", NULL, compression); if (strcmp(compression, "none")) { papplLogClient(client, PAPPL_LOGLEVEL_INFO, "Receiving job file with '%s' compression.", compression); httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, compression); } } } // Is it a format we support? if ((attr = ippFindAttribute(client->request, "document-format", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_MIMETYPE || ippGetGroupTag(attr) != IPP_TAG_OPERATION) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { format = ippGetString(attr, 0, NULL); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s \"document-format\"='%s'", op_name, format); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, format); } } else { format = ippGetString(ippFindAttribute(client->printer->attrs, "document-format-default", IPP_TAG_MIMETYPE), 0, NULL); if (!format) format = "application/octet-stream"; /* Should never happen */ attr = ippAddString(client->request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format); } if (format && !strcmp(format, "application/octet-stream") && (ippGetOperation(client->request) == IPP_OP_PRINT_JOB || ippGetOperation(client->request) == IPP_OP_SEND_DOCUMENT)) { // Auto-type the file using the first N bytes of the file... unsigned char header[8192]; // First 8k bytes of file ssize_t headersize; // Number of bytes read memset(header, 0, sizeof(header)); headersize = httpPeek(client->http, (char *)header, sizeof(header)); _papplRWLockRead(client->system); if (!memcmp(header, "%PDF", 4)) format = "application/pdf"; else if (!memcmp(header, "%!", 2)) format = "application/postscript"; else if (!memcmp(header, "\377\330\377", 3) && header[3] >= 0xe0 && header[3] <= 0xef) format = "image/jpeg"; else if (!memcmp(header, "\211PNG", 4)) format = "image/png"; else if (!memcmp(header, "RaS2PwgR", 8)) format = "image/pwg-raster"; else if (!memcmp(header, "UNIRAST", 8)) format = "image/urf"; else if (client->system->mime_cb) format = (client->system->mime_cb)(header, (size_t)headersize, client->system->mime_cbdata); else format = NULL; _papplRWUnlock(client->system); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Auto-type header: %02X%02X%02X%02X%02X%02X%02X%02X... format: %s\n", header[0], header[1], header[2], header[3], header[4], header[5], header[6], header[7], format ? format : "unknown"); if (format) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s Auto-typed \"document-format\"='%s'.", op_name, format); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, format); } } _papplRWLockRead(client->printer); if (op != IPP_OP_CREATE_JOB && (supported = ippFindAttribute(client->printer->attrs, "document-format-supported", IPP_TAG_MIMETYPE)) != NULL && !ippContainsString(supported, format)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } _papplRWUnlock(client->printer); return (valid); } // // 'ipp_cancel_job()' - Cancel a job. // static void ipp_cancel_job(pappl_client_t *client) // I - Client { pappl_job_t *job; // Job information // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Get the job... if (ippGetOperation(client->request) == IPP_OP_CANCEL_CURRENT_JOB) job = client->printer->processing_job; else job = client->job; if (!job) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); return; } // See if the job is already completed, canceled, or aborted; if so, // we can't cancel... switch (job->state) { case IPP_JSTATE_CANCELED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already canceled - can\'t cancel.", job->job_id); break; case IPP_JSTATE_ABORTED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already aborted - can\'t cancel.", job->job_id); break; case IPP_JSTATE_COMPLETED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already completed - can\'t cancel.", job->job_id); break; default : // Cancel the job... papplJobCancel(job); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); break; } } // // 'ipp_close_job()' - Close an open job. // static void ipp_close_job(pappl_client_t *client) // I - Client { pappl_job_t *job = client->job; // Job information // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Get the job... if (!job) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); return; } // See if the job is already completed, canceled, or aborted; if so, // we can't cancel... switch (job->state) { case IPP_JSTATE_CANCELED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is canceled - can\'t close.", job->job_id); break; case IPP_JSTATE_ABORTED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is aborted - can\'t close.", job->job_id); break; case IPP_JSTATE_COMPLETED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is completed - can\'t close.", job->job_id); break; case IPP_JSTATE_PROCESSING : case IPP_JSTATE_STOPPED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already closed.", job->job_id); break; default : papplClientRespondIPP(client, IPP_STATUS_OK, NULL); break; } } // // 'ipp_get_job_attributes()' - Get the attributes for a job object. // static void ipp_get_job_attributes( pappl_client_t *client) // I - Client { pappl_job_t *job = client->job; // Job information cups_array_t *ra; // requested-attributes // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; if (!job) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job not found."); return; } papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(job); ra = ippCreateRequestedArray(client->request); _papplJobCopyAttributesNoLock(job, client, ra); cupsArrayDelete(ra); _papplRWUnlock(job); } // // 'ipp_hold_job()' - Hold a job. // static void ipp_hold_job(pappl_client_t *client) // I - Client { pappl_job_t *job = client->job; // Job information // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Get the job... if (job) { const char *hold_until; // "job-hold-until" keyword time_t hold_until_time; // "job-hold-until-time" value hold_until = ippGetString(ippFindAttribute(client->request, "job-hold-until", IPP_TAG_KEYWORD), 0, NULL); hold_until_time = ippDateToTime(ippGetDate(ippFindAttribute(client->request, "job-hold-until-time", IPP_TAG_DATE), 0)); if (!hold_until && !hold_until_time) hold_until = "indefinite"; // "job-hold-until" = 'no-hold' means release the job... if (hold_until && !strcmp(hold_until, "no-hold")) { if (papplJobRelease(job, client->username)) papplClientRespondIPP(client, IPP_STATUS_OK, "Job released."); else papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job already released."); } else { // Otherwise hold with the specified values... if (papplJobHold(job, client->username, hold_until, hold_until_time)) papplClientRespondIPP(client, IPP_STATUS_OK, "Job held."); else papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job not pending/held."); } } else { // Not found... papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); } } // // 'ipp_release_job()' - Release a job. // static void ipp_release_job(pappl_client_t *client) // I - Client { pappl_job_t *job = client->job; // Job information // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Get the job... if (job) { if (papplJobRelease(job, client->username)) papplClientRespondIPP(client, IPP_STATUS_OK, "Job released."); else papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job not held."); } else { // Not found... papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); } } // // 'ipp_send_document()' - Add an attached document to a job object created with // Create-Job. // static void ipp_send_document( pappl_client_t *client) // I - Client { pappl_job_t *job = client->job; // Job information ipp_attribute_t *attr; // Current attribute bool have_data; // Do we have document data? // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Get the job... if (!job) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); _papplClientFlushDocumentData(client); return; } // See if we already have a document for this job or the job has already // in a non-pending state... have_data = _papplClientHaveDocumentData(client); if (have_data) { if (job->filename || job->fd >= 0 || job->streaming) { papplClientRespondIPP(client, IPP_STATUS_ERROR_MULTIPLE_JOBS_NOT_SUPPORTED, "Multiple document jobs are not supported."); _papplClientFlushDocumentData(client); return; } else if (job->state > IPP_JSTATE_HELD) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job is not in a pending state."); _papplClientFlushDocumentData(client); return; } } // Make sure we have the "last-document" operation attribute... if ((attr = ippFindAttribute(client->request, "last-document", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required \"last-document\" attribute."); _papplClientFlushDocumentData(client); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "The \"last-document\" attribute is not in the operation group."); _papplClientFlushDocumentData(client); return; } else if (ippGetValueTag(attr) != IPP_TAG_BOOLEAN || ippGetCount(attr) != 1) { papplClientRespondIPPUnsupported(client, attr); _papplClientFlushDocumentData(client); return; } // Validate document attributes... if (have_data && !_papplJobValidateDocumentAttributes(client)) { _papplClientFlushDocumentData(client); return; } if (!have_data && !job->filename) job->state = IPP_JSTATE_ABORTED; // Then finish getting the document data and process things... _papplRWLockWrite(client->printer); _papplCopyAttributes(job->attrs, client->request, NULL, IPP_TAG_JOB, false); if ((attr = ippFindAttribute(job->attrs, "document-format-detected", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else if ((attr = ippFindAttribute(job->attrs, "document-format-supplied", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else job->format = client->printer->driver_data.format; _papplRWUnlock(client->printer); if (have_data) _papplJobCopyDocumentData(client, job); } pappl-1.4.9/pappl/job-private.h000066400000000000000000000075301476704353100163670ustar00rootroot00000000000000// // Private job header file for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_JOB_PRIVATE_H_ # define _PAPPL_JOB_PRIVATE_H_ # include "base-private.h" # include "job.h" # include "log.h" // // Types and structures... // struct _pappl_job_s // Job data { pthread_rwlock_t rwlock; // Reader/writer lock pappl_system_t *system; // Containing system pappl_printer_t *printer; // Containing printer int job_id; // "job-id" value const char *name, // "job-name" value *username, // "job-originating-user-name" value *format; // "document-format" value ipp_jstate_t state; // "job-state" value pappl_jreason_t state_reasons; // "job-state-reasons" values bool is_canceled; // Has this job been canceled? char *message; // "job-state-message" value pappl_loglevel_t msglevel; // "job-state-message" log level time_t created, // "[date-]time-at-creation" value processing, // "[date-]time-at-processing" value completed, // "[date-]time-at-completed" value hold_until, // "job-hold-until[-time]" value retain_until; // "job-retain-until[-interval,-time]" value int copies, // "copies" value copcompleted, // "copies-completed" value impressions, // "job-impressions" value impcompleted; // "job-impressions-completed" value ipp_t *attrs; // Static attributes char *filename; // Print file name int fd; // Print file descriptor bool streaming; // Streaming job? void *data; // Per-job driver data }; // // Functions... // extern int _papplJobCompareActive(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE; extern int _papplJobCompareAll(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE; extern int _papplJobCompareCompleted(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE; extern void _papplJobCopyAttributesNoLock(pappl_job_t *job, pappl_client_t *client, cups_array_t *ra) _PAPPL_PRIVATE; extern void _papplJobCopyDocumentData(pappl_client_t *client, pappl_job_t *job) _PAPPL_PRIVATE; extern void _papplJobCopyStateNoLock(pappl_job_t *job, ipp_tag_t group_tag, ipp_t *ipp, cups_array_t *ra) _PAPPL_PRIVATE; extern pappl_job_t *_papplJobCreate(pappl_printer_t *printer, int job_id, const char *username, const char *format, const char *job_name, ipp_t *attrs) _PAPPL_PRIVATE; extern void _papplJobDelete(pappl_job_t *job) _PAPPL_PRIVATE; # ifdef HAVE_LIBJPEG extern bool _papplJobFilterJPEG(pappl_job_t *job, pappl_device_t *device, void *data); # endif // HAVE_LIBJPEG # ifdef HAVE_LIBPNG extern bool _papplJobFilterPNG(pappl_job_t *job, pappl_device_t *device, void *data); # endif // HAVE_LIBPNG extern bool _papplJobHoldNoLock(pappl_job_t *job, const char *username, const char *until, time_t until_time) _PAPPL_PRIVATE; extern void *_papplJobProcess(pappl_job_t *job) _PAPPL_PRIVATE; extern void _papplJobProcessIPP(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplJobProcessRaster(pappl_job_t *job, pappl_client_t *client) _PAPPL_PRIVATE; extern const char *_papplJobReasonString(pappl_jreason_t reason) _PAPPL_PRIVATE; extern void _papplJobReleaseNoLock(pappl_job_t *job, const char *username) _PAPPL_PRIVATE; extern void _papplJobRemoveFile(pappl_job_t *job) _PAPPL_PRIVATE; extern bool _papplJobRetainNoLock(pappl_job_t *job, const char *username, const char *until, int until_interval, time_t until_time) _PAPPL_PRIVATE; extern void _papplJobSetRetain(pappl_job_t *job) _PAPPL_PRIVATE; extern void _papplJobSetState(pappl_job_t *job, ipp_jstate_t state) _PAPPL_PRIVATE; extern void _papplJobSubmitFile(pappl_job_t *job, const char *filename) _PAPPL_PRIVATE; extern bool _papplJobValidateDocumentAttributes(pappl_client_t *client) _PAPPL_PRIVATE; #endif // !_PAPPL_JOB_PRIVATE_H_ pappl-1.4.9/pappl/job-process.c000066400000000000000000001156231476704353100163710ustar00rootroot00000000000000// // Job processing (printing) functions for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static const char *cups_cspace_string(cups_cspace_t cspace); static bool filter_raw(pappl_job_t *job, pappl_device_t *device); static void finish_job(pappl_job_t *job); static bool start_job(pappl_job_t *job); // // 'papplJobCreatePrintOptions()' - Create the printer options for a job. // // This function allocates a printer options structure and computes the print // options for a job based upon the Job Template attributes submitted in the // print request and the default values set in the printer driver data. // // The "num_pages" and "color" arguments specify the number of pages and whether // the document contains non-grayscale colors - this information typically comes // from parsing the job file. // pappl_pr_options_t * // O - Job options data or `NULL` on error papplJobCreatePrintOptions( pappl_job_t *job, // I - Job unsigned num_pages, // I - Number of pages (`0` for unknown) bool color) // I - Is the document in color? { pappl_pr_options_t *options; // New options data cups_len_t i, // Looping var count; // Number of values ipp_attribute_t *attr; // Attribute pappl_printer_t *printer = job->printer; // Printer const char *raster_type; // Raster type for output #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 static const char * const media_positions[] = { // "media-source" to MediaPosition mapping "auto", "main", "alternate", "large-capacity", "manual", "envelope", "disc", "photo", "hagaki", "main-roll", "alternate-roll", "top", "middle", "bottom", "side", "left", "right", "center", "rear", "by-pass-tray", "tray-1", "tray-2", "tray-3", "tray-4", "tray-5", "tray-6", "tray-7", "tray-8", "tray-9", "tray-10", "tray-11", "tray-12", "tray-13", "tray-14", "tray-15", "tray-16", "tray-17", "tray-18", "tray-19", "tray-20", "roll-1", "roll-2", "roll-3", "roll-4", "roll-5", "roll-6", "roll-7", "roll-8", "roll-9", "roll-10" }; static const cups_orient_t orientations[] = { // "orientation-requested" to Orientation mapping CUPS_ORIENT_0, CUPS_ORIENT_90, CUPS_ORIENT_270, CUPS_ORIENT_180, CUPS_ORIENT_0 }; #endif // CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 static const char * const sheet_back[] = { // "pwg-raster-document-sheet-back values "normal", "flipped", "rotated", "manual-tumble" }; papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Getting options for num_pages=%u, color=%s", num_pages, color ? "true" : "false"); // Clear all options... if ((options = calloc(1, sizeof(pappl_pr_options_t))) == NULL) return (NULL); options->media = printer->driver_data.media_default; _papplRWLockRead(printer); // copies options->copies = job->copies; // finishings options->finishings = PAPPL_FINISHINGS_NONE; if ((attr = ippFindAttribute(job->attrs, "finishings", IPP_TAG_ENUM)) != NULL) { if (ippContainsInteger(attr, IPP_FINISHINGS_PUNCH)) options->finishings |= PAPPL_FINISHINGS_PUNCH; if (ippContainsInteger(attr, IPP_FINISHINGS_STAPLE)) options->finishings |= PAPPL_FINISHINGS_STAPLE; if (ippContainsInteger(attr, IPP_FINISHINGS_TRIM)) options->finishings |= PAPPL_FINISHINGS_TRIM; } else if ((attr = ippFindAttribute(job->attrs, "finishings-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) { for (i = 0, count = ippGetCount(attr); i < count; i ++) { ipp_t *col = ippGetCollection(attr, i); // "finishings-col" collection value const char *template = ippGetString(ippFindAttribute(col, "finishing-template", IPP_TAG_ZERO), 0, NULL); // "finishing-template" value if (template && !strcmp(template, "punch")) options->finishings |= PAPPL_FINISHINGS_PUNCH; else if (template && !strcmp(template, "staple")) options->finishings |= PAPPL_FINISHINGS_STAPLE; else if (template && !strcmp(template, "trim")) options->finishings |= PAPPL_FINISHINGS_TRIM; } } // media-xxx options->media = printer->driver_data.media_default; if ((attr = ippFindAttribute(job->attrs, "media-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) { options->media.source[0] = '\0'; _papplMediaColImport(ippGetCollection(attr, 0), &options->media); } else if ((attr = ippFindAttribute(job->attrs, "media", IPP_TAG_ZERO)) != NULL) { const char *pwg_name = ippGetString(attr, 0, NULL); pwg_media_t *pwg_media = pwgMediaForPWG(pwg_name); if (pwg_name && pwg_media) { papplCopyString(options->media.size_name, pwg_name, sizeof(options->media.size_name)); options->media.size_width = pwg_media->width; options->media.size_length = pwg_media->length; options->media.source[0] = '\0'; } } if (!options->media.source[0]) { for (i = 0; i < (cups_len_t)printer->driver_data.num_source; i ++) { if (!strcmp(options->media.size_name, printer->driver_data.media_ready[i].size_name)) { papplCopyString(options->media.source, printer->driver_data.source[i], sizeof(options->media.source)); break; } } if (!options->media.source[0]) papplCopyString(options->media.source, printer->driver_data.media_default.source, sizeof(options->media.source)); } // orientation-requested if ((attr = ippFindAttribute(job->attrs, "orientation-requested", IPP_TAG_ENUM)) != NULL) options->orientation_requested = (ipp_orient_t)ippGetInteger(attr, 0); else if (printer->driver_data.orient_default) options->orientation_requested = printer->driver_data.orient_default; else options->orientation_requested = IPP_ORIENT_NONE; // output-bin if (printer->driver_data.num_bin > 0) { const char *value; // Attribute string value if ((value = ippGetString(ippFindAttribute(job->attrs, "output-bin", IPP_TAG_ZERO), 0, NULL)) != NULL) papplCopyString(options->output_bin, value, sizeof(options->output_bin)); else papplCopyString(options->output_bin, printer->driver_data.bin[printer->driver_data.bin_default], sizeof(options->output_bin)); } // page-ranges if ((attr = ippFindAttribute(job->attrs, "page-ranges", IPP_TAG_RANGE)) != NULL && ippGetCount(attr) == 1) { int last, first = ippGetRange(attr, 0, &last); // pages-ranges values if (first > (int)num_pages && num_pages != 0) { options->first_page = num_pages + 1; options->last_page = num_pages + 1; options->num_pages = 0; } else { options->first_page = (unsigned)first; if (last > (int)num_pages && num_pages != 0) options->last_page = num_pages; else options->last_page = (unsigned)last; options->num_pages = options->last_page - options->first_page + 1; } } else if (num_pages > 0) { options->first_page = 1; options->last_page = num_pages; options->num_pages = num_pages; } else { // Unknown number of pages... options->first_page = 1; options->last_page = INT_MAX; options->num_pages = 0; } // print-color-mode if ((attr = ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_KEYWORD)) != NULL) options->print_color_mode = _papplColorModeValue(ippGetString(attr, 0, NULL)); else options->print_color_mode = printer->driver_data.color_default; papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-color-mode=%s", _papplColorModeString(options->print_color_mode)); if (options->print_color_mode == PAPPL_COLOR_MODE_AUTO) { if (color) options->print_color_mode = PAPPL_COLOR_MODE_COLOR; else options->print_color_mode = PAPPL_COLOR_MODE_MONOCHROME; papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "new print-color-mode=%s", _papplColorModeString(options->print_color_mode)); } else if (options->print_color_mode == PAPPL_COLOR_MODE_AUTO_MONOCHROME) { options->print_color_mode = PAPPL_COLOR_MODE_MONOCHROME; papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "new print-color-mode=%s", _papplColorModeString(options->print_color_mode)); } // print-content-optimize if ((attr = ippFindAttribute(job->attrs, "print-content-optimize", IPP_TAG_KEYWORD)) != NULL) options->print_content_optimize = _papplContentValue(ippGetString(attr, 0, NULL)); else options->print_content_optimize = printer->driver_data.content_default; // print-darkness if ((attr = ippFindAttribute(job->attrs, "print-darkness", IPP_TAG_INTEGER)) != NULL) options->print_darkness = ippGetInteger(attr, 0); else options->print_darkness = printer->driver_data.darkness_default; options->darkness_configured = printer->driver_data.darkness_configured; // print-quality if ((attr = ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM)) != NULL) options->print_quality = (ipp_quality_t)ippGetInteger(attr, 0); else options->print_quality = printer->driver_data.quality_default; // print-scaling if ((attr = ippFindAttribute(job->attrs, "print-scaling", IPP_TAG_KEYWORD)) != NULL) options->print_scaling = _papplScalingValue(ippGetString(attr, 0, NULL)); else options->print_scaling = printer->driver_data.scaling_default; // print-speed if ((attr = ippFindAttribute(job->attrs, "print-speed", IPP_TAG_INTEGER)) != NULL) options->print_speed = ippGetInteger(attr, 0); else options->print_speed = printer->driver_data.speed_default; // printer-resolution if ((attr = ippFindAttribute(job->attrs, "printer-resolution", IPP_TAG_RESOLUTION)) != NULL) { ipp_res_t units; // Resolution units options->printer_resolution[0] = ippGetResolution(attr, 0, options->printer_resolution + 1, &units); } else if (options->print_quality == IPP_QUALITY_DRAFT) { // print-quality=draft options->printer_resolution[0] = printer->driver_data.x_resolution[0]; options->printer_resolution[1] = printer->driver_data.y_resolution[0]; } else if (options->print_quality == IPP_QUALITY_NORMAL) { // print-quality=normal i = (cups_len_t)printer->driver_data.num_resolution / 2; options->printer_resolution[0] = printer->driver_data.x_resolution[i]; options->printer_resolution[1] = printer->driver_data.y_resolution[i]; } else { // print-quality=high i = (cups_len_t)printer->driver_data.num_resolution - 1; options->printer_resolution[0] = printer->driver_data.x_resolution[i]; options->printer_resolution[1] = printer->driver_data.y_resolution[i]; } // sides if ((attr = ippFindAttribute(job->attrs, "sides", IPP_TAG_KEYWORD)) != NULL) options->sides = _papplSidesValue(ippGetString(attr, 0, NULL)); else if (printer->driver_data.sides_default != PAPPL_SIDES_ONE_SIDED && options->num_pages != 1) options->sides = printer->driver_data.sides_default; else options->sides = PAPPL_SIDES_ONE_SIDED; // Vendor options... for (i = 0; i < (cups_len_t)printer->driver_data.num_vendor; i ++) { const char *name = printer->driver_data.vendor[i]; // Vendor attribute name if ((attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO)) == NULL) { char defname[128]; // xxx-default attribute snprintf(defname, sizeof(defname), "%s-default", name); attr = ippFindAttribute(job->attrs, defname, IPP_TAG_ZERO); } if (attr) { char value[1024]; // Value of attribute ippAttributeString(attr, value, sizeof(value)); options->num_vendor = (int)cupsAddOption(name, value, (cups_len_t)options->num_vendor, &options->vendor); } } // Figure out the PWG raster header... if (printer->driver_data.force_raster_type == PAPPL_PWG_RASTER_TYPE_BLACK_1) { // Force bitmap output... raster_type = "black_1"; if (options->print_color_mode == PAPPL_COLOR_MODE_BI_LEVEL || options->print_quality == IPP_QUALITY_DRAFT) memset(options->dither, 127, sizeof(options->dither)); else if (options->print_content_optimize == PAPPL_CONTENT_PHOTO || !strcmp(job->format, "image/jpeg") || options->print_quality == IPP_QUALITY_HIGH) memcpy(options->dither, printer->driver_data.pdither, sizeof(options->dither)); else memcpy(options->dither, printer->driver_data.gdither, sizeof(options->dither)); } else if (options->print_color_mode == PAPPL_COLOR_MODE_COLOR) { // Color output... if (printer->driver_data.raster_types & PAPPL_PWG_RASTER_TYPE_SRGB_8) raster_type = "srgb_8"; else if (printer->driver_data.raster_types & PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8) raster_type = "adobe-rgb_8"; else raster_type = "rgb_8"; } else { // Monochrome output... if (printer->driver_data.raster_types & PAPPL_PWG_RASTER_TYPE_SGRAY_8) raster_type = "sgray_8"; else raster_type = "black_8"; } if (options->print_quality == IPP_QUALITY_HIGH) memcpy(options->dither, printer->driver_data.pdither, sizeof(options->dither)); else memcpy(options->dither, printer->driver_data.gdither, sizeof(options->dither)); // Generate the raster header... #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 cupsRasterInitPWGHeader(&options->header, pwgMediaForPWG(options->media.size_name), raster_type, options->printer_resolution[0], options->printer_resolution[1], _papplSidesString(options->sides), sheet_back[printer->driver_data.duplex]); for (i = 0; i < (int)(sizeof(media_positions) / sizeof(media_positions[0])); i ++) { if (!strcmp(media_positions[i], options->media.source)) { options->header.MediaPosition = (unsigned)i; break; } } papplCopyString(options->header.MediaType, options->media.type, sizeof(options->header.MediaType)); papplCopyString(options->header.OutputType, _papplContentString(options->print_content_optimize), sizeof(options->header.OutputType)); if (options->finishings & PAPPL_FINISHINGS_TRIM) options->header.CutMedia = CUPS_CUT_PAGE; options->header.Orientation = orientations[options->orientation_requested - IPP_ORIENT_PORTRAIT]; options->header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount] = (unsigned)options->copies * options->num_pages; options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom] = options->header.cupsHeight - (unsigned)options->media.bottom_margin * options->header.HWResolution[1] / 2540 - 1; options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxLeft] = (unsigned)options->media.left_margin * options->header.HWResolution[0] / 2540; options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxRight] = options->header.cupsWidth - (unsigned)options->media.right_margin * options->header.HWResolution[0] / 2540 - 1; options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxTop] = (unsigned)options->media.top_margin * options->header.HWResolution[1] / 2540; options->header.cupsInteger[CUPS_RASTER_PWG_PrintQuality] = options->print_quality; #else // CUPS 2.5/3.x have a new API for this... cups_media_t media; // CUPS media value memset(&media, 0, sizeof(media)); papplCopyString(media.media, options->media.size_name, sizeof(media.media)); papplCopyString(media.source, options->media.source, sizeof(media.source)); papplCopyString(media.type, options->media.type, sizeof(media.type)); media.width = options->media.size_width; media.length = options->media.size_length; media.bottom = options->media.bottom_margin; media.left = options->media.left_margin; media.right = options->media.right_margin; media.top = options->media.top_margin; cupsRasterInitHeader(&options->header, &media, _papplContentString(options->print_content_optimize), options->print_quality, /*intent*/NULL, options->orientation_requested, _papplSidesString(options->sides), raster_type, options->printer_resolution[0], options->printer_resolution[1], sheet_back[printer->driver_data.duplex]); #endif // CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 // Log options... papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsWidth=%u", options->header.cupsWidth); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsHeight=%u", options->header.cupsHeight); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsBitsPerColor=%u", options->header.cupsBitsPerColor); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsBitsPerPixel=%u", options->header.cupsBitsPerPixel); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsBytesPerLine=%u", options->header.cupsBytesPerLine); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsColorOrder=%u", options->header.cupsColorOrder); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsColorSpace=%u (%s)", options->header.cupsColorSpace, cups_cspace_string(options->header.cupsColorSpace)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.cupsNumColors=%u", options->header.cupsNumColors); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.HWResolution=[%u %u]", options->header.HWResolution[0], options->header.HWResolution[1]); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "header.PWG_ImageBox=[%u %u %u %u]", options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxLeft], options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxTop], options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxRight], options->header.cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom]); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "num_pages=%u", options->num_pages); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "copies=%d", options->copies); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "finishings=0x%x", options->finishings); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.bottom-margin=%d", options->media.bottom_margin); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.left-margin=%d", options->media.left_margin); if (printer->driver_data.left_offset_supported[1]) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.left-offset=%d", options->media.left_offset); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.right-margin=%d", options->media.right_margin); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.size=%dx%d", options->media.size_width, options->media.size_length); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.size-name='%s'", options->media.size_name); if (printer->driver_data.num_source) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.source='%s'", options->media.source); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.top-margin=%d", options->media.top_margin); if (printer->driver_data.top_offset_supported[1]) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.top-offset=%d", options->media.top_offset); if (printer->driver_data.tracking_supported) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.tracking='%s'", _papplMediaTrackingString(options->media.tracking)); if (printer->driver_data.num_type) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "media-col.type='%s'", options->media.type); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "orientation-requested=%s", ippEnumString("orientation-requested", (int)options->orientation_requested)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "page-ranges=%u-%u", options->first_page, options->last_page); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-color-mode='%s'", _papplColorModeString(options->print_color_mode)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-content-optimize='%s'", _papplContentString(options->print_content_optimize)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-darkness=%d", options->print_darkness); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-quality=%s", ippEnumString("print-quality", (int)options->print_quality)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-scaling='%s'", _papplScalingString(options->print_scaling)); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "print-speed=%d", options->print_speed); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "printer-resolution=%dx%ddpi", options->printer_resolution[0], options->printer_resolution[1]); for (i = 0; i < (cups_len_t)options->num_vendor; i ++) papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "%s=%s", options->vendor[i].name, options->vendor[i].value); _papplRWUnlock(printer); return (options); } // // 'papplJobDeletePrintOptions()' - Delete a job options structure. // // This function frees the memory used for a job options structure. // void papplJobDeletePrintOptions( pappl_pr_options_t *options) // I - Options { if (options) { cupsFreeOptions((cups_len_t)options->num_vendor, options->vendor); free(options); } } // // '_papplJobProcess()' - Process a print job. // void * // O - Thread exit status _papplJobProcess(pappl_job_t *job) // I - Job { _pappl_mime_filter_t *filter; // Filter for printing // Start processing the job... if (start_job(job)) { // Do file-specific conversions... if ((filter = _papplSystemFindMIMEFilter(job->system, job->format, job->printer->driver_data.format)) == NULL) filter =_papplSystemFindMIMEFilter(job->system, job->format, "image/pwg-raster"); if (filter) { if (!(filter->cb)(job, job->printer->device, filter->cbdata)) job->state = IPP_JSTATE_ABORTED; } else if (!strcmp(job->format, job->printer->driver_data.format)) { if (!filter_raw(job, job->printer->device)) job->state = IPP_JSTATE_ABORTED; } else { // Abort a job we can't process... papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to process job with format '%s'.", job->format); job->state = IPP_JSTATE_ABORTED; } } // Move the job to a completed state... finish_job(job); return (NULL); } // // '_papplJobProcessRaster()' - Process an Apple/PWG Raster file. // void _papplJobProcessRaster( pappl_job_t *job, // I - Job pappl_client_t *client) // I - Client { pappl_printer_t *printer = job->printer; // Printer for job pappl_pr_options_t *options = NULL;// Job options cups_raster_t *ras = NULL; // Raster stream cups_page_header_t header; // Page header unsigned header_pages; // Number of pages from page header const unsigned char *dither; // Dither line unsigned char *pixels, // Incoming pixel line *pixptr, // Pixel pointer in line *line, // Output (bitmap) line *lineptr, // Pointer in line byte, // Byte in line bit; // Current bit unsigned page = 0, // Current page x, // Current column y; // Current line int job_pages_per_set; // "job-pages-per-set" value, if any unsigned next_copy; // Next copy boundary // Start processing the job... job->streaming = true; if (!start_job(job)) goto complete_job; // Open the raster stream... if ((ras = cupsRasterOpenIO((cups_raster_cb_t)httpRead, client->http, CUPS_RASTER_READ)) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to open raster stream from client - %s", cupsGetErrorString()); job->state = IPP_JSTATE_ABORTED; goto complete_job; } // Prepare options... if (!cupsRasterReadHeader(ras, &header)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to read raster stream from client - %s", cupsGetErrorString()); job->state = IPP_JSTATE_ABORTED; goto complete_job; } if ((job_pages_per_set = ippGetInteger(ippFindAttribute(job->attrs, "job-pages-per-set", IPP_TAG_INTEGER), 0)) > 0) { // Use the job-pages-per-set value to set the number of impressions... papplJobSetImpressions(job, job_pages_per_set); // Track copies at page boundaries... next_copy = (unsigned)job_pages_per_set; } else { // Don't track copies... next_copy = 0; } if ((header_pages = header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount]) > 0 && job_pages_per_set == 0) papplJobSetImpressions(job, (int)header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount]); options = papplJobCreatePrintOptions(job, (unsigned)job->impressions, header.cupsBitsPerPixel > 8); if (!(printer->driver_data.rstartjob_cb)(job, options, job->printer->device)) { job->state = IPP_JSTATE_ABORTED; goto complete_job; } // Print pages... do { if (job->is_canceled) break; papplJobSetImpressionsCompleted(job, 1); papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Page %u raster data is %ux%ux%u (%s)", page + 1, header.cupsWidth, header.cupsHeight, header.cupsBitsPerPixel, cups_cspace_string(header.cupsColorSpace)); papplSystemAddEvent(printer->system, printer, job, PAPPL_EVENT_JOB_PROGRESS, NULL); // Set options for this page... papplJobDeletePrintOptions(options); options = papplJobCreatePrintOptions(job, (unsigned)job->impressions, header.cupsBitsPerPixel > 8); if (header.cupsWidth == 0 || header.cupsHeight == 0 || (header.cupsBitsPerColor != 1 && header.cupsBitsPerColor != 8) || header.cupsColorOrder != CUPS_ORDER_CHUNKED || (header.cupsBytesPerLine != ((header.cupsWidth * header.cupsBitsPerPixel + 7) / 8))) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Bad raster data seen."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_FORMAT_ERROR, PAPPL_JREASON_NONE); job->state = IPP_JSTATE_ABORTED; break; } if (header.cupsBitsPerPixel > 8 && !(printer->driver_data.color_supported & PAPPL_COLOR_MODE_COLOR)) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unsupported raster data seen."); papplJobSetReasons(job, PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR, PAPPL_JREASON_NONE); job->state = IPP_JSTATE_ABORTED; break; } if (options->header.cupsBitsPerPixel >= 8 && header.cupsBitsPerPixel >= 8) options->header = header; // Use page header from client if (!(printer->driver_data.rstartpage_cb)(job, options, job->printer->device, page)) { job->state = IPP_JSTATE_ABORTED; break; } if (options->header.cupsBytesPerLine > header.cupsBytesPerLine) { // Allocate enough space for the entire output line and clear to white if ((pixels = malloc(options->header.cupsBytesPerLine)) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate raster line."); job->state = IPP_JSTATE_ABORTED; break; } if (options->header.cupsColorSpace == CUPS_CSPACE_K) memset(pixels, 0, options->header.cupsBytesPerLine); else memset(pixels, 255, options->header.cupsBytesPerLine); } else { // The input raster is at least as wide as the output raster... if ((pixels = malloc(header.cupsBytesPerLine)) == NULL) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate raster line."); job->state = IPP_JSTATE_ABORTED; break; } } if ((line = malloc(options->header.cupsBytesPerLine)) == NULL) { free(pixels); papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate raster line."); job->state = IPP_JSTATE_ABORTED; break; } for (y = 0; !job->is_canceled && y < header.cupsHeight && y < options->header.cupsHeight; y ++) { if (cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine)) { if (header.cupsBitsPerPixel == 8 && options->header.cupsBitsPerPixel == 1) { // Dither the line... dither = options->dither[y & 15]; memset(line, 0, options->header.cupsBytesPerLine); if (header.cupsColorSpace == CUPS_CSPACE_K) { // Black... for (x = 0, lineptr = line, pixptr = pixels, bit = 128, byte = 0; x < header.cupsWidth; x ++, pixptr ++) { if (*pixptr > dither[x & 15]) byte |= bit; if (bit == 1) { *lineptr++ = byte; byte = 0; bit = 128; } else bit /= 2; } if (bit < 128) *lineptr = byte; } else { // Grayscale to black... for (x = 0, lineptr = line, pixptr = pixels, bit = 128, byte = 0; x < header.cupsWidth; x ++, pixptr ++) { if (*pixptr <= dither[x & 15]) byte |= bit; if (bit == 1) { *lineptr++ = byte; byte = 0; bit = 128; } else bit /= 2; } if (bit < 128) *lineptr = byte; } (printer->driver_data.rwriteline_cb)(job, options, job->printer->device, y, line); } else (printer->driver_data.rwriteline_cb)(job, options, job->printer->device, y, pixels); } else break; } if (!job->is_canceled && y < header.cupsHeight) { // Discard excess lines from client... while (y < header.cupsHeight) { cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine); y ++; } } else { // Pad missing lines with whitespace... if (header.cupsBitsPerPixel == 8 && options->header.cupsBitsPerPixel == 1) { memset(line, 0, options->header.cupsBytesPerLine); while (y < options->header.cupsHeight) { (printer->driver_data.rwriteline_cb)(job, options, job->printer->device, y, line); y ++; } } else { if (header.cupsColorSpace == CUPS_CSPACE_K || header.cupsColorSpace == CUPS_CSPACE_CMYK) memset(pixels, 0x00, header.cupsBytesPerLine); else memset(pixels, 0xff, header.cupsBytesPerLine); while (y < options->header.cupsHeight) { (printer->driver_data.rwriteline_cb)(job, options, job->printer->device, y, pixels); y ++; } } } free(pixels); free(line); if (!(printer->driver_data.rendpage_cb)(job, options, job->printer->device, page)) { job->state = IPP_JSTATE_ABORTED; break; } page ++; if (page == next_copy) { // Report a completed copy... papplJobSetCopiesCompleted(job, 1); next_copy += (unsigned)job_pages_per_set; } if (job->is_canceled) { break; } else if (y < header.cupsHeight) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to read page from raster stream from client - %s", cupsGetErrorString()); job->state = IPP_JSTATE_ABORTED; break; } } while (cupsRasterReadHeader(ras, &header)); if (next_copy == 0) { // Not tracking copies so record this as a single completed copy... papplJobSetCopiesCompleted(job, 1); } if (!(printer->driver_data.rendjob_cb)(job, options, job->printer->device)) job->state = IPP_JSTATE_ABORTED; else if (header_pages == 0 && job_pages_per_set == 0) papplJobSetImpressions(job, (int)page); complete_job: papplJobDeletePrintOptions(options); if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { // Flush excess data... char buffer[8192]; // Read buffer while (httpRead(client->http, buffer, sizeof(buffer)) > 0) ; // Read all document data } cupsRasterClose(ras); finish_job(job); return; } // // 'papplJobResume()' - Resume processing of a job. // void papplJobResume(pappl_job_t *job, // I - Job pappl_jreason_t remove) // I - Reasons to remove from "job-state-reasons" { // Range check input... if (!job) return; // Update state... _papplRWLockWrite(job); if (job->state == IPP_JSTATE_STOPPED) { job->state = IPP_JSTATE_PENDING; job->state_reasons &= ~remove; } _papplRWUnlock(job); _papplRWLockWrite(job->printer); _papplPrinterCheckJobsNoLock(job->printer); _papplRWUnlock(job->printer); } // // 'papplJobSuspend()' - Temporarily stop processing of a job. // void papplJobSuspend(pappl_job_t *job, // I - Job pappl_jreason_t add) // I - Reasons to add to "job-state-reasons" { // Range check input... if (!job) return; // Update state... _papplRWLockWrite(job); if (job->state < IPP_JSTATE_STOPPED) { job->state = IPP_JSTATE_STOPPED; job->state_reasons |= add; } _papplRWUnlock(job); } // // 'cups_cspace_string()' - Get a string corresponding to a cupsColorSpace enum value. // static const char * // O - cupsColorSpace string value cups_cspace_string( cups_cspace_t value) // I - cupsColorSpace enum value { static const char * const cspace[] = // cupsColorSpace values { "Gray", "RGB", "RGBA", "Black", "CMY", "YMC", "CMYK", "YMCK", "KCMY", "KCMYcm", "GMCK", "GMCS", "White", "Gold", "Silver", "CIE-XYZ", "CIE-Lab", "RGBW", "sGray", "sRGB", "Adobe-RGB", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "ICC-1", "ICC-2", "ICC-3", "ICC-4", "ICC-5", "ICC-6", "ICC-7", "ICC-8", "ICC-9", "ICC-10", "ICC-11", "ICC-12", "ICC-13", "ICC-14", "ICC-15", "47", "Device-1", "Device-2", "Device-3", "Device-4", "Device-5", "Device-6", "Device-7", "Device-8", "Device-9", "Device-10", "Device-11", "Device-12", "Device-13", "Device-14", "Device-15" }; if (value >= CUPS_CSPACE_W && value <= CUPS_CSPACE_DEVICEF) return (cspace[value]); else return ("Unknown"); } // // 'filter_raw()' - "Filter" a raw print file. // static bool // O - `true` on success, `false` otherwise filter_raw(pappl_job_t *job, // I - Job pappl_device_t *device) // I - Device { pappl_pr_options_t *options; // Job options papplJobSetImpressions(job, 1); options = papplJobCreatePrintOptions(job, 0, job->printer->driver_data.ppm_color > 0); if (!(job->printer->driver_data.printfile_cb)(job, options, device)) { papplJobDeletePrintOptions(options); return (false); } papplJobDeletePrintOptions(options); papplJobSetImpressionsCompleted(job, 1); return (true); } // // 'finish_job()' - Finish job processing... // static void finish_job(pappl_job_t *job) // I - Job { pappl_printer_t *printer = job->printer; // Printer static const char * const job_states[] = { "Pending", "Held", "Processing", "Stopped", "Canceled", "Aborted", "Completed" }; _papplRWLockWrite(printer); _papplRWLockWrite(job); if (job->is_canceled) job->state = IPP_JSTATE_CANCELED; else if (job->state == IPP_JSTATE_PROCESSING) job->state = IPP_JSTATE_COMPLETED; papplLogJob(job, PAPPL_LOGLEVEL_INFO, "%s, job-impressions-completed=%d.", job_states[job->state - IPP_JSTATE_PENDING], job->impcompleted); if (job->state >= IPP_JSTATE_CANCELED) job->completed = time(NULL); _papplJobSetRetain(job); printer->processing_job = NULL; if (job->state >= IPP_JSTATE_CANCELED && !printer->max_preserved_jobs && !job->retain_until) _papplJobRemoveFile(job); _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_COMPLETED, NULL); if (printer->is_stopped) { // New printer-state is 'stopped'... printer->state = IPP_PSTATE_STOPPED; printer->is_stopped = false; } else { // New printer-state is 'idle'... printer->state = IPP_PSTATE_IDLE; } printer->state_time = time(NULL); cupsArrayRemove(printer->active_jobs, job); cupsArrayAdd(printer->completed_jobs, job); printer->impcompleted += job->impcompleted; if (!job->system->clean_time) job->system->clean_time = time(NULL) + 60; _papplRWUnlock(job); _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, NULL); if (printer->max_preserved_jobs > 0) _papplPrinterCleanJobsNoLock(printer); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); if (papplPrinterIsDeleted(printer)) { papplPrinterDelete(printer); return; } else if (!strncmp(printer->device_uri, "file:", 5) || cupsArrayGetCount(printer->active_jobs) == 0) { pappl_devmetrics_t metrics; // Metrics for device IO _papplRWLockWrite(printer); papplDeviceGetMetrics(printer->device, &metrics); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Device read metrics: %lu requests, %lu bytes, %lu msecs", (unsigned long)metrics.read_requests, (unsigned long)metrics.read_bytes, (unsigned long)metrics.read_msecs); papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Device write metrics: %lu requests, %lu bytes, %lu msecs", (unsigned long)metrics.write_requests, (unsigned long)metrics.write_bytes, (unsigned long)metrics.write_msecs); // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Closing device for job %d.", job->job_id); papplDeviceClose(printer->device); printer->device = NULL; _papplRWUnlock(printer); } if (papplPrinterGetNumberOfActiveJobs(printer) > 0) { _papplRWLockWrite(printer); _papplPrinterCheckJobsNoLock(printer); _papplRWUnlock(printer); } } // // 'start_job()' - Start processing a job... // static bool // O - `true` on success, `false` otherwise start_job(pappl_job_t *job) // I - Job { bool ret = false; // Return value pappl_printer_t *printer = job->printer; // Printer bool first_open = true; // Is this the first time we try to open the device? // Move the job to the 'processing' state... _papplRWLockWrite(printer); _papplRWLockWrite(job); papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Starting print job."); job->state = IPP_JSTATE_PROCESSING; job->processing = time(NULL); printer->processing_job = job; _papplSystemAddEventNoLock(printer->system, printer, job, PAPPL_EVENT_JOB_STATE_CHANGED, NULL); _papplRWUnlock(job); // Open the output device... if (printer->device_in_use) { papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Waiting for device to become available."); while (printer->device_in_use && !printer->is_deleted && !job->is_canceled && papplSystemIsRunning(printer->system)) { _papplRWUnlock(printer); sleep(1); _papplRWLockWrite(printer); } } while (!printer->device && !printer->is_deleted && !job->is_canceled && papplSystemIsRunning(printer->system)) { // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Opening device for job %d.", job->job_id); printer->device = papplDeviceOpen(printer->device_uri, job->name, papplLogDevice, job->system); if (!printer->device && !printer->is_deleted && !job->is_canceled) { // Log that the printer is unavailable then sleep for 5 seconds to retry. if (first_open) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to open device '%s', pausing queue until printer becomes available.", printer->device_uri); first_open = false; printer->state = IPP_PSTATE_STOPPED; printer->state_time = time(NULL); } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Still unable to open device."); } _papplRWUnlock(printer); sleep(5); _papplRWLockWrite(printer); } } if (!papplSystemIsRunning(printer->system)) { job->state = IPP_JSTATE_PENDING; _papplRWLockRead(job); _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_STATE_CHANGED, NULL); _papplRWUnlock(job); if (printer->device) { papplDeviceClose(printer->device); printer->device = NULL; } } if (printer->device) { // Move the printer to the 'processing' state... printer->state = IPP_PSTATE_PROCESSING; printer->state_time = time(NULL); ret = true; } _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, NULL); _papplRWUnlock(printer); return (ret); } pappl-1.4.9/pappl/job.c000066400000000000000000001000171476704353100147040ustar00rootroot00000000000000// // Job object for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // 'papplJobCancel()' - Cancel a job. // // This function cancels the specified job. If the job is currently being // printed, it will be stopped at a convenient time (usually the end of a page) // so that the printer will be left in a known state. // void papplJobCancel(pappl_job_t *job) // I - Job { if (!job) return; _papplRWLockWrite(job->printer); _papplRWLockWrite(job); if (job->state == IPP_JSTATE_PROCESSING || (job->state == IPP_JSTATE_HELD && job->fd >= 0)) { job->is_canceled = true; } else { job->state = IPP_JSTATE_CANCELED; job->completed = time(NULL); _papplJobRemoveFile(job); cupsArrayRemove(job->printer->active_jobs, job); cupsArrayAdd(job->printer->completed_jobs, job); } if (!job->system->clean_time) job->system->clean_time = time(NULL) + 60; _papplRWUnlock(job); _papplRWUnlock(job->printer); papplSystemAddEvent(job->system, job->printer, job, PAPPL_EVENT_JOB_COMPLETED, NULL); } // // '_papplJobCreate()' - Create a new/existing job object. // pappl_job_t * // O - Job _papplJobCreate( pappl_printer_t *printer, // I - Printer int job_id, // I - Existing Job ID or `0` for new job const char *username, // I - Username const char *format, // I - Document format or `NULL` for none const char *job_name, // I - Job name ipp_t *attrs) // I - Job creation attributes or `NULL` for none { pappl_job_t *job; // Job ipp_attribute_t *attr; // Job attribute char job_printer_uri[1024], // job-printer-uri value job_uri[1024], // job-uri value job_uuid[64]; // job-uuid value _papplRWLockWrite(printer); if (printer->max_active_jobs > 0 && (int)cupsArrayGetCount(printer->active_jobs) >= printer->max_active_jobs) { _papplRWUnlock(printer); return (NULL); } // Allocate and initialize the job object... if ((job = calloc(1, sizeof(pappl_job_t))) == NULL) { papplLog(printer->system, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for job: %s", strerror(errno)); _papplRWUnlock(printer); return (NULL); } pthread_rwlock_init(&job->rwlock, NULL); job->attrs = ippNew(); job->fd = -1; job->format = format; job->name = job_name; job->printer = printer; job->state = IPP_JSTATE_HELD; job->system = printer->system; job->created = time(NULL); job->copies = 1; if (attrs) { // Copy all of the job attributes... const char *hold_until; // "job-hold-until" value time_t hold_until_time; // "job-hold-until-time" value if ((attr = ippFindAttribute(attrs, "client-info", IPP_TAG_BEGIN_COLLECTION)) != NULL) { if ((attr = ippCopyAttribute(job->attrs, attr, false)) != NULL) ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB); } _papplCopyAttributes(job->attrs, attrs, NULL, IPP_TAG_JOB, 0); if ((attr = ippFindAttribute(job->attrs, "copies", IPP_TAG_INTEGER)) != NULL) job->copies = ippGetInteger(attr, 0); hold_until = ippGetString(ippFindAttribute(attrs, "job-hold-until", IPP_TAG_KEYWORD), 0, NULL); hold_until_time = ippDateToTime(ippGetDate(ippFindAttribute(attrs, "job-hold-until-time", IPP_TAG_DATE), 0)); if ((hold_until && strcmp(hold_until, "no-hold")) || hold_until_time) _papplJobHoldNoLock(job, NULL, hold_until, hold_until_time); if (!format && ippGetOperation(attrs) != IPP_OP_CREATE_JOB) { if ((attr = ippFindAttribute(attrs, "document-format-detected", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else if ((attr = ippFindAttribute(attrs, "document-format-supplied", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else job->format = "application/octet-stream"; } } else { ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, job_name); } if ((attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name", NULL, username)) != NULL) job->username = ippGetString(attr, 0, NULL); if ((attr = ippFindAttribute(attrs, "job-impressions", IPP_TAG_INTEGER)) != NULL) job->impressions = ippGetInteger(attr, 0); // Add job description attributes and add to the jobs array... job->job_id = job_id > 0 ? job_id : printer->next_job_id ++; if ((attr = ippFindAttribute(attrs, "printer-uri", IPP_TAG_URI)) != NULL) { papplCopyString(job_printer_uri, ippGetString(attr, 0, NULL), sizeof(job_printer_uri)); snprintf(job_uri, sizeof(job_uri), "%s/%d", ippGetString(attr, 0, NULL), job->job_id); } else { httpAssembleURI(HTTP_URI_CODING_ALL, job_printer_uri, sizeof(job_printer_uri), "ipps", NULL, printer->system->hostname, printer->system->port, printer->resource); httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipps", NULL, printer->system->hostname, printer->system->port, "%s/%d", printer->resource, job->job_id); } _papplSystemMakeUUID(printer->system, printer->name, job->job_id, job_uuid, sizeof(job_uuid)); ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->job_id); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL, job_uuid); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, job_printer_uri); cupsArrayAdd(printer->all_jobs, job); if (!job_id) cupsArrayAdd(printer->active_jobs, job); _papplRWUnlock(printer); papplSystemAddEvent(printer->system, printer, job, PAPPL_EVENT_JOB_CREATED, NULL); _papplSystemConfigChanged(printer->system); return (job); } // // 'papplJobCreateWithFile()' - Create a job with a local file. // // This function creates a new print job with a local file. The "num_options" // and "options" parameters specify additional print options, as needed. The // file specified by "filename" is removed automatically if it resides in the // spool directory. // pappl_job_t * // O - New job object or `NULL` on error papplJobCreateWithFile( pappl_printer_t *printer, // I - Printer const char *username, // I - Submitting user name const char *format, // I - MIME media type of file const char *job_name, // I - Job name int num_options, // I - Number of options cups_option_t *options, // I - Options or `NULL` if none const char *filename) // I - File to print { pappl_job_t *job; // New job ipp_t *attrs; // Attributes for job // Range check input... if (!printer || !username || !format || !job_name || !filename) return (NULL); // Encode options as needed... if (num_options > 0 && options) { attrs = ippNew(); _papplRWLockRead(printer); _papplMainloopAddOptions(attrs, (cups_len_t)num_options, options, printer->driver_attrs); _papplRWUnlock(printer); } else { attrs = NULL; } // Create the job... if ((job = _papplJobCreate(printer, 0, username, format, job_name, attrs)) != NULL) _papplJobSubmitFile(job, filename); ippDelete(attrs); return (job); } // // '_papplJobDelete()' - Remove a job from the system and free its memory. // void _papplJobDelete(pappl_job_t *job) // I - Job { papplLogJob(job, PAPPL_LOGLEVEL_INFO, "Removing job from history."); pthread_rwlock_destroy(&job->rwlock); ippDelete(job->attrs); free(job->message); // Only remove the job file (document) if the job is in a terminating state... if (job->state >= IPP_JSTATE_CANCELED) _papplJobRemoveFile(job); free(job); } // // 'papplJobHold()' - Hold a job for printing. // // This function holds a pending job for printing at a later time. // bool // O - `true` on success, `false` on failure papplJobHold(pappl_job_t *job, // I - Job const char *username, // I - User that held the job or `NULL` for none/system const char *until, // I - "job-hold-until" keyword or `NULL` time_t until_time) // I - "job-hold-until-time" value or 0 for indefinite { bool ret = false; // Return value // Range check input if (!job) return (false); // Lock the printer and job so we can change it... _papplRWLockRead(job->printer); _papplRWLockWrite(job); // Only hold jobs that haven't entered the processing state... if (job->state < IPP_JSTATE_PROCESSING) { // Hold until the specified time... ret = _papplJobHoldNoLock(job, username, until, until_time); } _papplRWUnlock(job); _papplRWUnlock(job->printer); return (ret); } // // '_papplJobHoldNoLock()' - Hold a job for printing without locking. // bool // O - `true` on success, `false` on failure _papplJobHoldNoLock( pappl_job_t *job, // I - Job const char *username, // I - User that held the job or `NULL` for none/system const char *until, // I - "job-hold-until" keyword or `NULL` time_t until_time) // I - "job-hold-until-time" value or 0 for indefinite { ipp_attribute_t *attr; // "job-hold-until[-time]" attribute job->state = IPP_JSTATE_HELD; if (until) { // Hold until the specified time period... time_t curtime; // Current time struct tm curdate; // Current date job->state_reasons |= PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED; time(&curtime); localtime_r(&curtime, &curdate); if (!strcmp(until, "day-time")) { // Hold to 6am the next morning unless local time is < 6pm. if (curdate.tm_hour < 18) job->hold_until = curtime; else job->hold_until = curtime + ((29 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "evening") || !strcmp(until, "night")) { // Hold to 6pm unless local time is > 6pm or < 6am. if (curdate.tm_hour < 6 || curdate.tm_hour >= 18) job->hold_until = curtime; else job->hold_until = curtime + ((17 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "second-shift")) { // Hold to 4pm unless local time is > 4pm. if (curdate.tm_hour >= 16) job->hold_until = curtime; else job->hold_until = curtime + ((15 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "third-shift")) { // Hold to 12am unless local time is < 8am. if (curdate.tm_hour < 8) job->hold_until = curtime; else job->hold_until = curtime + ((23 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "weekend")) { // Hold to weekend unless we are in the weekend. if (curdate.tm_wday == 0 || curdate.tm_wday == 6) job->hold_until = curtime; else job->hold_until = curtime + (((5 - curdate.tm_wday) * 24 + (17 - curdate.tm_hour)) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else { // Hold indefinitely... job->hold_until = 0; } // Update attributes... if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) != NULL) ippSetString(job->attrs, &attr, 0, until); else ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-hold-until", NULL, until); if ((attr = ippFindAttribute(job->attrs, "job-hold-until-time", IPP_TAG_DATE)) != NULL) ippDeleteAttribute(job->attrs, attr); } else if (until_time > 0) { // Hold until the specified time... job->state_reasons |= PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED; job->hold_until = until_time; // Update attributes... if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) != NULL) ippDeleteAttribute(job->attrs, attr); if ((attr = ippFindAttribute(job->attrs, "job-hold-until-time", IPP_TAG_DATE)) != NULL) ippSetDate(job->attrs, &attr, 0, ippTimeToDate(until_time)); else ippAddDate(job->attrs, IPP_TAG_JOB, "job-hold-until-time", ippTimeToDate(until_time)); } else { // Hold indefinitely... job->state_reasons &= (pappl_jreason_t)(~PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED); job->hold_until = 0; // Update attributes... if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) != NULL) ippDeleteAttribute(job->attrs, attr); if ((attr = ippFindAttribute(job->attrs, "job-hold-until-time", IPP_TAG_DATE)) != NULL) ippDeleteAttribute(job->attrs, attr); } if (username) { _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_STATE_CHANGED, "Job held by '%s'.", username); } return (true); } // // 'papplJobOpenFile()' - Create or open a file for the document in a job. // // This function creates or opens a file for a job. The "fname" and "fnamesize" // arguments specify the location and size of a buffer to store the job // filename, which incorporates the "directory", printer ID, job ID, job name // (title), and "ext" values. The job name is "sanitized" to only contain // alphanumeric characters. // // The "mode" argument is "r" to read an existing job file or "w" to write a // new job file. New files are created with restricted permissions for // security purposes. // int // O - File descriptor or -1 on error papplJobOpenFile( pappl_job_t *job, // I - Job char *fname, // I - Filename buffer size_t fnamesize, // I - Size of filename buffer const char *directory, // I - Directory to store in (`NULL` for default) const char *ext, // I - Extension (`NULL` for default) const char *mode) // I - Open mode - "r" for reading or "w" for writing { char name[64], // "Safe" filename *nameptr; // Pointer into filename const char *job_name; // job-name value // Range check input... if (!job || !fname || fnamesize < 256 || !mode) { if (fname) *fname = '\0'; return (-1); } // Make sure the spool directory exists... if (!directory) directory = job->system->directory; if (mkdir(directory, 0777) && errno != EEXIST) { papplLogJob(job, PAPPL_LOGLEVEL_FATAL, "Unable to create spool directory '%s': %s", directory, strerror(errno)); return (-1); } // Make a name from the job-name attribute... if ((job_name = ippGetString(ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME), 0, NULL)) == NULL) job_name = "untitled"; if ((nameptr = strrchr(job_name, '/')) != NULL && nameptr[1]) job_name = nameptr + 1; for (nameptr = name; *job_name && nameptr < (name + sizeof(name) - 1); job_name ++) { if (isalnum(*job_name & 255) || *job_name == '-') { *nameptr++ = (char)tolower(*job_name & 255); } else { *nameptr++ = '_'; while (job_name[1] && !isalnum(job_name[1] & 255) && job_name[1] != '-') job_name ++; } } *nameptr = '\0'; // Figure out the extension... if (!ext) { if (!strcasecmp(job->format, "image/jpeg")) ext = "jpg"; else if (!strcasecmp(job->format, "image/png")) ext = "png"; else if (!strcasecmp(job->format, "image/pwg-raster")) ext = "pwg"; else if (!strcasecmp(job->format, "image/urf")) ext = "urf"; else if (!strcasecmp(job->format, "application/pdf")) ext = "pdf"; else if (!strcasecmp(job->format, "application/postscript")) ext = "ps"; else ext = "prn"; } // Create a filename with the job-id, job-name, and document-format (extension)... snprintf(fname, fnamesize, "%s/p%05dj%09d-%s.%s", directory, job->printer->printer_id, job->job_id, name, ext); if (!strcmp(mode, "r")) return (open(fname, O_RDONLY | O_NOFOLLOW | O_CLOEXEC | O_BINARY)); else if (!strcmp(mode, "w")) return (open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC | O_BINARY, 0600)); else if (!strcmp(mode, "x")) return (unlink(fname)); else return (-1); } // // 'papplJobRelease()' - Release a job for printing. // // This function releases a held job for printing. // bool // O - `true` on success, `false` on failure papplJobRelease(pappl_job_t *job, // I - Job const char *username) // I - User that released the job or `NULL` for none/system { bool ret = false; // Return value // Range check input if (!job) return (false); // Lock the job and printer... _papplRWLockWrite(job->printer); _papplRWLockWrite(job); // Only release jobs in the held state... if (job->state == IPP_JSTATE_HELD) { // Do the release... _papplJobReleaseNoLock(job, username); ret = true; } // Unlock and return... _papplRWUnlock(job); _papplPrinterCheckJobsNoLock(job->printer); _papplRWUnlock(job->printer); return (ret); } // // '_papplJobReleaseNoLock()' - Release a job for printing without locking. // void _papplJobReleaseNoLock( pappl_job_t *job, // I - Job const char *username) // I - User that released the job or `NULL` for none/system { ipp_attribute_t *attr; // "job-hold-until[-time]" attribute // Move the job back to the pending state and clear any attributes or states // related to job-hold-until... job->state = IPP_JSTATE_PENDING; job->state_reasons &= (pappl_jreason_t)(~PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED); if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) != NULL) ippDeleteAttribute(job->attrs, attr); if ((attr = ippFindAttribute(job->attrs, "job-hold-until-time", IPP_TAG_DATE)) != NULL) ippDeleteAttribute(job->attrs, attr); if (username) _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_STATE_CHANGED, "Job released by '%s'.", username); } // // '_papplJobRemoveFile()' - Remove a file in spool directory // void _papplJobRemoveFile(pappl_job_t *job) // I - Job { size_t dirlen = strlen(job->system->directory); // Length of spool directory const char *tempdir = papplGetTempDir(); // Location of temporary files size_t templen = strlen(tempdir); // Length of temporary directory // Only remove the file if it is in spool or temporary directory... if (job->filename) { if ((!strncmp(job->filename, job->system->directory, dirlen) && job->filename[dirlen] == '/') || (!strncmp(job->filename, tempdir, templen) && job->filename[templen] == '/')) unlink(job->filename); } free(job->filename); job->filename = NULL; } // // 'papplJobRetain()' - Retain a completed job until the specified time. // bool // O - `true` on success, `false` on failure papplJobRetain( pappl_job_t *job, // I - Job const char *username, // I - User that held the job or `NULL` for none/system const char *until, // I - "job-retain-until" value or `NULL` for none int until_interval, // I - "job-retain-until-interval" value or `0` for none time_t until_time) // I - "job-retain-until-time" value or `0` for none { bool ret = false; // Return value // Range check input if (!job) return (false); // Lock the printer and job so we can change it... _papplRWLockRead(job->printer); _papplRWLockWrite(job); // Only hold jobs that haven't entered the processing state... if (job->state < IPP_JSTATE_CANCELED) { // Hold until the specified time... ret = _papplJobRetainNoLock(job, username, until, until_interval, until_time); } _papplRWUnlock(job); _papplRWUnlock(job->printer); return (ret); } // // '_papplJobRetainNoLock()' - Retain a completed job until the specified time. // bool // O - `true` on success, `false` on failure _papplJobRetainNoLock( pappl_job_t *job, // I - Job const char *username, // I - User that held the job or `NULL` for none/system const char *until, // I - "job-retain-until" value or `NULL` for none int until_interval, // I - "job-retain-until-interval" value or `0` for none time_t until_time) // I - "job-retain-until-time" value or `0` for none { ipp_attribute_t *attr; // "job-retain-until[-interval,-time]" attribute // Update attributes... if ((attr = ippFindAttribute(job->attrs, "job-retain-until", IPP_TAG_KEYWORD)) != NULL) { if (until) ippSetString(job->attrs, &attr, 0, until); else ippDeleteAttribute(job->attrs, attr); } else if (until) { ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-retain-until", NULL, until); } if ((attr = ippFindAttribute(job->attrs, "job-retain-until-interval", IPP_TAG_INTEGER)) != NULL) { if (until_interval > 0) ippSetInteger(job->attrs, &attr, 0, until_interval); else ippDeleteAttribute(job->attrs, attr); } else if (until_interval > 0) { ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-retain-until-interval", until_interval); } if ((attr = ippFindAttribute(job->attrs, "job-retain-until-time", IPP_TAG_DATE)) != NULL) { if (until_time > 0) ippSetDate(job->attrs, &attr, 0, ippTimeToDate(until_time)); else ippDeleteAttribute(job->attrs, attr); } else if (until_time > 0) { ippAddDate(job->attrs, IPP_TAG_JOB, "job-retain-until-time", ippTimeToDate(until_time)); } if (username) { _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_CONFIG_CHANGED, "Job retain set by '%s'.", username); } return (true); } // // '_papplJobSetRetain()' - Set the "retain_until" value for a Job. // void _papplJobSetRetain(pappl_job_t *job) // I - Job { ipp_attribute_t *attr; // "job-retain-until[-interval,-time]" attribute if ((attr = ippFindAttribute(job->attrs, "job-retain-until", IPP_TAG_KEYWORD)) != NULL) { // Hold until the specified time period... const char *until = ippGetString(attr, 0, NULL); // Keyword value time_t curtime; // Current time struct tm curdate; // Current date time(&curtime); localtime_r(&curtime, &curdate); if (!strcmp(until, "day-time")) { // Hold to 6am the next morning unless local time is < 6pm. if (curdate.tm_hour < 18) job->retain_until = curtime; else job->retain_until = curtime + ((29 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "evening") || !strcmp(until, "night")) { // Hold to 6pm unless local time is > 6pm or < 6am. if (curdate.tm_hour < 6 || curdate.tm_hour >= 18) job->retain_until = curtime; else job->retain_until = curtime + ((17 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "second-shift")) { // Hold to 4pm unless local time is > 4pm. if (curdate.tm_hour >= 16) job->retain_until = curtime; else job->retain_until = curtime + ((15 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "third-shift")) { // Hold to 12am unless local time is < 8am. if (curdate.tm_hour < 8) job->retain_until = curtime; else job->retain_until = curtime + ((23 - curdate.tm_hour) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } else if (!strcmp(until, "weekend")) { // Hold to weekend unless we are in the weekend. if (curdate.tm_wday == 0 || curdate.tm_wday == 6) job->retain_until = curtime; else job->retain_until = curtime + (((5 - curdate.tm_wday) * 24 + (17 - curdate.tm_hour)) * 60 + 59 - curdate.tm_min) * 60 + 60 - curdate.tm_sec; } } else if ((attr = ippFindAttribute(job->attrs, "job-retain-until-interval", IPP_TAG_INTEGER)) != NULL) { job->retain_until = time(NULL) + ippGetInteger(attr, 0); } else if ((attr = ippFindAttribute(job->attrs, "job-retain-until-time", IPP_TAG_DATE)) != NULL) { job->retain_until = ippDateToTime(ippGetDate(attr, 0)); } } // // '_papplJobSubmitFile()' - Submit a file for printing. // void _papplJobSubmitFile( pappl_job_t *job, // I - Job const char *filename) // I - Filename { _papplRWLockWrite(job); if (!job->format) { // Open the file unsigned char header[8192]; // First 8k bytes of file ssize_t headersize; // Number of bytes read int fd; // File descriptor if ((fd = open(filename, O_RDONLY)) >= 0) { // Auto-type the file using the first N bytes of the file... memset(header, 0, sizeof(header)); headersize = read(fd, (char *)header, sizeof(header)); close(fd); _papplRWLockRead(job->system); if (!memcmp(header, "%PDF", 4)) job->format = "application/pdf"; else if (!memcmp(header, "%!", 2)) job->format = "application/postscript"; else if (!memcmp(header, "\377\330\377", 3) && header[3] >= 0xe0 && header[3] <= 0xef) job->format = "image/jpeg"; else if (!memcmp(header, "\211PNG", 4)) job->format = "image/png"; else if (!memcmp(header, "RaS2PwgR", 8)) job->format = "image/pwg-raster"; else if (!memcmp(header, "UNIRAST", 8)) job->format = "image/urf"; else if (job->system->mime_cb) job->format = (job->system->mime_cb)(header, (size_t)headersize, job->system->mime_cbdata); _papplRWUnlock(job->system); } } if (!job->format) { // Guess the format using the filename extension... const char *ext = strrchr(filename, '.'); // Extension on filename if (!ext) job->format = job->printer->driver_data.format; else if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg")) job->format = "image/jpeg"; else if (!strcmp(ext, ".png")) job->format = "image/png"; else if (!strcmp(ext, ".pwg")) job->format = "image/pwg-raster"; else if (!strcmp(ext, ".urf")) job->format = "image/urf"; else if (!strcmp(ext, ".txt")) job->format = "text/plain"; else if (!strcmp(ext, ".pdf")) job->format = "application/pdf"; else if (!strcmp(ext, ".ps")) job->format = "application/postscript"; else job->format = job->printer->driver_data.format; } // Save the print file information... if ((job->filename = strdup(filename)) != NULL) { if (!job->printer->hold_new_jobs && !(job->state_reasons & PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED)) { // Process the job... job->state = IPP_JSTATE_PENDING; _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_STATE_CHANGED, NULL); _papplRWUnlock(job); _papplRWLockWrite(job->printer); _papplPrinterCheckJobsNoLock(job->printer); _papplRWUnlock(job->printer); } else { // Queue the job... _papplRWUnlock(job); } } else { // Abort the job... size_t dirlen = strlen(job->system->directory); // Length of spool directory job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); _papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_COMPLETED, "Job aborted."); _papplRWUnlock(job); papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to allocate filename."); if (!strncmp(filename, job->system->directory, dirlen) && filename[dirlen] == '/') unlink(filename); _papplRWLockWrite(job->printer); cupsArrayRemove(job->printer->active_jobs, job); cupsArrayAdd(job->printer->completed_jobs, job); _papplRWUnlock(job->printer); if (!job->system->clean_time) job->system->clean_time = time(NULL) + 60; } } // // '_papplPrinterCheckJobsNoLock()' - Check for new jobs to process. // void _papplPrinterCheckJobsNoLock( pappl_printer_t *printer) // I - Printer { pappl_job_t *job; // Current job papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Checking for new jobs to process."); if (printer->device_in_use) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Printer is in use."); return; } else if (printer->processing_job) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Printer is already processing job %d.", printer->processing_job->job_id); return; } else if (printer->is_deleted) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Printer is being deleted."); return; } else if (printer->state == IPP_PSTATE_STOPPED || printer->is_stopped) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Printer is stopped."); return; } // Enumerate the jobs. Since we have a writer (exclusive) lock, we are the // only thread enumerating and can use cupsArrayGetFirst/Last... for (job = (pappl_job_t *)cupsArrayGetFirst(printer->active_jobs); job; job = (pappl_job_t *)cupsArrayGetNext(printer->active_jobs)) { if (job->state == IPP_JSTATE_HELD && job->hold_until && job->hold_until >= time(NULL)) { // Release job when the hold time arrives... _papplRWLockWrite(job); _papplJobReleaseNoLock(job, NULL); _papplRWUnlock(job); } if (job->state == IPP_JSTATE_PENDING) { pthread_t t; // Thread papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Starting job %d.", job->job_id); if (pthread_create(&t, NULL, (void *(*)(void *))_papplJobProcess, job)) { job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); cupsArrayRemove(printer->active_jobs, job); cupsArrayAdd(printer->completed_jobs, job); if (!printer->system->clean_time) printer->system->clean_time = time(NULL) + 60; } else { pthread_detach(t); } break; } } if (!job) papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "No jobs to process at this time."); } // // '_papplPrinterCleanJobsNoLock()' - Clean completed jobs for a printer. // void _papplPrinterCleanJobsNoLock( pappl_printer_t *printer) // I - Printer { time_t cleantime; // Clean time pappl_job_t *job; // Current job int preserved; // Number of preserved jobs if (cupsArrayGetCount(printer->completed_jobs) == 0 || (printer->max_preserved_jobs == 0 && printer->max_completed_jobs <= 0)) return; // Enumerate the jobs. Since we have a writer (exclusive) lock, we are the // only thread enumerating and can use cupsArrayGetFirst/Last... for (job = (pappl_job_t *)cupsArrayGetFirst(printer->completed_jobs), cleantime = time(NULL) - 60, preserved = 0; job; job = (pappl_job_t *)cupsArrayGetNext(printer->completed_jobs)) { if (job->completed && job->completed < cleantime && printer->max_completed_jobs > 0 && (int)cupsArrayGetCount(printer->completed_jobs) > printer->max_completed_jobs) { cupsArrayRemove(printer->completed_jobs, job); cupsArrayRemove(printer->all_jobs, job); } else if (printer->max_preserved_jobs > 0) { if (job->filename) { if ((preserved + 1) > printer->max_preserved_jobs || (job->retain_until && time(NULL) > job->retain_until)) _papplJobRemoveFile(job); else preserved ++; } } else { break; } } } // // 'papplPrinterFindJob()' - Find a job. // // This function finds a job submitted to a printer using its integer ID value. // pappl_job_t * // O - Job or `NULL` if not found papplPrinterFindJob( pappl_printer_t *printer, // I - Printer int job_id) // I - Job ID { pappl_job_t key, // Job search key *job; // Matching job, if any key.job_id = job_id; _papplRWLockRead(printer); job = (pappl_job_t *)cupsArrayFind(printer->all_jobs, &key); _papplRWUnlock(printer); return (job); } // // 'papplSystemCleanJobs()' - Clean out old (completed) jobs. // // This function deletes all old (completed) jobs above the limit set by the // @link papplPrinterSetMaxCompletedJobs@ function. The level may temporarily // exceed this limit if the jobs were completed within the last 60 seconds. // // > Note: This function is normally called automatically from the // > @link papplSystemRun@ function. // void papplSystemCleanJobs( pappl_system_t *system) // I - System { cups_len_t i, // Looping var count; // Number of printers pappl_printer_t *printer; // Current printer _papplRWLockRead(system); // Loop through the printers. // // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the printers array. for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); _papplRWLockWrite(printer); _papplPrinterCleanJobsNoLock(printer); _papplRWUnlock(printer); } system->clean_time = 0; _papplRWUnlock(system); } pappl-1.4.9/pappl/job.h000066400000000000000000000133741476704353100147220ustar00rootroot00000000000000// // Public job header file for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_JOB_H_ # define _PAPPL_JOB_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Constants... // enum pappl_jreason_e // IPP "job-state-reasons" bit values { PAPPL_JREASON_NONE = 0x00000000, // 'none' PAPPL_JREASON_ABORTED_BY_SYSTEM = 0x00000001, // 'aborted-by-system' PAPPL_JREASON_COMPRESSION_ERROR = 0x00000002, // 'compression-error' PAPPL_JREASON_DOCUMENT_FORMAT_ERROR = 0x00000004, // 'document-format-error' PAPPL_JREASON_DOCUMENT_PASSWORD_ERROR = 0x00000008, // 'document-password-error' PAPPL_JREASON_DOCUMENT_PERMISSION_ERROR = 0x00000010, // 'document-permission-error' PAPPL_JREASON_DOCUMENT_UNPRINTABLE_ERROR = 0x00000020,// 'document-unprintable-error' PAPPL_JREASON_ERRORS_DETECTED = 0x00000040, // 'errors-detected' PAPPL_JREASON_JOB_CANCELED_AT_DEVICE = 0x00000080, // 'job-canceled-at-device' PAPPL_JREASON_JOB_CANCELED_BY_USER = 0x00000100, // 'job-canceled-by-user' PAPPL_JREASON_JOB_COMPLETED_SUCCESSFULLY = 0x00000200,// 'job-completed-successfully' PAPPL_JREASON_JOB_COMPLETED_WITH_ERRORS = 0x00000400, // 'job-completed-with-errors' PAPPL_JREASON_JOB_COMPLETED_WITH_WARNINGS = 0x00000800,// 'job-completed-with-warnings' PAPPL_JREASON_JOB_DATA_INSUFFICIENT = 0x00001000, // 'job-data-insufficient' PAPPL_JREASON_JOB_INCOMING = 0x000002000, // 'job-incoming' PAPPL_JREASON_JOB_PRINTING = 0x00004000, // 'job-printing' PAPPL_JREASON_JOB_QUEUED = 0x00008000, // 'job-queued' PAPPL_JREASON_JOB_SPOOLING = 0x00010000, // 'job-spooling' PAPPL_JREASON_PRINTER_STOPPED = 0x00020000, // 'printer-stopped' PAPPL_JREASON_PRINTER_STOPPED_PARTLY = 0x00040000, // 'printer-stopped-partly' PAPPL_JREASON_PROCESSING_TO_STOP_POINT = 0x00080000, // 'processing-to-stop-point' PAPPL_JREASON_QUEUED_IN_DEVICE = 0x00100000, // 'queued-in-device' PAPPL_JREASON_WARNINGS_DETECTED = 0x00200000, // 'warnings-detected' PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED = 0x00400000, // 'job-hold-until-specified' PAPPL_JREASON_JOB_CANCELED_AFTER_TIMEOUT = 0x00800000,// 'job-canceled-after-timeout' PAPPL_JREASON_JOB_FETCHABLE = 0x01000000, // 'job-fetchable' PAPPL_JREASON_JOB_SUSPENDED_FOR_APPROVAL = 0x02000000 // 'job-suspended-for-approval' }; typedef unsigned int pappl_jreason_t; // Bitfield for IPP "job-state-reasons" values // // Functions... // extern void papplJobCancel(pappl_job_t *job) _PAPPL_PUBLIC; extern pappl_pr_options_t *papplJobCreatePrintOptions(pappl_job_t *job, unsigned num_pages, bool color) _PAPPL_PUBLIC; extern pappl_job_t *papplJobCreateWithFile(pappl_printer_t *printer, const char *username, const char *format, const char *job_name, int num_options, cups_option_t *options, const char *filename); extern void papplJobDeletePrintOptions(pappl_pr_options_t *options); extern bool papplJobFilterImage(pappl_job_t *job, pappl_device_t *device, pappl_pr_options_t *options, const unsigned char *pixels, int width, int height, int depth, int ppi, bool smoothing) _PAPPL_PUBLIC; extern ipp_attribute_t *papplJobGetAttribute(pappl_job_t *job, const char *name) _PAPPL_PUBLIC; extern int papplJobGetCopies(pappl_job_t *job) _PAPPL_PUBLIC; extern int papplJobGetCopiesCompleted(pappl_job_t *job) _PAPPL_PUBLIC; extern void *papplJobGetData(pappl_job_t *job) _PAPPL_PUBLIC; extern const char *papplJobGetFilename(pappl_job_t *job) _PAPPL_PUBLIC; extern const char *papplJobGetFormat(pappl_job_t *job) _PAPPL_PUBLIC; extern int papplJobGetID(pappl_job_t *job) _PAPPL_PUBLIC; extern int papplJobGetImpressions(pappl_job_t *job) _PAPPL_PUBLIC; extern int papplJobGetImpressionsCompleted(pappl_job_t *job) _PAPPL_PUBLIC; extern const char *papplJobGetMessage(pappl_job_t *job) _PAPPL_PUBLIC; extern const char *papplJobGetName(pappl_job_t *job) _PAPPL_PUBLIC; extern pappl_printer_t *papplJobGetPrinter(pappl_job_t *job) _PAPPL_PUBLIC; extern pappl_jreason_t papplJobGetReasons(pappl_job_t *job) _PAPPL_PUBLIC; extern ipp_jstate_t papplJobGetState(pappl_job_t *job) _PAPPL_PUBLIC; extern time_t papplJobGetTimeCompleted(pappl_job_t *job) _PAPPL_PUBLIC; extern time_t papplJobGetTimeCreated(pappl_job_t *job) _PAPPL_PUBLIC; extern time_t papplJobGetTimeProcessed(pappl_job_t *job) _PAPPL_PUBLIC; extern const char *papplJobGetUsername(pappl_job_t *job) _PAPPL_PUBLIC; extern bool papplJobHold(pappl_job_t *job, const char *username, const char *until, time_t until_time) _PAPPL_PUBLIC; extern bool papplJobIsCanceled(pappl_job_t *job) _PAPPL_PUBLIC; extern int papplJobOpenFile(pappl_job_t *job, char *fname, size_t fnamesize, const char *directory, const char *ext, const char *mode) _PAPPL_PUBLIC; extern bool papplJobRelease(pappl_job_t *job, const char *username) _PAPPL_PUBLIC; extern void papplJobResume(pappl_job_t *job, pappl_jreason_t remove) _PAPPL_PUBLIC; extern bool papplJobRetain(pappl_job_t *job, const char *username, const char *until, int until_interval, time_t until_time) _PAPPL_PUBLIC; extern void papplJobSetCopiesCompleted(pappl_job_t *job, int add) _PAPPL_PUBLIC; extern void papplJobSetData(pappl_job_t *job, void *data) _PAPPL_PUBLIC; extern void papplJobSetImpressions(pappl_job_t *job, int impressions) _PAPPL_PUBLIC; extern void papplJobSetImpressionsCompleted(pappl_job_t *job, int add) _PAPPL_PUBLIC; extern void papplJobSetMessage(pappl_job_t *job, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(2,3); extern void papplJobSetReasons(pappl_job_t *job, pappl_jreason_t add, pappl_jreason_t remove) _PAPPL_PUBLIC; extern void papplJobSuspend(pappl_job_t *job, pappl_jreason_t add) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_JOB_H_ pappl-1.4.9/pappl/libpappl1.def000066400000000000000000000143321476704353100163360ustar00rootroot00000000000000LIBRARY libpappl1 VERSION 1.2 EXPORTS papplClientGetCSRFToken papplClientGetCookie papplClientGetForm papplClientGetHTTP papplClientGetHostName papplClientGetHostPort papplClientGetJob papplClientGetLoc papplClientGetLocString papplClientGetMethod papplClientGetOperation papplClientGetOptions papplClientGetPrinter papplClientGetRequest papplClientGetResponse papplClientGetSystem papplClientGetURI papplClientGetUsername papplClientHTMLAuthorize papplClientHTMLEscape papplClientHTMLFooter papplClientHTMLHeader papplClientHTMLPrinterFooter papplClientHTMLPrinterHeader papplClientHTMLPrintf papplClientHTMLPuts papplClientHTMLStartForm papplClientIsAuthorized papplClientIsEncrypted papplClientIsValidForm papplClientRespond papplClientRespondIPP papplClientRespondIPPUnsupported papplClientRespondRedirect papplClientSetCookie papplClientSetUsername papplCopyString papplCreateTempFile papplDeviceAddScheme papplDeviceAddScheme2 papplDeviceClose papplDeviceError papplDeviceFlush papplDeviceGetData papplDeviceGetID papplDeviceGetMetrics papplDeviceGetStatus papplDeviceGetSupplies papplDeviceIsSupported papplDeviceList papplDeviceOpen papplDeviceParseID papplDevicePrintf papplDevicePuts papplDeviceRead papplDeviceRemoveScheme papplDeviceRemoveTypes papplDeviceSetData papplDeviceWrite papplGetRand papplGetTempDir papplJobCancel papplJobCreatePrintOptions papplJobCreateWithFile papplJobDeletePrintOptions papplJobFilterImage papplJobGetAttribute papplJobGetCopies papplJobGetCopiesCompleted papplJobGetData papplJobGetFilename papplJobGetFormat papplJobGetID papplJobGetImpressions papplJobGetImpressionsCompleted papplJobGetMessage papplJobGetName papplJobGetPrinter papplJobGetReasons papplJobGetState papplJobGetTimeCompleted papplJobGetTimeCreated papplJobGetTimeProcessed papplJobGetUsername papplJobHold papplJobIsCanceled papplJobOpenFile papplJobRelease papplJobResume papplJobRetain papplJobSetCopiesCompleted papplJobSetData papplJobSetImpressions papplJobSetImpressionsCompleted papplJobSetMessage papplJobSetReasons papplJobSuspend papplLocFormatString papplLocGetDefaultMediaSizeName papplLocGetString papplLog papplLogClient papplLogDevice papplLogJob papplLogPrinter papplMainloop papplMainloopShutdown papplPrinterAddLink papplPrinterCancelAllJobs papplPrinterCloseDevice papplPrinterCreate papplPrinterDelete papplPrinterDisable papplPrinterEnable papplPrinterFindJob papplPrinterGetContact papplPrinterGetDNSSDName papplPrinterGetDeviceID papplPrinterGetDeviceURI papplPrinterGetDriverAttributes papplPrinterGetDriverData papplPrinterGetDriverName papplPrinterGetGeoLocation papplPrinterGetID papplPrinterGetImpressionsCompleted papplPrinterGetLocation papplPrinterGetMaxActiveJobs papplPrinterGetMaxCompletedJobs papplPrinterGetMaxPreservedJobs papplPrinterGetName papplPrinterGetNextJobID papplPrinterGetNumberOfActiveJobs papplPrinterGetNumberOfCompletedJobs papplPrinterGetNumberOfJobs papplPrinterGetOrganization papplPrinterGetOrganizationalUnit papplPrinterGetPath papplPrinterGetPrintGroup papplPrinterGetReasons papplPrinterGetState papplPrinterGetSupplies papplPrinterGetSystem papplPrinterHoldNewJobs papplPrinterIsAcceptingJobs papplPrinterIsDeleted papplPrinterIsHoldingNewJobs papplPrinterIterateActiveJobs papplPrinterIterateAllJobs papplPrinterIterateCompletedJobs papplPrinterOpenDevice papplPrinterOpenFile papplPrinterPause papplPrinterReleaseHeldNewJobs papplPrinterRemoveLink papplPrinterResume papplPrinterSetContact papplPrinterSetDNSSDName papplPrinterSetDriverData papplPrinterSetDriverDefaults papplPrinterSetGeoLocation papplPrinterSetImpressionsCompleted papplPrinterSetLocation papplPrinterSetMaxActiveJobs papplPrinterSetMaxCompletedJobs papplPrinterSetMaxPreservedJobs papplPrinterSetNextJobID papplPrinterSetOrganization papplPrinterSetOrganizationalUnit papplPrinterSetPrintGroup papplPrinterSetReadyMedia papplPrinterSetReasons papplPrinterSetSupplies papplPrinterSetUSB papplSubscriptionCancel papplSubscriptionCreate papplSubscriptionGetEvents papplSubscriptionGetID papplSubscriptionGetJob papplSubscriptionGetPrinter papplSubscriptionGetUsername papplSubscriptionRenew papplSystemAddEvent papplSystemAddLink papplSystemAddListeners papplSystemAddMIMEFilter papplSystemAddResourceCallback papplSystemAddResourceData papplSystemAddResourceDirectory papplSystemAddResourceFile papplSystemAddResourceString papplSystemAddStringsData papplSystemAddStringsFile papplSystemAddTimerCallback papplSystemCleanJobs papplSystemCreate papplSystemCreatePrinters papplSystemDelete papplSystemFindLoc papplSystemFindPrinter papplSystemFindSubscription papplSystemGetAdminGroup papplSystemGetAuthService papplSystemGetContact papplSystemGetDNSSDName papplSystemGetDefaultPrintGroup papplSystemGetDefaultPrinterID papplSystemGetFooterHTML papplSystemGetGeoLocation papplSystemGetHostName papplSystemGetHostPort papplSystemGetHostname papplSystemGetLocation papplSystemGetLogLevel papplSystemGetMaxClients papplSystemGetMaxImageSize papplSystemGetMaxLogSize papplSystemGetMaxSubscriptions papplSystemGetName papplSystemGetNextPrinterID papplSystemGetOptions papplSystemGetOrganization papplSystemGetOrganizationalUnit papplSystemGetPassword papplSystemGetPort papplSystemGetServerHeader papplSystemGetSessionKey papplSystemGetTLSOnly papplSystemGetUUID papplSystemGetVersions papplSystemHashPassword papplSystemIsRunning papplSystemIsShutdown papplSystemIteratePrinters papplSystemLoadState papplSystemMatchDriver papplSystemRemoveLink papplSystemRemoveResource papplSystemRemoveTimerCallback papplSystemRun papplSystemSaveState papplSystemSetAdminGroup papplSystemSetAuthCallback papplSystemSetContact papplSystemSetDNSSDName papplSystemSetDefaultPrintGroup papplSystemSetDefaultPrinterID papplSystemSetEventCallback papplSystemSetFooterHTML papplSystemSetGeoLocation papplSystemSetHostName papplSystemSetHostname papplSystemSetLocation papplSystemSetLogLevel papplSystemSetMIMECallback papplSystemSetMaxClients papplSystemSetMaxImageSize papplSystemSetMaxLogSize papplSystemSetMaxSubscriptions papplSystemSetNetworkCallbacks papplSystemSetNextPrinterID papplSystemSetOperationCallback papplSystemSetOrganization papplSystemSetOrganizationalUnit papplSystemSetPassword papplSystemSetPrinterDrivers papplSystemSetSaveCallback papplSystemSetUUID papplSystemSetVersions papplSystemSetWiFiCallbacks papplSystemShutdown pappl-1.4.9/pappl/link.c000066400000000000000000000107601476704353100150740ustar00rootroot00000000000000// // Link functions for the Printer Application Framework // // Copyright © 2020-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // Local functions... // static int compare_links(_pappl_link_t *a, _pappl_link_t *b); static _pappl_link_t *copy_link(_pappl_link_t *l); static void free_link(_pappl_link_t *l); // // 'papplPrinterAddLink()' - Add a printer link to the navigation header. // // This function adds a navigation link for a printer. The "path_or_url" // argument specifies a absolute path such as "/ipp/print/example/page" or an // absolute URL such as "https://www.example.com/". The "options" argument // specifies where the link is shown and whether the link should redirect an // absolute path to the secure ("https://.../path") web interface. // void papplPrinterAddLink( pappl_printer_t *printer, // I - Printer const char *label, // I - Label string const char *path_or_url, // I - Path or URL pappl_loptions_t options) // I - Link options { _pappl_link_t l; // Link if (!printer || !label || !path_or_url) return; _papplRWLockWrite(printer); if (!printer->links) printer->links = cupsArrayNew((cups_array_cb_t)compare_links, NULL, NULL, 0, (cups_acopy_cb_t)copy_link, (cups_afree_cb_t)free_link); l.label = (char *)label; l.path_or_url = (char *)path_or_url; l.options = options; if (!cupsArrayFind(printer->links, &l)) cupsArrayAdd(printer->links, &l); _papplRWUnlock(printer); } // // 'papplPrinterRemoveLink()' - Remove a printer link from the navigation header. // // This function removes the named link for the printer. // void papplPrinterRemoveLink( pappl_printer_t *printer, // I - Printer const char *label) // I - Label string { _pappl_link_t l; // Link if (!printer || !label) return; _papplRWLockWrite(printer); l.label = (char *)label; cupsArrayRemove(printer->links, &l); _papplRWUnlock(printer); } // // 'papplSystemAddLink()' - Add a link to the navigation header. // // This function adds a navigation link for the system. The "path_or_url" // argument specifies a absolute path such as "/page" or an absolute URL such // as "https://www.example.com/". The "options" argument specifies where the // link is shown and whether the link should redirect an absolute path to the // secure ("https://.../path") web interface. // void papplSystemAddLink( pappl_system_t *system, // I - System const char *label, // I - Label string const char *path_or_url, // I - Path or URL pappl_loptions_t options) // I - Link options { _pappl_link_t l; // Link if (!system || !label || !path_or_url) return; _papplRWLockWrite(system); if (!system->links) system->links = cupsArrayNew((cups_array_cb_t)compare_links, NULL, NULL, 0, (cups_acopy_cb_t)copy_link, (cups_afree_cb_t)free_link); l.label = (char *)label; l.path_or_url = (char *)path_or_url; l.options = options; if (!cupsArrayFind(system->links, &l)) cupsArrayAdd(system->links, &l); _papplRWUnlock(system); } // // 'papplSystemRemoveLink()' - Remove a link from the navigation header. // // This function removes the named link for the system. // void papplSystemRemoveLink( pappl_system_t *system, // I - System const char *label) // I - Label string { _pappl_link_t l; // Link if (!system || !label) return; _papplRWLockWrite(system); l.label = (char *)label; cupsArrayRemove(system->links, &l); _papplRWUnlock(system); } // // 'compare_links()' - Compare two links. // static int // O - Result of comparison compare_links(_pappl_link_t *a, // I - First link _pappl_link_t *b) // I - Second link { return (strcmp(a->label, b->label)); } // // 'copy_link()' - Copy a link. // static _pappl_link_t * // O - New link copy_link(_pappl_link_t *l) // I - Current link { _pappl_link_t *newl = calloc(1, sizeof(_pappl_link_t)); // New link if (newl) { newl->label = strdup(l->label); newl->path_or_url = strdup(l->path_or_url); newl->options = l->options; if (!newl->label || !newl->path_or_url) { free_link(newl); return (NULL); } } return (newl); } // // 'free_link()' - Free the memory used by a link. // static void free_link(_pappl_link_t *l) // I - Link { free(l->label); free(l->path_or_url); free(l); } pappl-1.4.9/pappl/loc-private.h000066400000000000000000000024661476704353100163750ustar00rootroot00000000000000// // Private localization header file for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_LOC_PRIVATE_H_ # define _PAPPL_LOC_PRIVATE_H_ # include "system-private.h" # include "printer-private.h" # include "loc.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Structures... // typedef struct _pappl_locpair_s // String key/text pair { char *key; // Key text char *text; // Localized text } _pappl_locpair_t; struct _pappl_loc_s // Localization data { pthread_rwlock_t rwlock; // Reader/writer lock pappl_system_t *system; // Associated system char *name; // Language/locale name cups_array_t *pairs; // String pairs }; // // Functions... // extern int _papplLocCompare(pappl_loc_t *a, pappl_loc_t *b) _PAPPL_PRIVATE; extern pappl_loc_t *_papplLocCreate(pappl_system_t *system, _pappl_resource_t *r) _PAPPL_PRIVATE; extern void _papplLocDelete(pappl_loc_t *loc) _PAPPL_PRIVATE; extern void _papplLocLoadAll(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplLocPrintf(FILE *fp, const char *message, ...) _PAPPL_FORMAT(2,3) _PAPPL_PRIVATE; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_LOC_PRIVATE_H_ pappl-1.4.9/pappl/loc.c000066400000000000000000000413211476704353100147110ustar00rootroot00000000000000// // Localization functions for the Printer Application Framework // // Copyright © 2022-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "loc-private.h" #include "strings/de_strings.h" #include "strings/en_strings.h" #include "strings/es_strings.h" #include "strings/fr_strings.h" #include "strings/it_strings.h" #include "strings/ja_strings.h" #include "strings/nb-NO_strings.h" #include "strings/pl_strings.h" #include "strings/tr_strings.h" // // Local globals... // static pappl_loc_t loc_default = { PTHREAD_RWLOCK_INITIALIZER, NULL, NULL, NULL }; static pthread_mutex_t loc_mutex = PTHREAD_MUTEX_INITIALIZER; // // Local functions... // static void loc_load_resource(pappl_loc_t *loc, _pappl_resource_t *r); static int locpair_compare(_pappl_locpair_t *a, _pappl_locpair_t *b); static _pappl_locpair_t *locpair_copy(_pappl_locpair_t *pair); static void locpair_free(_pappl_locpair_t *pair); // // '_papplLocCompare()' - Compare two localizations. // int // O - Result of comparison _papplLocCompare(pappl_loc_t *a, // I - First localization pappl_loc_t *b) // I - Second localization { return (strcasecmp(a->name, b->name)); } // // '_papplLocCreate()' - Create/update a localization for the given system and language. // pappl_loc_t * // O - Localization or `NULL` on error _papplLocCreate( pappl_system_t *system, // I - System _pappl_resource_t *r) // I - Resource { pappl_loc_t *loc; // Localization data // See if we already have a localization for this language... if ((loc = papplSystemFindLoc(system, r->language)) == NULL) { // No, allocate memory for a new one... if ((loc = (pappl_loc_t *)calloc(1, sizeof(pappl_loc_t))) == NULL) return (NULL); pthread_rwlock_init(&loc->rwlock, NULL); loc->system = system; loc->name = strdup(r->language); loc->pairs = cupsArrayNew((cups_array_cb_t)locpair_compare, NULL, NULL, 0, (cups_acopy_cb_t)locpair_copy, (cups_afree_cb_t)locpair_free); if (!loc->name || !loc->pairs) { _papplLocDelete(loc); return (NULL); } // Add it to the system... _papplSystemAddLoc(system, loc); } // Load resource... _papplRWLockWrite(loc); loc_load_resource(loc, r); _papplRWUnlock(loc); // Return it... return (loc); } // // '_papplLocDelete()' - Free memory used by a localization. // void _papplLocDelete(pappl_loc_t *loc) // I - Localization { pthread_rwlock_destroy(&loc->rwlock); free(loc->name); cupsArrayDelete(loc->pairs); free(loc); } // // 'papplLocFormatString()' - Format a localized string into a buffer. // // This function formats a localized string into a buffer using the specified // localization data. Numbers are formatted according to the locale and // language used. // const char * // O - Localized formatted string papplLocFormatString( pappl_loc_t *loc, // I - Localization data char *buffer, // I - Output buffer size_t bufsize, // I - Size of output buffer const char *key, // I - Printf-style key string to localize ...) // I - Additional arguments as needed { va_list ap; // Argument pointer // Range-check input if (!buffer || bufsize < 10 || !key) { if (buffer) *buffer = '\0'; return (NULL); } // Format string va_start(ap, key); vsnprintf(buffer, bufsize, papplLocGetString(loc, key), ap); va_end(ap); return (buffer); } // // 'papplLocGetDefaultMediaSizeName()' - Get the default media size name // associated with a locale. // // This function returns the default PWG media size name corresponding to the // current locale. Currently only "na_letter_8.5x11in" or "iso_a4_210x297mm" // are returned. // const char * // O - PWG media size name papplLocGetDefaultMediaSizeName(void) { cups_lang_t *lang; // Default language const char *country; // Country in language... // Range check input... if ((lang = cupsLangDefault()) != NULL) { // Look at locale name for country or language to map to a size... const char *name = cupsLangGetName(lang); // Locale name... if ((country = strchr(name, '_')) != NULL) { // Based on: // // // // Belize (BZ), Canada (CA), Chile (CL), Colombia (CO), Costa Rica (CR), // El Salvador (SV), Guatemala (GT), Mexico (MX), Nicaragua (NI), // Panama (PA), Philippines (PH), Puerto Rico (PR), United States (US), // and Venezuela (VE) all use US Letter these days, everyone else uses // A4... country ++; if (!strcmp(country, "BZ") || !strcmp(country, "CA") || !strcmp(country, "CL") || !strcmp(country, "CO") || !strcmp(country, "CR") || !strcmp(country, "SV") || !strcmp(country, "GT") || !strcmp(country, "MX") || !strcmp(country, "NI") || !strcmp(country, "PA") || !strcmp(country, "PH") || !strcmp(country, "PR") || !strcmp(country, "US") || !strcmp(country, "VE")) return ("na_letter_8.5x11in"); } else if (!strcmp(name, "C") || !strcmp(name, "en")) { // POSIX and generic English are treated as US English locales with US media... return ("na_letter_8.5x11in"); } } // If we get here then it is A4... return ("iso_a4_210x297mm"); } // // 'papplLocGetString()' - Get a localized version of a key string. // // This function looks up the specified key string in the localization data and // returns either the localized value or the original key string if no // localization is available. // const char * // O - Localized text string papplLocGetString(pappl_loc_t *loc, // I - Localization data const char *key) // I - Key text { _pappl_locpair_t search, // Search key *match; // Matching pair, if any // Range check input... if (!loc) return (key); // Look up the key... _papplRWLockRead(loc); search.key = (char *)key; match = cupsArrayFind(loc->pairs, &search); _papplRWUnlock(loc); // Return a string to use... return (match ? match->text : key); } // // '_papplLocLoadAll()' - Load all base localizations. // void _papplLocLoadAll(pappl_system_t *system)// I - System { _pappl_resource_t r; // Temporary resource data memset(&r, 0, sizeof(r)); r.language = "de"; r.data = (const void *)de_strings; _papplLocCreate(system, &r); r.language = "en"; r.data = (const void *)en_strings; _papplLocCreate(system, &r); r.language = "es"; r.data = (const void *)es_strings; _papplLocCreate(system, &r); r.language = "fr"; r.data = (const void *)fr_strings; _papplLocCreate(system, &r); r.language = "it"; r.data = (const void *)it_strings; _papplLocCreate(system, &r); r.language = "ja"; r.data = (const void *)ja_strings; _papplLocCreate(system, &r); r.language = "nb-NO"; r.data = (const void *)nb_NO_strings; _papplLocCreate(system, &r); r.language = "pl"; r.data = (const void *)pl_strings; _papplLocCreate(system, &r); r.language = "tr"; r.data = (const void *)tr_strings; _papplLocCreate(system, &r); } // // '_papplLocPrintf()' - Print a localized string. // void _papplLocPrintf(FILE *fp, // I - Output file const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { va_list ap; // Argument pointer // Load the default message catalog as needed... pthread_mutex_lock(&loc_mutex); if (!loc_default.pairs) { cups_lang_t *lang = cupsLangDefault(); // Default locale/language _pappl_resource_t r; // Dummy resource pthread_rwlock_init(&loc_default.rwlock, NULL); loc_default.name = strdup(cupsLangGetName(lang)); loc_default.pairs = cupsArrayNew((cups_array_cb_t)locpair_compare, NULL, NULL, 0, (cups_acopy_cb_t)locpair_copy, (cups_afree_cb_t)locpair_free); memset(&r, 0, sizeof(r)); if (!strncmp(loc_default.name, "de", 2)) r.data = (const void *)de_strings; else if (!strncmp(loc_default.name, "en", 2)) r.data = (const void *)en_strings; else if (!strncmp(loc_default.name, "es", 2)) r.data = (const void *)es_strings; else if (!strncmp(loc_default.name, "fr", 2)) r.data = (const void *)fr_strings; else if (!strncmp(loc_default.name, "it", 2)) r.data = (const void *)it_strings; else if (!strncmp(loc_default.name, "ja", 2)) r.data = (const void *)ja_strings; else if (!strncmp(loc_default.name, "nb", 2)) r.data = (const void *)nb_NO_strings; else if (!strncmp(loc_default.name, "pl", 2)) r.data = (const void *)pl_strings; else if (!strncmp(loc_default.name, "tr", 2)) r.data = (const void *)tr_strings; if (r.data) loc_load_resource(&loc_default, &r); } pthread_mutex_unlock(&loc_mutex); // Then format the localized message... va_start(ap, message); vfprintf(fp, papplLocGetString(&loc_default, message), ap); putc('\n', fp); va_end(ap); } // // 'loc_load_resource()' - Load a strings resource into a localization. // static void loc_load_resource( pappl_loc_t *loc, // I - Localization data _pappl_resource_t *r) // I - Resource { const char *data, // Pointer to strings data *dataptr; // Pointer into string data char key[1024], // Key string text[1024], // Localized text string *ptr; // Pointer into strings int linenum; // Line number _pappl_locpair_t pair; // New pair if (r->filename) { // Load the resource file... int fd; // File descriptor struct stat fileinfo; // File information ssize_t bytes; // Bytes read if ((fd = open(r->filename, O_RDONLY)) < 0) { papplLog(loc->system, PAPPL_LOGLEVEL_ERROR, "Unable to open '%s' (%s): %s", r->path, r->filename, strerror(errno)); return; } if (fstat(fd, &fileinfo)) { papplLog(loc->system, PAPPL_LOGLEVEL_ERROR, "Unable to stat '%s' (%s): %s", r->path, r->filename, strerror(errno)); close(fd); return; } if ((ptr = malloc((size_t)(fileinfo.st_size + 1))) == NULL) { papplLog(loc->system, PAPPL_LOGLEVEL_ERROR, "Unable to allocate %u bytes for '%s' (%s): %s", (unsigned)(fileinfo.st_size + 1), r->path, r->filename, strerror(errno)); close(fd); return; } if ((bytes = read(fd, ptr, (size_t)fileinfo.st_size)) < 0) { papplLog(loc->system, PAPPL_LOGLEVEL_ERROR, "Unable to read '%s' (%s): %s", r->path, r->filename, strerror(errno)); close(fd); free(ptr); return; } else if (bytes < (ssize_t)fileinfo.st_size) { // Short read, shouldn't happen but warn if it does... papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Only read %u of %u bytes of '%s' (%s).", (unsigned)bytes, (unsigned)fileinfo.st_size, r->path, r->filename); } close(fd); ptr[bytes] = '\0'; data = ptr; } else { // Use in-memory strings data... data = (const char *)r->data; } // Scan the in-memory strings data and add key/text pairs... // // Format of strings files is: // // "key" = "text"; pair.key = key; pair.text = text; for (dataptr = data, linenum = 1; *dataptr; dataptr ++) { // Skip leading whitespace... while (*dataptr && isspace(*dataptr & 255)) { if (*dataptr == '\n') linenum ++; dataptr ++; } if (!*dataptr) { // End of string... break; } else if (*dataptr == '/' && dataptr[1] == '*') { // Start of C-style comment... for (dataptr += 2; *dataptr; dataptr ++) { if (*dataptr == '*' && dataptr[1] == '/') { dataptr += 2; break; } else if (*dataptr == '\n') linenum ++; } if (!*dataptr) break; } else if (*dataptr != '\"') { // Something else we don't recognize... papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Syntax error on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } // Parse key string... dataptr ++; for (ptr = key; *dataptr && *dataptr != '\"'; dataptr ++) { if (*dataptr == '\\' && dataptr[1]) { // Escaped character... int ch; // Character dataptr ++; if (*dataptr == '\\' || *dataptr == '\'' || *dataptr == '\"') { ch = *dataptr; } else if (*dataptr == 'n') { ch = '\n'; } else if (*dataptr == 'r') { ch = '\r'; } else if (*dataptr == 't') { ch = '\t'; } else if (*dataptr >= '0' && *dataptr <= '3' && dataptr[1] >= '0' && dataptr[1] <= '7' && dataptr[2] >= '0' && dataptr[2] <= '7') { // Octal escape ch = ((*dataptr - '0') << 6) | ((dataptr[1] - '0') << 3) | (dataptr[2] - '0'); dataptr += 2; } else { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Invalid escape in key string on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } if (ptr < (key + sizeof(key) - 1)) *ptr++ = (char)ch; } else if (ptr < (key + sizeof(key) - 1)) { *ptr++ = *dataptr; } } if (!*dataptr) { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Unterminated key string on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } dataptr ++; *ptr = '\0'; // Parse separator... while (*dataptr && isspace(*dataptr & 255)) { if (*dataptr == '\n') linenum ++; dataptr ++; } if (*dataptr != '=') { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Missing separator on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } dataptr ++; while (*dataptr && isspace(*dataptr & 255)) { if (*dataptr == '\n') linenum ++; dataptr ++; } if (*dataptr != '\"') { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Missing text string on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } // Parse text string... dataptr ++; for (ptr = text; *dataptr && *dataptr != '\"'; dataptr ++) { if (*dataptr == '\\') { // Escaped character... int ch; // Character dataptr ++; if (*dataptr == '\\' || *dataptr == '\'' || *dataptr == '\"') { ch = *dataptr; } else if (*dataptr == 'n') { ch = '\n'; } else if (*dataptr == 'r') { ch = '\r'; } else if (*dataptr == 't') { ch = '\t'; } else if (*dataptr >= '0' && *dataptr <= '3' && dataptr[1] >= '0' && dataptr[1] <= '7' && dataptr[2] >= '0' && dataptr[2] <= '7') { // Octal escape ch = ((*dataptr - '0') << 6) | ((dataptr[1] - '0') << 3) | (dataptr[2] - '0'); dataptr += 2; } else { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Invalid escape in text string on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } if (ptr < (text + sizeof(text) - 1)) *ptr++ = (char)ch; } else if (ptr < (text + sizeof(text) - 1)) { *ptr++ = *dataptr; } } if (!*dataptr) { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Unterminated text string on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } dataptr ++; *ptr = '\0'; // Look for terminator, then add the pair... if (*dataptr != ';') { papplLog(loc->system, PAPPL_LOGLEVEL_WARN, "Missing terminator on line %d of '%s' (%s).", linenum, r->path, r->filename ? r->filename : "in-memory"); break; } dataptr ++; if (!cupsArrayFind(loc->pairs, &pair)) cupsArrayAdd(loc->pairs, &pair); } if (data != r->data) free((void *)data); } // // 'locpair_compare()' - Compare the keys of two key/text pairs. // static int // O - Result of comparison locpair_compare(_pappl_locpair_t *a, // I - First key/text pair _pappl_locpair_t *b) // I - Second key/text pair { return (strcmp(a->key, b->key)); } // // 'locpair_copy()' - Copy a key/text pair. // static _pappl_locpair_t * // O - Copy of pair locpair_copy(_pappl_locpair_t *pair) // I - Pair to copy { _pappl_locpair_t *npair; // New pair // Allocate a new pair... if ((npair = calloc(1, sizeof(_pappl_locpair_t))) != NULL) { // Duplicate the strings... npair->key = strdup(pair->key); npair->text = strdup(pair->text); if (!npair->key || !npair->text) { // Wasn't able to allocate everything... locpair_free(npair); npair = NULL; } } return (npair); } // // 'locpair_free()' - Free memory used by a key/text pair. // static void locpair_free(_pappl_locpair_t *pair) // I - Pair { free(pair->key); free(pair->text); free(pair); } pappl-1.4.9/pappl/loc.h000066400000000000000000000013461476704353100147210ustar00rootroot00000000000000// // Public localization header file for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_LOC_H_ # define _PAPPL_LOC_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Functions... // extern const char *papplLocFormatString(pappl_loc_t *loc, char *buffer, size_t bufsize, const char *key, ...) _PAPPL_FORMAT(4,5) _PAPPL_PUBLIC; extern const char *papplLocGetDefaultMediaSizeName(void) _PAPPL_PUBLIC; extern const char *papplLocGetString(pappl_loc_t *loc, const char *key) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_LOC_H_ pappl-1.4.9/pappl/log-private.h000066400000000000000000000010761476704353100163750ustar00rootroot00000000000000// // Private log header file for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_LOG_PRIVATE_H_ # define _PAPPL_LOG_PRIVATE_H_ # include "base-private.h" # include "log.h" // // Functions... // extern void _papplLogAttributes(pappl_client_t *client, const char *title, ipp_t *ipp, bool is_response) _PAPPL_PRIVATE; extern void _papplLogOpenNoLock(pappl_system_t *system) _PAPPL_PRIVATE; #endif // !_PAPPL_LOG_PRIVATE_H_ pappl-1.4.9/pappl/log.c000066400000000000000000000451771476704353100147320ustar00rootroot00000000000000// // Logging functions for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "client-private.h" #include "job-private.h" #include "log-private.h" #include "printer-private.h" #include "system-private.h" #include #if !_WIN32 # include #endif // !_WIN32 // // Local functions... // static void rotate_log_no_lock(pappl_system_t *system); static void write_log_no_lock(pappl_system_t *system, pappl_loglevel_t level, const char *message, va_list ap); // // Local globals... // #if !_WIN32 static const int syslevels[] = // Mapping of log levels to syslog { LOG_DEBUG | LOG_PID | LOG_LPR, LOG_INFO | LOG_PID | LOG_LPR, LOG_WARNING | LOG_PID | LOG_LPR, LOG_ERR | LOG_PID | LOG_LPR, LOG_CRIT | LOG_PID | LOG_LPR }; #endif // !_WIN32 // // 'papplLog()' - Log a message for the system. // // This function sends a message to the system's log file. The "level" argument // specifies the urgency of the message: // // - `PAPPL_LOGLEVEL_DEBUG`: A debugging message. // - `PAPPL_LOGLEVEL_ERROR`: An error message. // - `PAPPL_LOGLEVEL_FATAL`: A fatal error message. // - `PAPPL_LOGLEVEL_INFO`: An informational message. // - `PAPPL_LOGLEVEL_WARN`: A warning message. // // The "message" argument specifies a `printf`-style format string. Values // logged using the "%c" and "%s" format specifiers are sanitized to not // contain control characters. // void papplLog(pappl_system_t *system, // I - System pappl_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { va_list ap; // Pointer to arguments if (!message) return; if (!system) { if (level >= PAPPL_LOGLEVEL_WARN) { va_start(ap, message); vfprintf(stderr, message, ap); putc('\n', stderr); va_end(ap); } return; } if (level < papplSystemGetLogLevel(system)) return; va_start(ap, message); #if !_WIN32 if (system->log_is_syslog) { vsyslog(syslevels[level], message, ap); } else #endif // !_WIN32 { pthread_mutex_lock(&system->log_mutex); write_log_no_lock(system, level, message, ap); pthread_mutex_unlock(&system->log_mutex); } va_end(ap); } // // '_papplLogAttributes()' - Log IPP attributes for a client connection. // // This function logs the IPP attributes sent or received on a client // connection at the `PAPPL_LOGLEVEL_DEBUG` (debug) log level. // void _papplLogAttributes( pappl_client_t *client, // I - Client const char *title, // I - Title for attributes ipp_t *ipp, // I - IPP message bool is_response) // I - `true` if a response, `false` if a request { int major, // Major version number minor; // Minor version number ipp_attribute_t *attr; // Current attribute ipp_tag_t group = IPP_TAG_ZERO; // Current group const char *name; // Name char value[1024]; // Value if (!client || !title || !ipp) return; if (papplSystemGetLogLevel(client->system) > PAPPL_LOGLEVEL_DEBUG) return; major = ippGetVersion(ipp, &minor); if (is_response) papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s response: IPP/%d.%d request-id=%d, status-code=%s", title, major, minor, ippGetRequestId(ipp), ippErrorString(ippGetStatusCode(ipp))); else papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s request: IPP/%d.%d request-id=%d", title, major, minor, ippGetRequestId(ipp)); for (attr = ippGetFirstAttribute(ipp); attr; attr = ippGetNextAttribute(ipp)) { if ((name = ippGetName(attr)) == NULL) { group = IPP_TAG_ZERO; continue; } if (ippGetGroupTag(attr) != group) { group = ippGetGroupTag(attr); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s %s: %s", title, is_response ? "response" : "request", ippTagString(group)); } ippAttributeString(attr, value, sizeof(value)); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s %s: %s %s%s %s", title, is_response ? "response" : "request", name, ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)), value); } } // // 'papplLogClient()' - Log a message for a client. // // This function sends a client message to the system's log file. The "level" // argument specifies the urgency of the message: // // - `PAPPL_LOGLEVEL_DEBUG`: A debugging message. // - `PAPPL_LOGLEVEL_ERROR`: An error message. // - `PAPPL_LOGLEVEL_FATAL`: A fatal error message. // - `PAPPL_LOGLEVEL_INFO`: An informational message. // - `PAPPL_LOGLEVEL_WARN`: A warning message. // // The "message" argument specifies a `printf`-style format string. Values // logged using the "%c" and "%s" format specifiers are sanitized to not // contain control characters. // void papplLogClient( pappl_client_t *client, // I - Client pappl_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char cmessage[1024]; // Message with client prefix va_list ap; // Pointer to arguments pappl_system_t *system; // System if (!client || !message) return; system = client->system; if (level < papplSystemGetLogLevel(system)) return; snprintf(cmessage, sizeof(cmessage), "[Client %d] %s", client->number, message); va_start(ap, message); #if !_WIN32 if (system->log_is_syslog) { vsyslog(syslevels[level], cmessage, ap); } else #endif // !_WIN32 { pthread_mutex_lock(&system->log_mutex); write_log_no_lock(system, level, cmessage, ap); pthread_mutex_unlock(&system->log_mutex); } va_end(ap); } // // 'papplLogDevice()' - Log a device error for the system... // // This function sends a device error message to the system's log file. // void papplLogDevice( const char *message, // I - Message void *data) // I - System { pappl_system_t *system = (pappl_system_t *)data; // System papplLog(system, PAPPL_LOGLEVEL_ERROR, "[Device] %s", message); } // // 'papplLogJob()' - Log a message for a job. // // This function sends a job message to the system's log file. The "level" // argument specifies the urgency of the message: // // - `PAPPL_LOGLEVEL_DEBUG`: A debugging message. // - `PAPPL_LOGLEVEL_ERROR`: An error message. // - `PAPPL_LOGLEVEL_FATAL`: A fatal error message. // - `PAPPL_LOGLEVEL_INFO`: An informational message. // - `PAPPL_LOGLEVEL_WARN`: A warning message. // // The "message" argument specifies a `printf`-style format string. Values // logged using the "%c" and "%s" format specifiers are sanitized to not // contain control characters. // void papplLogJob( pappl_job_t *job, // I - Job pappl_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char jmessage[1024]; // Message with job prefix va_list ap; // Pointer to arguments pappl_system_t *system; // System if (!job || !message) return; system = job->system; if (level < papplSystemGetLogLevel(system)) return; snprintf(jmessage, sizeof(jmessage), "[Job %d] %s", job->job_id, message); va_start(ap, message); #if !_WIN32 if (system->log_is_syslog) { vsyslog(syslevels[level], jmessage, ap); } else #endif // !_WIN32 { pthread_mutex_lock(&system->log_mutex); write_log_no_lock(system, level, jmessage, ap); pthread_mutex_unlock(&system->log_mutex); } va_end(ap); } // // '_papplLogOpenNoLock()' - Open the log file // void _papplLogOpenNoLock( pappl_system_t *system) // I - System { // Open the log file... if (system->log_is_syslog) { // Log to syslog... system->log_fd = -1; } else if (!strcmp(system->log_file, "-")) { // Log to stderr... system->log_fd = 2; } else { int oldfd = system->log_fd; // Old log file descriptor // Log to a file... if ((system->log_fd = open(system->log_file, O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW | O_CLOEXEC, 0600)) < 0) { // Fallback to logging to stderr if we can't open the log file... perror(system->log_file); system->log_fd = 2; } // Close any old file... if (oldfd != -1) close(oldfd); } // Log the system status information if (system->log_level <= PAPPL_LOGLEVEL_INFO && !system->log_is_syslog) { struct timeval curtime; // Current time struct tm curdate; // Current date char message[1024]; // First log message gettimeofday(&curtime, NULL); #if _WIN32 time_t curtemp = (time_t)curtime.tv_sec; gmtime_s(&curdate, &curtemp); #else gmtime_r(&curtime.tv_sec, &curdate); #endif // _WIN32 snprintf(message, sizeof(message), "I [%04d-%02d-%02dT%02d:%02d:%02d.%03dZ] Starting log, system up %ld second(s), %u printer(s), listening for connections on '%s:%d' from up to %u clients.\n", curdate.tm_year + 1900, curdate.tm_mon + 1, curdate.tm_mday, curdate.tm_hour, curdate.tm_min, curdate.tm_sec, (int)(curtime.tv_usec / 1000), (long)(time(NULL) - system->start_time), (unsigned)cupsArrayGetCount(system->printers), system->hostname, system->port, (unsigned)system->max_clients); write(system->log_fd, message, strlen(message)); } } // // 'papplLogPrinter()' - Log a message for a printer. // // This function sends a printer message to the system's log file. The "level" // argument specifies the urgency of the message: // // - `PAPPL_LOGLEVEL_DEBUG`: A debugging message. // - `PAPPL_LOGLEVEL_ERROR`: An error message. // - `PAPPL_LOGLEVEL_FATAL`: A fatal error message. // - `PAPPL_LOGLEVEL_INFO`: An informational message. // - `PAPPL_LOGLEVEL_WARN`: A warning message. // // The "message" argument specifies a `printf`-style format string. Values // logged using the "%c" and "%s" format specifiers are sanitized to not // contain control characters. // void papplLogPrinter( pappl_printer_t *printer, // I - Printer pappl_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char pmessage[1024], // Message with printer prefix *pptr, // Pointer into prefix *nameptr; // Pointer into printer name va_list ap; // Pointer to arguments pappl_system_t *system; // System if (!printer || !message) return; system = printer->system; if (level < papplSystemGetLogLevel(system)) return; // Prefix the message with "[Printer foo]", making sure to not insert any // printf format specifiers. papplCopyString(pmessage, "[Printer ", sizeof(pmessage)); for (pptr = pmessage + 9, nameptr = printer->name; *nameptr && pptr < (pmessage + 200); pptr ++) { if (*nameptr == '%') *pptr++ = '%'; *pptr = *nameptr++; } *pptr++ = ']'; *pptr++ = ' '; papplCopyString(pptr, message, sizeof(pmessage) - (size_t)(pptr - pmessage)); // Write the log message... va_start(ap, message); #if !_WIN32 if (system->log_is_syslog) { vsyslog(syslevels[level], pmessage, ap); } else #endif // !_WIN32 { pthread_mutex_lock(&system->log_mutex); write_log_no_lock(system, level, pmessage, ap); pthread_mutex_unlock(&system->log_mutex); } va_end(ap); } // // 'rotate_log_no_lock()' - Rotate the log file... // static void rotate_log_no_lock( pappl_system_t *system) // I - System { struct stat loginfo; // Lof file information // Re-check whether we need to rotate the log file... if (!fstat(system->log_fd, &loginfo) && loginfo.st_size >= (off_t)system->log_max_size) { // Rename existing log file to "xxx.O" char backname[1024]; // Backup log filename #if _WIN32 // Windows doesn't allow an open file to be renamed... close(system->log_fd); system->log_fd = -1; #endif // _WIN32 snprintf(backname, sizeof(backname), "%s.O", system->log_file); unlink(backname); rename(system->log_file, backname); _papplLogOpenNoLock(system); } } // // 'write_log_no_lock()' - Write a line to the log file... // static void write_log_no_lock( pappl_system_t *system, // I - System pappl_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string va_list ap) // I - Pointer to additional arguments { struct stat loginfo; // Log file information char buffer[2048], // Output buffer *bufptr, // Pointer into buffer *bufend; // Pointer to end of buffer struct timeval curtime; // Current time struct tm curdate; // Current date char prefix; // Message prefix static const char *prefixes = "DIWEF";// Message prefixes const char *sval; // String value char size, // Size character (h, l, L) type; // Format type character int width, // Width of field prec; // Number of characters of precision char tformat[100], // Temporary format string for sprintf() *tptr; // Pointer into temporary format // Each log line starts with a standard prefix of log level and date/time... gettimeofday(&curtime, NULL); #if _WIN32 time_t curtemp = (time_t)curtime.tv_sec; gmtime_s(&curdate, &curtemp); #else gmtime_r(&curtime.tv_sec, &curdate); #endif // _WIN32 if (level < PAPPL_LOGLEVEL_DEBUG) prefix = 'd'; else if (level > PAPPL_LOGLEVEL_FATAL) prefix = 'f'; else prefix = prefixes[level]; snprintf(buffer, sizeof(buffer), "%c [%04d-%02d-%02dT%02d:%02d:%02d.%03dZ] ", prefix, curdate.tm_year + 1900, curdate.tm_mon + 1, curdate.tm_mday, curdate.tm_hour, curdate.tm_min, curdate.tm_sec, (int)(curtime.tv_usec / 1000)); bufptr = buffer + 29; // Skip level/date/time bufend = buffer + sizeof(buffer) - 1; // Leave room for newline on end // Then format the message line using printf format sequences... while (*message && bufptr < bufend) { if (*message == '%' && message[1]) { tptr = tformat; *tptr++ = *message++; if (*message == '%') { *bufptr++ = *message++; continue; } else if (strchr(" -+#\'", *message)) *tptr++ = *message++; if (*message == '*') { // Get width from argument... message ++; width = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width); tptr += strlen(tptr); } else { width = 0; while (isdigit(*message & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *message; width = width * 10 + *message++ - '0'; } } if (*message == '.') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *message; message ++; if (*message == '*') { // Get precision from argument... message ++; prec = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec); tptr += strlen(tptr); } else { prec = 0; while (isdigit(*message & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *message; prec = prec * 10 + *message++ - '0'; } } } if (*message == 'l' && message[1] == 'l') { size = 'L'; if (tptr < (tformat + sizeof(tformat) - 2)) { *tptr++ = 'l'; *tptr++ = 'l'; } message += 2; } else if (*message == 'h' || *message == 'l' || *message == 'L') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *message; size = *message++; } else size = 0; if (!*message) break; if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *message; type = *message++; *tptr = '\0'; switch (type) { case 'E' : // Floating point formats case 'G' : case 'e' : case 'f' : case 'g' : snprintf(bufptr, (size_t)(bufend - bufptr), tformat, va_arg(ap, double)); bufptr += strlen(bufptr); break; case 'B' : // Integer formats case 'X' : case 'b' : case 'd' : case 'i' : case 'o' : case 'u' : case 'x' : # ifdef HAVE_LONG_LONG if (size == 'L') snprintf(bufptr, (size_t)(bufend - bufptr), tformat, va_arg(ap, long long)); else # endif // HAVE_LONG_LONG if (size == 'l') snprintf(bufptr, (size_t)(bufend - bufptr), tformat, va_arg(ap, long)); else snprintf(bufptr, (size_t)(bufend - bufptr), tformat, va_arg(ap, int)); bufptr += strlen(bufptr); break; case 'p' : // Log a pointer snprintf(bufptr, (size_t)(bufend - bufptr), "%p", va_arg(ap, void *)); bufptr += strlen(bufptr); break; case 'c' : // Character or character array if (width <= 1) { *bufptr++ = (char)va_arg(ap, int); } else { if ((bufend - bufptr) < width) width = (int)(bufend - bufptr); memcpy(bufptr, va_arg(ap, char *), (size_t)width); bufptr += width; } break; case 's' : // Log a string if ((sval = va_arg(ap, char *)) == NULL) sval = "(null)"; while (*sval && bufptr < bufend) { int val = (*sval++) & 255; if (val < ' ' || val == 0x7f || val == '\\' || val == '\'' || val == '\"') { // Escape control and special characters in the string... if (bufptr > (bufend - 4)) break; *bufptr++ = '\\'; if (val == '\\') *bufptr++ = '\\'; else if (val == '\'') *bufptr++ = '\''; else if (val == '\"') *bufptr++ = '\"'; else if (val == '\n') *bufptr++ = 'n'; else if (val == '\r') *bufptr++ = 'r'; else if (val == '\t') *bufptr++ = 't'; else { // Use octal escape for other control characters... *bufptr++ = (char)('0' + (val / 64)); *bufptr++ = (char)('0' + ((val / 8) & 7)); *bufptr++ = (char)('0' + (val & 7)); } } else *bufptr++ = (char)val; } break; default : // Something else we don't support papplCopyString(bufptr, tformat, (size_t)(bufend - bufptr)); bufptr += strlen(bufptr); break; } } else *bufptr++ = *message++; } // Add a newline... *bufptr++ = '\n'; // Rotate log as needed... if (system->log_max_size > 0 && !fstat(system->log_fd, &loginfo) && loginfo.st_size >= (off_t)system->log_max_size) rotate_log_no_lock(system); // Write the log entry... write(system->log_fd, buffer, (size_t)(bufptr - buffer)); } pappl-1.4.9/pappl/log.h000066400000000000000000000026531476704353100147270ustar00rootroot00000000000000// // Logging header file for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_LOG_H_ # define _PAPPL_LOG_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Constants... // typedef enum pappl_loglevel_e // Log levels { PAPPL_LOGLEVEL_UNSPEC = -1, // Not specified PAPPL_LOGLEVEL_DEBUG, // Debug message PAPPL_LOGLEVEL_INFO, // Informational message PAPPL_LOGLEVEL_WARN, // Warning message PAPPL_LOGLEVEL_ERROR, // Error message PAPPL_LOGLEVEL_FATAL // Fatal message } pappl_loglevel_t; // // Functions... // extern void papplLog(pappl_system_t *system, pappl_loglevel_t level, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(3,4); extern void papplLogClient(pappl_client_t *client, pappl_loglevel_t level, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(3, 4); extern void papplLogDevice(const char *message, void *data) _PAPPL_PUBLIC; extern void papplLogJob(pappl_job_t *job, pappl_loglevel_t level, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(3, 4); extern void papplLogPrinter(pappl_printer_t *printer, pappl_loglevel_t level, const char *message, ...) _PAPPL_PUBLIC _PAPPL_FORMAT(3, 4); # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_LOG_H_ pappl-1.4.9/pappl/lookup.c000066400000000000000000000040461476704353100154500ustar00rootroot00000000000000// // Lookup functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "base-private.h" // // '_papplLookupString()' - Lookup the string value for a bit. // const char * // O - Keyword or `NULL` _papplLookupString( unsigned value, // I - Bit value size_t num_strings, // I - Number of strings const char * const *strings) // I - Strings { size_t i; // Looking var unsigned bit; // Current bit for (i = 0, bit = 1; i < num_strings; i ++, bit *= 2) { if (bit == value) return (strings[i]); } return (NULL); } // // '_papplLookupStrings()' - Lookup the string values for all set bits. // size_t // O - number of keywords returned _papplLookupStrings( unsigned value, // I - Bitfield value size_t max_keywords, // I - Max number of keywords to return char *keywords[], // I - Array of char * to be assigned and returned size_t num_strings, // I - Number of strings const char * const *strings) // I - Strings { size_t i; // Looking var unsigned bit; // Current bit size_t counter = 0; // Counter to be returned for (i = 0, bit = 1; i < num_strings && counter < max_keywords; i ++, bit *= 2) { if (value & bit) { keywords[counter] = (char*)strings[i]; counter++; } } return counter; } // // '_papplLookupValue()' - Lookup the bit value for a string. // unsigned // O - Bit value or `0` _papplLookupValue( const char *value, // I - Keyword value size_t num_strings, // I - Number of strings const char * const *strings) // I - Strings { size_t i; // Looking var unsigned bit; // Current bit if (!value) return (0); for (i = 0, bit = 1; i < num_strings; i ++, bit *= 2) { if (!strcmp(strings[i], value)) return (bit); } return (0); } pappl-1.4.9/pappl/mainloop-private.h000066400000000000000000000074761476704353100174440ustar00rootroot00000000000000// // Private mainloop header file for the Printer Application Framework // // Copyright © 2020-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_MAINLOOP_PRIVATE_H_ # define _PAPPL_MAINLOOP_PRIVATE_H_ # include "mainloop.h" # include "base-private.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Globals... // extern char *_papplMainloopPath _PAPPL_PRIVATE; // // Functions... // extern int _papplMainloopAddPrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopAutoAddPrinters(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopCancelJob(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopDeletePrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopGetSetDefaultPrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopModifyPrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopPausePrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopResumePrinter(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopRunServer(const char *base_name, const char *version, const char *footer_html, cups_len_t num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_driver_cb_t driver_cb, cups_len_t num_options, cups_option_t **options, pappl_ml_system_cb_t system_cb, void *data) _PAPPL_PRIVATE; extern int _papplMainloopShowDevices(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopShowDrivers(const char *base_name, cups_len_t num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_driver_cb_t driver_cb, cups_len_t num_options, cups_option_t *options, pappl_ml_system_cb_t system_cb, void *data) _PAPPL_PRIVATE; extern int _papplMainloopShowJobs(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopShowOptions(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopShowPrinters(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopShowStatus(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopShutdownServer(const char *base_name, cups_len_t num_options, cups_option_t *options) _PAPPL_PRIVATE; extern int _papplMainloopSubmitJob(const char *base_name, cups_len_t num_options, cups_option_t *options, cups_len_t num_files, char **files) _PAPPL_PRIVATE; extern void _papplMainloopAddOptions(ipp_t *request, cups_len_t num_options, cups_option_t *options, ipp_t *supported) _PAPPL_PRIVATE; extern void _papplMainloopAddPrinterURI(ipp_t *request, const char *printer_name, char *resource,size_t rsize) _PAPPL_PRIVATE; extern http_t *_papplMainloopConnect(const char *base_name, bool auto_start) _PAPPL_PRIVATE; extern http_t *_papplMainloopConnectURI(const char *base_name, const char *printer_uri, char *resource, size_t rsize) _PAPPL_PRIVATE; extern char *_papplMainloopGetDefaultPrinter(http_t *http, char *buffer, size_t bufsize) _PAPPL_PRIVATE; extern char *_papplMainloopGetServerPath(const char *base_name, uid_t uid, char *buffer, size_t bufsize) _PAPPL_PRIVATE; extern int _papplMainloopGetServerPort(const char *base_name) _PAPPL_PRIVATE; # ifdef __cplusplus } # endif // __cplusplus # endif // !_PAPPL_MAIN_PRIVATE_H pappl-1.4.9/pappl/mainloop-subcommands.c000066400000000000000000002001461476704353100202650ustar00rootroot00000000000000// // Standard papplMainloop sub-commands for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // # include "pappl-private.h" # ifdef __APPLE__ # include # include # endif // __APPLE__ // // Local globals // static pthread_mutex_t mainloop_mutex = PTHREAD_MUTEX_INITIALIZER; // Mutex for system object static pappl_system_t *mainloop_system = NULL; // Current system object // // Local functions // static char *copy_stdin(const char *base_name, char *name, size_t namesize); static pappl_system_t *default_system_cb(const char *base_name, int num_options, cups_option_t *options, void *data); static ipp_t *get_printer_attributes(http_t *http, const char *printer_uri, const char *printer_name, const char *resource, cups_len_t num_requested, const char * const *requested); static char *get_value(ipp_attribute_t *attr, const char *name, cups_len_t element, char *buffer, size_t bufsize); static cups_len_t load_options(const char *filename, cups_len_t num_options, cups_option_t **options); static void print_option(ipp_t *response, const char *name); #if _WIN32 static void save_server_port(const char *base_name, int port); #endif // _WIN32 // // '_papplMainloopAddPrinter()' - Add a printer. // int // O - Exit status _papplMainloopAddPrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // Create-Printer request const char *device_uri, // Device URI *driver_name, // Name of driver *printer_name, // Name of printer *printer_uri; // Printer URI // Get required values... device_uri = cupsGetOption("smi55357-device-uri", num_options, options); driver_name = cupsGetOption("smi55357-driver", num_options, options); printer_name = cupsGetOption("printer-name", num_options, options); if (!device_uri || !driver_name || !printer_name) { if (!printer_name) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-d PRINTER'."), base_name); if (!driver_name) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-m DRIVER-NAME'."), base_name); if (!device_uri) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-v DEVICE-URI'."), base_name); return (1); } if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { char resource[1024]; // Resource path // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } // Send a Create-Printer request to the server... request = ippNewRequest(IPP_OP_CREATE_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "printer-service-type", NULL, "print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "smi55357-driver", NULL, driver_name); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "smi55357-device-uri", NULL, device_uri); ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, printer_name); _papplMainloopAddOptions(request, num_options, options, NULL); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to add printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopAutoAddPrinters()' - Automatically add printers. // int // O - Exit status _papplMainloopAutoAddPrinters( const char *base_name, // I - Basename of application cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // IPP request (void)num_options; (void)options; // Try connecting to server... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); // Send a PAPPL-Create-Printers request... request = ippNewRequest(IPP_OP_PAPPL_CREATE_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); return (0); } // // '_papplMainloopCancelJob()' - Cancel job(s). // int // O - Exit status _papplMainloopCancelJob( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name = NULL; // Printer name char default_printer[256], // Default printer resource[1024]; // Resource path http_t *http; // Server connection ipp_t *request; // IPP request const char *value; // Option value int job_id = 0; // job-id if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to the server and get the destination printer... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = _papplMainloopGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: No default printer available."), base_name); httpClose(http); return (1); } } } // Figure out which job(s) to cancel... if (cupsGetOption("cancel-all", num_options, options)) { request = ippNewRequest(IPP_OP_CANCEL_MY_JOBS); } else if ((value = cupsGetOption("job-id", num_options, options)) != NULL) { char *end; // End of value request = ippNewRequest(IPP_OP_CANCEL_JOB); job_id = (int)strtol(value, &end, 10); if (job_id < 1 || errno == ERANGE || *end) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Bad job ID."), base_name); httpClose(http); return (1); } } else request = ippNewRequest(IPP_OP_CANCEL_CURRENT_JOB); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); if (job_id) ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to cancel job: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopDeletePrinter()' - Delete a printer. // int // O - Exit status _papplMainloopDeletePrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char resource[1024]; // Resource path int printer_id; // printer-id value static const char *pattrs = "printer-id"; // Requested attributes // Connect to/start up the server and get the destination printer... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-d PRINTER'."), base_name); httpClose(http); return (1); } // Get the printer-id for the printer we are deleting... response = get_printer_attributes(http, printer_uri, printer_name, resource, 1, &pattrs); printer_id = ippGetInteger(ippFindAttribute(response, "printer-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (printer_id == 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to get information for printer: %s"), base_name, cupsGetErrorString()); httpClose(http); return (1); } // Now that we have the printer-id, delete it from the system service... request = ippNewRequest(IPP_OP_DELETE_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "printer-id", printer_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to delete printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopGetSetDefaultPrinter()' - Get/set the default printer. // int // O - Exit status _papplMainloopGetSetDefaultPrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char resource[1024]; // Resource path int printer_id; // printer-id value static const char *pattrs = "printer-id"; // Requested attributes // Connect to/start up the server and get the destination printer... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { char default_printer[256]; // Default printer if (_papplMainloopGetDefaultPrinter(http, default_printer, sizeof(default_printer))) puts(default_printer); else _papplLocPrintf(stdout, _PAPPL_LOC("No default printer set.")); httpClose(http); return (0); } // OK, setting the default printer so get the printer-id for it... response = get_printer_attributes(http, printer_uri, printer_name, resource, 1, &pattrs); printer_id = ippGetInteger(ippFindAttribute(response, "printer-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (printer_id == 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to get information for '%s': %s"), base_name, printer_name, cupsGetErrorString()); httpClose(http); return (1); } // Now that we have the printer-id, set the system-default-printer-id // attribute for the system service... request = ippNewRequest(IPP_OP_SET_SYSTEM_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddInteger(request, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-default-printer-id", printer_id); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to set default printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopModifyPrinter()' - Modify printer. // int // O - Exit status _papplMainloopModifyPrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request, // Set-Printer-Attributes request *supported; // Supported attributes const char *printer_uri, // Printer URI *printer_name; // Name of printer char resource[1024]; // Resource path // Open a connection to the server... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-d PRINTER'."), base_name); return (1); } // Get the supported attributes... supported = get_printer_attributes(http, printer_uri, printer_name, resource, 0, NULL); // Send a Set-Printer-Attributes request to the server... request = ippNewRequest(IPP_OP_SET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); _papplMainloopAddOptions(request, num_options, options, supported); ippDelete(supported); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to modify printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopPausePrinter()' - Pause printer. // int // O - Exit status _papplMainloopPausePrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // Pause-Printer request const char *printer_uri, // Printer URI *printer_name; // Name of printer char resource[1024]; // Resource path // Open a connection to the server... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-d PRINTER'."), base_name); return (1); } // Send a Pause-Printer request to the server... request = ippNewRequest(IPP_OP_PAUSE_PRINTER); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to pause printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopResumePrinter()' - Resume printer. // int // O - Exit status _papplMainloopResumePrinter( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // Pause-Printer request const char *printer_uri, // Printer URI *printer_name; // Name of printer char resource[1024]; // Resource path // Open a connection to the server... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else if ((http = _papplMainloopConnect(base_name, true)) == NULL) { return (1); } else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing '-d PRINTER'."), base_name); return (1); } // Send a Resume-Printer request to the server... request = ippNewRequest(IPP_OP_RESUME_PRINTER); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to resume printer: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopRunServer()' - Run server. // int // O - Exit status _papplMainloopRunServer( const char *base_name, // I - Base name const char *version, // I - Version number const char *footer_html, // I - Footer HTML or `NULL` for none cups_len_t num_drivers, // I - Number of drivers pappl_pr_driver_t *drivers, // I - Drivers pappl_pr_autoadd_cb_t autoadd_cb, // I - Auto-add callback pappl_pr_driver_cb_t driver_cb, // I - Driver callback cups_len_t num_options, // I - Number of options cups_option_t **options, // I - Options pappl_ml_system_cb_t system_cb, // I - System callback void *data) // I - Callback data { pappl_system_t *system; // System object char filename[1023]; // Config filename #if !_WIN32 char sockname[1024]; // Socket filename #endif // !_WIN32 char statename[1024];// State filename #if _WIN32 const char *home = getenv("USERPROFILE"); // Home directory #else const char *home = getenv("HOME"); // Home directory #endif // _WIN32 const char *snap_common = getenv("SNAP_COMMON"); // Common data directory for snaps const char *tmpdir = papplGetTempDir(); // Temporary directory const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); // Freedesktop per-user config directory #ifdef __APPLE__ pthread_t tid; // Thread ID #endif // __APPLE__ // Load additional options from config files... if (xdg_config_home) { snprintf(filename, sizeof(filename), "%s/%s.conf", xdg_config_home, base_name); num_options = load_options(filename, num_options, options); } else if (home) { #ifdef __APPLE__ snprintf(filename, sizeof(filename), "%s/Library/Application Support/%s.conf", home, base_name); #elif _WIN32 snprintf(filename, sizeof(filename), "%s/AppData/Local/%s.conf", home, base_name); #else snprintf(filename, sizeof(filename), "%s/.config/%s.conf", home, base_name); #endif // __APPLE__ num_options = load_options(filename, num_options, options); } if (snap_common) { snprintf(filename, sizeof(filename), "%s/%s.conf", snap_common, base_name); num_options = load_options(filename, num_options, options); } else { #ifdef __APPLE__ snprintf(filename, sizeof(filename), "/Library/Application Support/%s.conf", base_name); #else snprintf(filename, sizeof(filename), "/usr/local/etc/%s.conf", base_name); num_options = load_options(filename, num_options, options); snprintf(filename, sizeof(filename), "/etc/%s.conf", base_name); #endif // __APPLE__ num_options = load_options(filename, num_options, options); } // Create the system object... if (system_cb) { // Developer-supplied system object... system = (system_cb)((int)num_options, *options, data); } else { // Use the default system object... system = default_system_cb(base_name, (int)num_options, *options, data); } if (!system) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Failed to create a system."), base_name); return (1); } // Set the version number as needed... if (system->num_versions == 0 && version) { pappl_version_t sysversion; // System version memset(&sysversion, 0, sizeof(sysversion)); papplCopyString(sysversion.name, base_name, sizeof(sysversion.name)); papplCopyString(sysversion.sversion, version, sizeof(sysversion.sversion)); sscanf(version, "%hu.%hu.%hu.%hu", sysversion.version + 0, sysversion.version + 1, sysversion.version + 2, sysversion.version + 3); papplSystemSetVersions(system, 1, &sysversion); } // Set the footer HTML as needed... if (!system->footer_html && footer_html) papplSystemSetFooterHTML(system, footer_html); // Set the driver info as needed... if (system->num_drivers == 0 && num_drivers > 0 && drivers && driver_cb) papplSystemSetPrinterDrivers(system, (int)num_drivers, drivers, autoadd_cb, /* create_cb */NULL, driver_cb, data); #if _WIN32 // Save the TCP/IP socket for the server in the registry so other processes // can find us... save_server_port(base_name, papplSystemGetHostPort(system)); #else // Listen for local (domain socket) connections so other processes can find // us... papplSystemAddListeners(system, _papplMainloopGetServerPath(base_name, getuid(), sockname, sizeof(sockname))); #endif // _WIN32 // Finish initialization... if (!system->save_cb) { // Register a callback for saving state information, then load any // previous state... statename[0] = '\0'; if (snap_common) { // Running inside a snap (https://snapcraft.io), so use the snap's common // data directory... if (!access(snap_common, X_OK)) snprintf(statename, sizeof(statename), "%s/%s.state", snap_common, base_name); } #if !_WIN32 else if (!getuid()) { // Running as root, so put the state file in the local state directory snprintf(statename, sizeof(statename), PAPPL_STATEDIR "/lib/%s.state", base_name); // Make sure base directory exists if (mkdir(PAPPL_STATEDIR "/lib", 0777) && errno != EEXIST) statename[0] = '\0'; } #endif // !_WIN32 else if (xdg_config_home) { // Use Freedesktop per-user config directory if (!access(xdg_config_home, X_OK)) snprintf(statename, sizeof(statename), "%s/%s.state", xdg_config_home, base_name); } else if (home) { #ifdef __APPLE__ // Put the state in "~/Library/Application Support" snprintf(statename, sizeof(statename), "%s/Library/Application Support/%s.state", home, base_name); #elif _WIN32 // Put the state in "~/AppData/Local" snprintf(statename, sizeof(statename), "%s/AppData/Local/%s.state", home, base_name); #else // Put the state under a ".config" directory in the home directory snprintf(statename, sizeof(statename), "%s/.config", home); // Make ~/.config as needed if (mkdir(statename, 0777) && errno != EEXIST) statename[0] = '\0'; if (statename[0]) snprintf(statename, sizeof(statename), "%s/.config/%s.state", home, base_name); #endif // __APPL__ } if (!statename[0]) { // As a last resort, put the state in the temporary directory (where it // will be lost on the nest reboot/logout... #if _WIN32 snprintf(statename, sizeof(statename), "%s/%s.state", tmpdir, base_name); #else snprintf(statename, sizeof(statename), "%s/%s%d.state", tmpdir, base_name, (int)getuid()); #endif // _WIN32 } papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, (void *)statename); if (!papplSystemLoadState(system, statename) && autoadd_cb) { // If there is no state file, auto-add locally-connected printers... papplSystemCreatePrinters(system, PAPPL_DEVTYPE_LOCAL, /*cb*/NULL, /*cb_data*/NULL); } } // Set the mainloop system object in case it is needed. pthread_mutex_lock(&mainloop_mutex); mainloop_system = system; pthread_mutex_unlock(&mainloop_mutex); // Run the system until shutdown... #ifdef __APPLE__ // TODO: Implement private/public API for running with UI auditinfo_addr_t ainfo; // Information about this process if (!getaudit_addr(&ainfo, sizeof(ainfo)) && (ainfo.ai_flags & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)) { // Show menubar extra when running in an ordinary login session. Since // macOS requires UI code to run on the main thread, run the system object // in a background thread... if (pthread_create(&tid, NULL, (void *(*)(void *))papplSystemRun, system)) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create system thread: %s", strerror(errno)); } else { // Then run the UI stuff on the main thread (macOS limitation...) while (!papplSystemIsRunning(system)) sleep(1); _papplSystemStatusUI(system); while (papplSystemIsRunning(system)) sleep(1); } } else // Don't do UI thread... #endif // __APPLE__ // Run the system on the main thread... papplSystemRun(system); #if _WIN32 save_server_port(base_name, 0); // Clear the Windows registry #endif // _WIN32 // Clear the mainloop system object. pthread_mutex_lock(&mainloop_mutex); mainloop_system = NULL; pthread_mutex_unlock(&mainloop_mutex); // Delete the system and return... papplSystemDelete(system); return (0); } // // '_papplMainloopShowDevices()' - Show available devices. // int // O - Exit status _papplMainloopShowDevices( const char *base_name, // I - Basename of application cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response ipp_attribute_t *attr; // IPP attribute // Connect to/start up the server and get the destination printer... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); request = ippNewRequest(IPP_OP_PAPPL_FIND_DEVICES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); response = cupsDoRequest(http, request, "/ipp/system"); httpClose(http); if (cupsGetError() != IPP_STATUS_OK && cupsGetError() != IPP_STATUS_ERROR_NOT_FOUND) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to get available devices: %s"), base_name, cupsGetErrorString()); ippDelete(response); return (1); } if ((attr = ippFindAttribute(response, "smi55357-device-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) { cups_len_t i, // Looping var num_devices = ippGetCount(attr); // Number of device entries for (i = 0; i < num_devices; i ++) { ipp_t *item = ippGetCollection(attr, i); // Device entry ipp_attribute_t *item_attr; // Device attr if ((item_attr = ippFindAttribute(item, "smi55357-device-uri", IPP_TAG_ZERO)) != NULL) { puts(ippGetString(item_attr, 0, NULL)); if (cupsGetOption("verbose", num_options, options)) { if ((item_attr = ippFindAttribute(item, "smi55357-device-info", IPP_TAG_ZERO)) != NULL) printf(" %s\n", ippGetString(item_attr, 0, NULL)); if ((item_attr = ippFindAttribute(item, "smi55357-device-id", IPP_TAG_ZERO)) != NULL) printf(" %s\n", ippGetString(item_attr, 0, NULL)); } } } } ippDelete(response); return (0); } // // '_papplMainloopShowDrivers()' - Show available drivers. // int // O - Exit status _papplMainloopShowDrivers( const char *base_name, // I - Basename of application cups_len_t num_drivers, // I - Number of drivers pappl_pr_driver_t *drivers, // I - Drivers pappl_pr_autoadd_cb_t autoadd_cb, // I - Auto-add callback pappl_pr_driver_cb_t driver_cb, // I - Driver callback cups_len_t num_options, // I - Number of options cups_option_t *options, // I - Options pappl_ml_system_cb_t system_cb, // I - System callback void *data) // I - Callback data { cups_len_t i; // Looping variable pappl_system_t *system; // System object const char *driver_name; // I - Driver name const char *device_id; // I - IEEE-1284 device ID if (system_cb) system = (system_cb)((int)num_options, options, data); else system = default_system_cb(base_name, (int)num_options, options, data); if (!system) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Failed to create a system."), base_name); return (1); } // Set the driver info as needed... if (system->num_drivers == 0 && num_drivers > 0 && drivers && driver_cb) papplSystemSetPrinterDrivers(system, (int)num_drivers, drivers, autoadd_cb, /* create_cb */NULL, driver_cb, data); if ((device_id = cupsGetOption("device-id", num_options, options)) != NULL) { if ((driver_name = (system->autoadd_cb)(NULL, NULL, device_id, data)) == NULL) goto cleanup; } else driver_name = NULL; for (i = 0; i < system->num_drivers; i ++) { if (!driver_name || !strcmp(driver_name, system->drivers[i].name)) printf("%s \"%s\" \"%s\"\n", system->drivers[i].name, system->drivers[i].description, system->drivers[i].device_id ? system->drivers[i].device_id : ""); } cleanup: papplSystemDelete(system); return (0); } // // '_papplMainloopShowJobs()' - Show pending printer jobs. // int // O - Exit status _papplMainloopShowJobs( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name char default_printer[256], // Default printer resource[1024]; // Resource path http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response ipp_attribute_t *attr; // Current attribute const char *attrname; // Attribute name int job_id, // Current job-id job_state; // Current job-state const char *job_name, // Current job-name *job_user; // Current job-originating-user-name static const char * const jattrs[] = // Requested attributes { "job-id", "job-name", "job-originating-user-name", "job-state" }; if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to/start up the server and get the destination printer... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = _papplMainloopGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: No default printer available."), base_name); httpClose(http); return (1); } } } // Send a Get-Jobs request... request = ippNewRequest(IPP_OP_GET_JOBS); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", NULL, "all"); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs); response = cupsDoRequest(http, request, resource); for (attr = ippGetFirstAttribute(response); attr; attr = ippGetNextAttribute(response)) { if (ippGetGroupTag(attr) == IPP_TAG_OPERATION) continue; job_id = 0; job_state = IPP_JSTATE_PENDING; job_name = "(none)"; job_user = "(unknown)"; while (ippGetGroupTag(attr) == IPP_TAG_JOB) { attrname = ippGetName(attr); if (!strcmp(attrname, "job-id")) job_id = ippGetInteger(attr, 0); else if (!strcmp(attrname, "job-name")) job_name = ippGetString(attr, 0, NULL); else if (!strcmp(attrname, "job-originating-user-name")) job_user = ippGetString(attr, 0, NULL); else if (!strcmp(attrname, "job-state")) job_state = ippGetInteger(attr, 0); attr = ippGetNextAttribute(response); } printf("%d %-12s %-16s %s\n", job_id, ippEnumString("job-state", job_state), job_user, job_name); } ippDelete(response); httpClose(http); return (0); } // // '_papplMainloopShowOptions()' - Show supported option. // int // O - Exit status _papplMainloopShowOptions( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { cups_len_t i, j, // Looping vars count; // Number of values const char *printer_uri, // Printer URI *printer_name; // Printer name char default_printer[256]; // Default printer name http_t *http; // Server connection ipp_t *response; // IPP response ipp_attribute_t *job_attrs; // "job-creation-attributes-supported" char resource[1024]; // Resource path static const char * const standard_options[] = { // Standard options "copies", "document-format", "document-name", "ipp-attribute-fidelity", "job-hold-until", "job-hold-until-time", "job-name", "job-priority", "job-retain-until", "job-retain-until-interval", "job-retain-until-time", "media", "media-col", "multiple-document-handling", "orientation-requested", "output-bin", "page-ranges", "print-color-mode", "print-content-optimize", "print-darkness", "print-quality", "print-speed", "printer-resolution", "sides" }; if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else { // Connect to/start up the server and get the destination printer... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = _papplMainloopGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: No default printer available."), base_name); httpClose(http); return (1); } } } // Get the xxx-supported and xxx-default attributes response = get_printer_attributes(http, printer_uri, printer_name, resource, 0, NULL); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to get printer options: %s"), base_name, cupsGetErrorString()); ippDelete(response); httpClose(http); return (1); } _papplLocPrintf(stdout, _PAPPL_LOC("Print job options:")); _papplLocPrintf(stdout, _PAPPL_LOC(" -c COPIES")); print_option(response, "media"); print_option(response, "media-source"); print_option(response, "media-top-offset"); print_option(response, "media-tracking"); print_option(response, "media-type"); print_option(response, "orientation-requested"); print_option(response, "print-color-mode"); print_option(response, "print-content-optimize"); if (ippFindAttribute(response, "print-darkness-supported", IPP_TAG_ZERO)) _papplLocPrintf(stdout, _PAPPL_LOC(" -o print-darkness=-100 to 100")); print_option(response, "print-quality"); print_option(response, "print-speed"); print_option(response, "printer-resolution"); // Show vendor extension options... if ((job_attrs = ippFindAttribute(response, "job-creation-attributes-supported", IPP_TAG_KEYWORD)) != NULL) { for (i = 0, count = ippGetCount(job_attrs); i < count; i ++) { const char *name = ippGetString(job_attrs, i, NULL); // Attribute name for (j = 0; j < (cups_len_t)(sizeof(standard_options) / sizeof(standard_options[0])); j ++) { if (!strcmp(name, standard_options[j])) break; } if (j >= (cups_len_t)(sizeof(standard_options) / sizeof(standard_options[0]))) { // Vendor option... print_option(response, name); } } } // Show printer settings... puts(""); _papplLocPrintf(stdout, _PAPPL_LOC("Printer options:")); print_option(response, "label-mode"); print_option(response, "label-tear-offset"); if (ippFindAttribute(response, "printer-darkness-supported", IPP_TAG_ZERO)) _papplLocPrintf(stdout, _PAPPL_LOC(" -o printer-darkness=0 to 100")); _papplLocPrintf(stdout, _PAPPL_LOC(" -o printer-geo-location='geo:LATITUDE,LONGITUDE'")); _papplLocPrintf(stdout, _PAPPL_LOC(" -o printer-location='LOCATION'")); _papplLocPrintf(stdout, _PAPPL_LOC(" -o printer-organization='ORGANIZATION'")); _papplLocPrintf(stdout, _PAPPL_LOC(" -o printer-organizational-unit='UNIT/SECTION'")); ippDelete(response); httpClose(http); return (0); } // // 'papplMainShowPrinters()' - Show printer queues. // int // O - Exit status _papplMainloopShowPrinters( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response ipp_attribute_t *attr; // Current attribute (void)num_options; (void)options; // Connect to/start up the server and get the list of printers... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); request = ippNewRequest(IPP_OP_GET_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/system"); for (attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME); attr; attr = ippFindNextAttribute(response, "printer-name", IPP_TAG_NAME)) puts(ippGetString(attr, 0, NULL)); ippDelete(response); httpClose(http); return (0); } // // '_papplMainloopShowStatus()' - Show system/printer status. // int // O - Exit status _papplMainloopShowStatus( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // HTTP connection const char *printer_uri, // Printer URI *printer_name; // Printer name char resource[1024]; // Resource path ipp_t *request, // IPP request *response; // IPP response cups_len_t i, // Looping var count; // Number of reasons int state; // *-state value ipp_attribute_t *state_reasons; // *-state-reasons attribute char state_reasons_str[1024], // *-state-reasons string *state_reasons_ptr; // Pointer into string time_t state_time; // *-state-change-time value char state_time_str[256]; // *-state-change-time date string const char *reason; // *-state-reasons value static const char * const states[] = // *-state strings { "idle", "processing jobs", "stopped" }; static const char * const pattrs[] = { // Requested printer attributes "printer-state", "printer-state-change-date-time", "printer-state-reasons" }; static const char * const sysattrs[] = { // Requested system attributes "system-state", "system-state-change-date-time", "system-state-reasons" }; if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else { // Connect to the server... if ((http = _papplMainloopConnect(base_name, false)) == NULL) { _papplLocPrintf(stdout, _PAPPL_LOC("Server is not running.")); return (0); } } if (printer_uri || (printer_name = cupsGetOption("printer-name", num_options, options)) != NULL) { // Get the printer's status response = get_printer_attributes(http, printer_uri, printer_name, resource, (int)(sizeof(pattrs) / sizeof(pattrs[0])), pattrs); state = ippGetInteger(ippFindAttribute(response, "printer-state", IPP_TAG_ENUM), 0); state_time = ippDateToTime(ippGetDate(ippFindAttribute(response, "printer-state-change-date-time", IPP_TAG_DATE), 0)); state_reasons = ippFindAttribute(response, "printer-state-reasons", IPP_TAG_KEYWORD); } else { // Get the system status request = ippNewRequest(IPP_OP_GET_SYSTEM_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(sysattrs) / sizeof(sysattrs[0])), NULL, sysattrs); response = cupsDoRequest(http, request, "/ipp/system"); state = ippGetInteger(ippFindAttribute(response, "system-state", IPP_TAG_ENUM), 0); state_time = ippDateToTime(ippGetDate(ippFindAttribute(response, "system-state-change-date-time", IPP_TAG_DATE), 0)); state_reasons = ippFindAttribute(response, "system-state-reasons", IPP_TAG_KEYWORD); } if (state < IPP_PSTATE_IDLE) state = IPP_PSTATE_IDLE; else if (state > IPP_PSTATE_STOPPED) state = IPP_PSTATE_STOPPED; state_reasons_str[0] = '\0'; if (state_reasons) { // Build a string with all of the reasons... for (i = 0, count = ippGetCount(state_reasons), state_reasons_ptr = state_reasons_str; i < count; i ++) { reason = ippGetString(state_reasons, i, NULL); if (strcmp(reason, "none")) { if (state_reasons_ptr > state_reasons_str) snprintf(state_reasons_ptr, sizeof(state_reasons_str) - (size_t)(state_reasons_ptr - state_reasons_str), ", %s", reason); else papplCopyString(state_reasons_str, reason, sizeof(state_reasons_str)); state_reasons_ptr += strlen(state_reasons_ptr); } } } _papplLocPrintf(stdout, _PAPPL_LOC(/* Running, STATE since DATE REASONS */"Running, %s since %s%s."), states[state - IPP_PSTATE_IDLE], httpGetDateString(state_time, state_time_str, sizeof(state_time_str)), state_reasons_str); ippDelete(response); return (0); } // // 'papplMainloopShutdown()' - Request a shutdown of a running system. // // This function requests that the system started by @link papplMainloop@ be // shutdown. // void papplMainloopShutdown(void) { pthread_mutex_lock(&mainloop_mutex); papplSystemShutdown(mainloop_system); pthread_mutex_unlock(&mainloop_mutex); } // // '_papplMainloopShutdownServer()' - Shutdown the server. // int // O - Exit status _papplMainloopShutdownServer( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // HTTP connection ipp_t *request; // IPP request (void)num_options; (void)options; // Try connecting to the server... if ((http = _papplMainloopConnect(base_name, false)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Server is not running."), base_name); return (1); } request = ippNewRequest(IPP_OP_SHUTDOWN_ALL_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/system")); if (cupsGetError() != IPP_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to shutdown server: %s"), base_name, cupsGetErrorString()); return (1); } return (0); } // // '_papplMainloopSubmitJob()' - Submit job(s). // int // O - Exit status _papplMainloopSubmitJob( const char *base_name, // I - Base name cups_len_t num_options, // I - Number of options cups_option_t *options, // I - Options cups_len_t num_files, // I - Number of files char **files) // I - Files { const char *document_format, // Document format *document_name, // Document name *filename, // Current print filename *job_name, // Job name *printer_name, // Printer name *printer_uri; // Printer URI http_t *http; // Server connection ipp_t *request, // IPP request *response, // IPP response *supported; // Supported attributes char default_printer[256], // Default printer name resource[1024], // Resource path tempfile[1024] = ""; // Temporary file cups_len_t i; // Looping var ipp_attribute_t *job_id; // job-id for created job #if !_WIN32 // If there are no input files and stdin is not a TTY, treat that as an // implicit request to print from stdin... char *stdin_file; // Dummy filename for passive stdin jobs if (num_files == 0 && !isatty(0)) { stdin_file = (char *)"-"; files = &stdin_file; num_files = 1; } #endif // !_WIN32 if (num_files == 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: No files to print."), base_name); return (1); } if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = _papplMainloopConnectURI(base_name, printer_uri, resource, sizeof(resource))) == NULL) return (1); printer_name = NULL; } else { // Connect to/start up the server and get the destination printer... if ((http = _papplMainloopConnect(base_name, true)) == NULL) return (1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = _papplMainloopGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: No default printer available."), base_name); httpClose(http); return (1); } } } // Loop through the print files job_name = cupsGetOption("job-name", num_options, options); document_format = cupsGetOption("document-format", num_options, options); for (i = 0; i < num_files; i ++) { // Get the current print file... if (!strcmp(files[i], "-")) { if (!copy_stdin(base_name, tempfile, sizeof(tempfile))) { httpClose(http); return (1); } filename = tempfile; document_name = "(stdin)"; } else { filename = files[i]; if ((document_name = strrchr(filename, '/')) != NULL) document_name ++; else document_name = filename; } // Get supported attributes... supported = get_printer_attributes(http, printer_uri, printer_name, resource, 0, NULL); // Send a Print-Job request... request = ippNewRequest(IPP_OP_PRINT_JOB); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else _papplMainloopAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, job_name ? job_name : document_name); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, document_name); if (document_format) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, document_format); _papplMainloopAddOptions(request, num_options, options, supported); ippDelete(supported); response = cupsDoFileRequest(http, request, resource, filename); if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to print '%s': %s"), base_name, filename, cupsGetErrorString()); ippDelete(response); httpClose(http); return (1); } if (printer_uri) printf("%d\n", ippGetInteger(job_id, 0)); else printf("%s-%d\n", printer_name, ippGetInteger(job_id, 0)); ippDelete(response); if (tempfile[0]) unlink(tempfile); } httpClose(http); return (0); } // // 'copy_stdin()' - Copy print data from the standard input. // static char * // O - Temporary filename or `NULL` on error copy_stdin( const char *base_name, // I - Printer application name char *name, // I - Filename buffer size_t namesize) // I - Size of filename buffer { int tempfd; // Temporary file descriptor size_t total = 0; // Total bytes read/written ssize_t bytes; // Number of bytes read/written char buffer[65536]; // Copy buffer // Create a temporary file for printing... if ((tempfd = cupsCreateTempFd(NULL, NULL, name, (cups_len_t)namesize)) < 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to create temporary file: %s"), base_name, strerror(errno)); return (NULL); } // Read from stdin until we see EOF... while ((bytes = read(0, buffer, sizeof(buffer))) > 0) { if (write(tempfd, buffer, (size_t)bytes) < 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to write to temporary file: %s"), base_name, strerror(errno)); goto fail; } total += (size_t)bytes; } // Only allow non-empty files... if (total == 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Empty print file received on the standard input."), base_name); goto fail; } // Close the temporary file and return it... close(tempfd); return (name); // If we get here, something went wrong... fail: // Close and remove the temporary file... close(tempfd); unlink(name); // Return NULL and an empty filename... *name = '\0'; return (NULL); } // // 'default_system_cb()' - Create a system object. // static pappl_system_t * // O - System object default_system_cb( const char *base_name, // I - Base name of application int num_options, // I - Number of options cups_option_t *options, // I - Options void *data) // I - Data (unused) { pappl_system_t *system; // System object pappl_soptions_t soptions = PAPPL_SOPTIONS_MULTI_QUEUE | PAPPL_SOPTIONS_WEB_INTERFACE | PAPPL_SOPTIONS_WEB_TLS; // Server options char spoolname[1024]; // Default spool directory const char *directory = cupsGetOption("spool-directory", (cups_len_t)num_options, options), // Spool directory *logfile = cupsGetOption("log-file", (cups_len_t)num_options, options), // Log file *server_hostname = cupsGetOption("server-hostname", (cups_len_t)num_options, options), // Server hostname *value, // Other option *valptr; // Pointer into option pappl_loglevel_t loglevel = PAPPL_LOGLEVEL_WARN; // Log level int port = 0; // Port #if _WIN32 const char *home = getenv("USERPROFILE"); // Home directory #else const char *home = getenv("HOME"); // Home directory #endif // _WIN32 const char *snap_common = getenv("SNAP_COMMON"); // Common data directory for snaps const char *tmpdir = papplGetTempDir(); // Temporary directory (void)data; // Collect standard options... if ((value = cupsGetOption("log-level", (cups_len_t)num_options, options)) != NULL) { if (!strcmp(value, "fatal")) loglevel = PAPPL_LOGLEVEL_FATAL; else if (!strcmp(value, "error")) loglevel = PAPPL_LOGLEVEL_ERROR; else if (!strcmp(value, "warn")) loglevel = PAPPL_LOGLEVEL_WARN; else if (!strcmp(value, "info")) loglevel = PAPPL_LOGLEVEL_INFO; else if (!strcmp(value, "debug")) loglevel = PAPPL_LOGLEVEL_DEBUG; } if ((value = cupsGetOption("server-options", (cups_len_t)num_options, options)) != NULL) { for (valptr = value; valptr && *valptr;) { if (!strcmp(valptr, "none") || !strncmp(valptr, "none,", 5)) soptions = PAPPL_SOPTIONS_NONE; else if (!strcmp(valptr, "dnssd-host") || !strncmp(valptr, "dnssd-host,", 11)) soptions |= PAPPL_SOPTIONS_DNSSD_HOST; else if (!strcmp(valptr, "no-multi-queue") || !strncmp(valptr, "no-multi-queue,", 15)) soptions &= (pappl_soptions_t)~PAPPL_SOPTIONS_MULTI_QUEUE; else if (!strcmp(valptr, "raw-socket") || !strncmp(valptr, "raw-socket,", 11)) soptions |= PAPPL_SOPTIONS_RAW_SOCKET; else if (!strcmp(valptr, "usb-printer") || !strncmp(valptr, "usb-printer,", 12)) soptions |= PAPPL_SOPTIONS_USB_PRINTER; else if (!strcmp(valptr, "no-web-interface") || !strncmp(valptr, "no-web-interface,", 17)) soptions &= (pappl_soptions_t)~PAPPL_SOPTIONS_WEB_INTERFACE; else if (!strcmp(valptr, "web-log") || !strncmp(valptr, "web-log,", 8)) soptions |= PAPPL_SOPTIONS_WEB_LOG; else if (!strcmp(valptr, "web-network") || !strncmp(valptr, "web-network,", 12)) soptions |= PAPPL_SOPTIONS_WEB_NETWORK; else if (!strcmp(valptr, "web-remote") || !strncmp(valptr, "web-remote,", 11)) soptions |= PAPPL_SOPTIONS_WEB_REMOTE; else if (!strcmp(valptr, "web-security") || !strncmp(valptr, "web-security,", 13)) soptions |= PAPPL_SOPTIONS_WEB_SECURITY; else if (!strcmp(valptr, "no-tls") || !strncmp(valptr, "no-tls,", 7)) soptions = (pappl_soptions_t)((soptions | PAPPL_SOPTIONS_NO_TLS) & (pappl_soptions_t)~PAPPL_SOPTIONS_WEB_TLS); if ((valptr = strchr(valptr, ',')) != NULL) valptr ++; } } if ((value = cupsGetOption("server-port", (cups_len_t)num_options, options)) != NULL) { char *end; // End of value port = (int)strtol(value, &end, 10); if (port < 0 || errno == ERANGE || *end) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Bad 'server-port' value."), base_name); return (NULL); } } // Make sure we have a spool directory... if (!directory) { spoolname[0] = '\0'; if (snap_common) { // Running inside a snap (https://snapcraft.io), so use the snap's common // data directory... snprintf(spoolname, sizeof(spoolname), "%s/%s.d", snap_common, base_name); } #if !_WIN32 else if (!getuid()) { // Running as root, so put the state file in the local state directory snprintf(spoolname, sizeof(spoolname), PAPPL_STATEDIR "/spool/%s", base_name); // Make sure base directory exists if (mkdir(PAPPL_STATEDIR "/spool", 0777) && errno != EEXIST) { // Can't use local state directory, so use the last resort... spoolname[0] = '\0'; } } #endif // !_WIN32 else if (home) { #ifdef __APPLE__ // Put the spool directory in "~/Library/Application Support" snprintf(spoolname, sizeof(spoolname), "%s/Library/Application Support/%s.d", home, base_name); #elif _WIN32 // Put the spool directory in "~/AppData/Local" snprintf(spoolname, sizeof(spoolname), "%s/AppData/Local/%s.d", home, base_name); #else // Put the spool directory under a ".config" directory in the home directory snprintf(spoolname, sizeof(spoolname), "%s/.config", home); // Make ~/.config as needed if (mkdir(spoolname, 0777) && errno != EEXIST) spoolname[0] = '\0'; if (spoolname[0]) snprintf(spoolname, sizeof(spoolname), "%s/.config/%s.d", home, base_name); #endif // __APPLE__ } if (!spoolname[0]) { // As a last resort, put the spool directory in the temporary directory // (where it will be lost on the nest reboot/logout... #if _WIN32 snprintf(spoolname, sizeof(spoolname), "%s/%s.d", tmpdir, base_name); #else snprintf(spoolname, sizeof(spoolname), "%s/%s%d.d", tmpdir, base_name, (int)getuid()); #endif // _WIN32 } directory = spoolname; } // Create the system object... system = papplSystemCreate(soptions, base_name, port, "_print,_universal", directory, logfile, loglevel, cupsGetOption("auth-service", (cups_len_t)num_options, options), /* tls_only */false); // Set any admin group and listen for network connections... if ((value = cupsGetOption("admin-group", (cups_len_t)num_options, options)) != NULL) papplSystemSetAdminGroup(system, value); if (server_hostname) papplSystemSetHostName(system, server_hostname); if (!cupsGetOption("private-server", (cups_len_t)num_options, options)) { // Listen for TCP/IP connections... papplSystemAddListeners(system, cupsGetOption("listen-hostname", (cups_len_t)num_options, options)); } return (system); } // // 'get_printer_attributes()' - Get printer attributes. // static ipp_t * // O - IPP response get_printer_attributes( http_t *http, // I - HTTP connection const char *printer_uri, // I - Printer URI, if any const char *printer_name, // I - Printer name, if any const char *resource, // I - Resource path cups_len_t num_requested, // I - Number of requested attributes const char * const *requested) // I - Requested attributes or `NULL` { ipp_t *request; // IPP request char temp[1024]; // Temporary string request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); if (printer_uri) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); } else { _papplMainloopAddPrinterURI(request, printer_name, temp, sizeof(temp)); resource = temp; } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); if (num_requested > 0 && requested) ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", num_requested, NULL, requested); return (cupsDoRequest(http, request, resource)); } // // 'get_value()' - Get the string representation of an attribute value. // static char * // O - String value get_value(ipp_attribute_t *attr, // I - Attribute const char *name, // I - Base name of attribute cups_len_t element, // I - Value index char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { const char *value; // String value int intvalue; // Integer value int lower, // Lower range value upper; // Upper range value int xres, // X resolution yres; // Y resolution ipp_res_t units; // Resolution units *buffer = '\0'; switch (ippGetValueTag(attr)) { default : case IPP_TAG_KEYWORD : if ((value = ippGetString(attr, element, NULL)) != NULL) { if (!strcmp(name, "media")) { pwg_media_t *pwg = pwgMediaForPWG(value); // Media size if ((pwg->width % 100) == 0) snprintf(buffer, bufsize, "%s (%dx%dmm or %.2gx%.2gin)", value, pwg->width / 100, pwg->length / 100, pwg->width / 2540.0, pwg->length / 2540.0); else snprintf(buffer, bufsize, "%s (%.2gx%.2gin or %dx%dmm)", value, pwg->width / 2540.0, pwg->length / 2540.0, pwg->width / 100, pwg->length / 100); } else { papplCopyString(buffer, value, bufsize); } } break; case IPP_TAG_ENUM : papplCopyString(buffer, ippEnumString(name, ippGetInteger(attr, element)), bufsize); break; case IPP_TAG_INTEGER : intvalue = ippGetInteger(attr, element); if (!strcmp(name, "label-tear-offset") || !strcmp(name, "media-top-offset") || !strcmp(name, "print-speed")) { if ((intvalue % 635) == 0) snprintf(buffer, bufsize, "%.2gin", intvalue / 2540.0); else snprintf(buffer, bufsize, "%.2gmm", intvalue * 0.01); } else snprintf(buffer, bufsize, "%d", intvalue); break; case IPP_TAG_RANGE : lower = ippGetRange(attr, element, &upper); if (!strcmp(name, "label-tear-offset") || !strcmp(name, "media-top-offset") || !strcmp(name, "print-speed")) { if ((upper % 635) == 0) snprintf(buffer, bufsize, "%.2gin to %.2gin", lower / 2540.0, upper / 2540.0); else snprintf(buffer, bufsize, "%.2gmm to %.2gmm", lower * 0.01, upper * 0.01); } else snprintf(buffer, bufsize, "%d to %d", lower, upper); break; case IPP_TAG_RESOLUTION : xres = ippGetResolution(attr, element, &yres, &units); if (xres == yres) snprintf(buffer, bufsize, "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); else snprintf(buffer, bufsize, "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); break; } return (buffer); } // // 'load_options()' - Load options from a file. // static cups_len_t // O - New number of options load_options(const char *filename, // I - Filename cups_len_t num_options, // I - Number of options cups_option_t **options) // IO - Options { cups_file_t *fp; // File pointer char line[8192]; // Line from file cups_len_t i, // Looping var num_loptions; // Number of line options cups_option_t *loptions, // Line options *loption; // Current line option // Open the file... if ((fp = cupsFileOpen(filename, "r")) == NULL) return (num_options); // Read lines until EOF... while (cupsFileGets(fp, line, sizeof(line))) { // Skip comment and blank lines... if (line[0] == '#' || !line[0]) continue; // Parse any options on this line... num_loptions = cupsParseOptions(line, /*end*/NULL, 0, &loptions); // Copy any unset line options to the options array... for (i = num_loptions, loption = loptions; i > 0; i --, loption ++) { if (!cupsGetOption(loption->name, num_options, *options)) num_options = cupsAddOption(loption->name, loption->value, num_options, options); } // Free the line options... cupsFreeOptions(num_loptions, loptions); } // Close the file and return... cupsFileClose(fp); return (num_options); } // // 'print_option()' - Print the supported and default value for an option. // static void print_option(ipp_t *response, // I - Get-Printer-Attributes response const char *name) // I - Attribute name { char defname[256], // xxx-default/xxx-configured name supname[256]; // xxx-supported name ipp_attribute_t *defattr, // xxx-default/xxx-configured attribute *supattr; // xxx-supported attribute cups_len_t i, // Looping var count; // Number of values char defvalue[256], // xxx-default/xxx-configured value supvalue[256]; // xxx-supported value // Get the default and supported attributes... snprintf(supname, sizeof(supname), "%s-supported", name); if ((supattr = ippFindAttribute(response, supname, IPP_TAG_ZERO)) == NULL) return; if (!strncmp(name, "media-", 6)) snprintf(defname, sizeof(defname), "media-col-default/%s", name); else snprintf(defname, sizeof(defname), "%s-default", name); if ((defattr = ippFindAttribute(response, defname, IPP_TAG_ZERO)) == NULL) { snprintf(defname, sizeof(defname), "%s-configured", name); defattr = ippFindAttribute(response, defname, IPP_TAG_ZERO); } get_value(defattr, name, 0, defvalue, sizeof(defvalue)); // Show the option with its values... if (defvalue[0]) _papplLocPrintf(stdout, _PAPPL_LOC(" -o %s=%s (default)"), name, defvalue); for (i = 0, count = ippGetCount(supattr); i < count; i ++) { if (strcmp(defvalue, get_value(supattr, name, i, supvalue, sizeof(supvalue)))) printf(" -o %s=%s\n", name, supvalue); } } #if _WIN32 // // 'save_server_port()' - Save the port number we are using for the server in // the registry. // static void save_server_port(const char *base_name, // I - Base name of application int port) // I - TCP/IP port number { char path[1024]; // Registry path HKEY key; // Registry key DWORD dport; // Port number value for registry // The server's port number is saved in SOFTWARE\appname\port snprintf(path, sizeof(path), "SOFTWARE\\%s", base_name); if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_WRITE, &key)) { // Was able to open the registry, save the port number... dport = (DWORD)port; RegSetKeyValueA(key, NULL, "port", REG_DWORD, &dport, sizeof(dport)); RegCloseKey(key); } } #endif // _WIN32 pappl-1.4.9/pappl/mainloop-support.c000066400000000000000000000553641476704353100175000ustar00rootroot00000000000000// // papplMainloop support functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // # include "pappl-private.h" # if _WIN32 # else # include # include # endif // _WIN32 // // Globals... // char *_papplMainloopPath = NULL; // Path to self // // Local functions // static int get_length(const char *value); // // '_papplMainloopAddOptions()' - Add default/job template attributes from options. // void _papplMainloopAddOptions( ipp_t *request, // I - IPP request cups_len_t num_options, // I - Number of options cups_option_t *options, // I - Options ipp_t *supported) // I - Supported attributes { ipp_attribute_t *job_attrs; // job-creation-attributes-supported int is_default; // Adding xxx-default attributes? ipp_tag_t group_tag; // Group to add to char *end; // End of value const char *value; // String value int intvalue; // Integer value const char *media_left_offset = cupsGetOption("media-left-offset", num_options, options), *media_source = cupsGetOption("media-source", num_options, options), *media_top_offset = cupsGetOption("media-top-offset", num_options, options), *media_tracking = cupsGetOption("media-tracking", num_options, options), *media_type = cupsGetOption("media-type", num_options, options); // media-xxx member values // Determine what kind of options we are adding... group_tag = ippGetOperation(request) == IPP_OP_PRINT_JOB ? IPP_TAG_JOB : IPP_TAG_PRINTER; is_default = (group_tag == IPP_TAG_PRINTER); if (is_default) { // Add Printer Description attributes... if ((value = cupsGetOption("label-mode-configured", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "label-mode-configured", NULL, value); if ((value = cupsGetOption("label-tear-offset-configured", num_options, options)) != NULL) ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "label-tear-offset-configured", get_length(value)); if ((value = cupsGetOption("media-ready", num_options, options)) != NULL) { cups_len_t num_values; // Number of values char *values[PAPPL_MAX_SOURCE], // Pointers to size strings *cvalue, // Copied value *cptr; // Pointer into copy num_values = 0; cvalue = strdup(value); cptr = cvalue; #if _WIN32 if ((values[num_values] = strtok_s(cvalue, ",", &cptr)) != NULL) { num_values ++; while (num_values < PAPPL_MAX_SOURCE && (values[num_values] = strtok_s(NULL, ",", &cptr)) != NULL) num_values ++; } #else while (num_values < PAPPL_MAX_SOURCE && (values[num_values] = strsep(&cptr, ",")) != NULL) num_values ++; #endif // _WIN32 if (num_values > 0) ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-ready", num_values, NULL, (const char * const *)values); free(cvalue); } if ((value = cupsGetOption("printer-darkness-configured", num_options, options)) != NULL) { if ((intvalue = (int)strtol(value, &end, 10)) >= 0 && intvalue <= 100 && errno != ERANGE && !*end) ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-darkness-configured", intvalue); } if ((value = cupsGetOption("printer-geo-location", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, value); if ((value = cupsGetOption("printer-location", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL, value); if ((value = cupsGetOption("printer-organization", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, value); if ((value = cupsGetOption("printer-organizational-unit", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, value); } else { if ((value = cupsGetOption("compression", num_options, options)) != NULL) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "compression", NULL, value); if ((value = cupsGetOption("page-ranges", num_options, options)) != NULL) { int first_page = 1, // First page last_page = INT_MAX; // Last page char *valptr = (char *)value;// Pointer into value if (isdigit(*valptr & 255)) first_page = (int)strtol(valptr, &valptr, 10); if (*valptr == '-') valptr ++; if (isdigit(*valptr & 255)) last_page = (int)strtol(valptr, &valptr, 10); ippAddRange(request, IPP_TAG_JOB, "page-ranges", first_page, last_page); } } if ((value = cupsGetOption("copies", num_options, options)) == NULL) value = cupsGetOption("copies-default", num_options, options); if (value && (intvalue = (int)strtol(value, &end, 10)) >= 1 && intvalue <= 9999 && errno != ERANGE && !*end) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "copies-default" : "copies", intvalue); if ((value = cupsGetOption("finishings", num_options, options)) == NULL) value = cupsGetOption("finishings-default", num_options, options); if (value) { // Get finishings enum values... cups_len_t num_enumvalues = 0; // Number of enum values int enumvalues[32]; // Enum values char keyword[128], // Current keyword/value *kptr; // Pointer into keyword/value while (*value && num_enumvalues < (cups_len_t)(sizeof(enumvalues) / sizeof(enumvalues[0]))) { for (kptr = keyword; *value && *value != ','; value ++) { if (kptr < (keyword + sizeof(keyword) - 1)) *kptr = *value; } *kptr = '\0'; if (isdigit(keyword[0] & 255)) enumvalues[num_enumvalues ++] = atoi(keyword); else if (keyword[0]) enumvalues[num_enumvalues ++] = ippEnumValue("finishings", keyword); } if (num_enumvalues > 0) ippAddIntegers(request, group_tag, IPP_TAG_ENUM, is_default ? "finishings-default" : "finishings", num_enumvalues, enumvalues); } value = cupsGetOption("media", num_options, options); if (media_left_offset || media_source || media_top_offset || media_tracking || media_type) { // Add media-col ipp_t *media_col = ippNew(); // media-col value pwg_media_t *pwg = pwgMediaForPWG(value); // Size if (pwg) { ipp_t *media_size = ippNew(); // media-size value ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", pwg->width); ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", pwg->length); ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size); ippDelete(media_size); } if (media_left_offset) ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-offset", get_length(media_left_offset)); if (media_source) ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-source", NULL, media_source); if (media_top_offset) ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-offset", get_length(media_top_offset)); if (media_tracking) ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-tracking", NULL, media_tracking); if (media_type) ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-type", NULL, media_type); ippAddCollection(request, group_tag, is_default ? "media-col-default" : "media-col", media_col); ippDelete(media_col); } else if (value) { // Add media ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, is_default ? "media-default" : "media", NULL, value); } if ((value = cupsGetOption("orientation-requested", num_options, options)) == NULL) value = cupsGetOption("orientation-requested-default", num_options, options); if (value) { if ((intvalue = ippEnumValue("orientation-requested", value)) != 0) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "orientation-requested-default" : "orientation-requested", intvalue); else if ((intvalue = (int)strtol(value, &end, 10)) >= IPP_ORIENT_PORTRAIT && intvalue <= IPP_ORIENT_NONE && errno != ERANGE && !*end) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "orientation-requested-default" : "orientation-requested", intvalue); } if ((value = cupsGetOption("output-bin", num_options, options)) == NULL) value = cupsGetOption("output-bin-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "output-bin-default" : "output-bin", NULL, value); if ((value = cupsGetOption("print-color-mode", num_options, options)) == NULL) value = cupsGetOption("print-color-mode-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "print-color-mode-default" : "print-color-mode", NULL, value); if ((value = cupsGetOption("print-content-optimize", num_options, options)) == NULL) value = cupsGetOption("print-content-optimize-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "print-content-optimize-mode-default" : "print-content-optimize", NULL, value); if ((value = cupsGetOption("print-darkness", num_options, options)) == NULL) value = cupsGetOption("print-darkness-default", num_options, options); if (value && (intvalue = (int)strtol(value, &end, 10)) >= -100 && intvalue <= 100 && errno != ERANGE && !*end) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "print-darkness-default" : "print-darkness", intvalue); if ((value = cupsGetOption("print-quality", num_options, options)) == NULL) value = cupsGetOption("print-quality-default", num_options, options); if (value) { if ((intvalue = ippEnumValue("print-quality", value)) != 0) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "print-quality-default" : "print-quality", intvalue); else if ((intvalue = (int)strtol(value, &end, 10)) >= IPP_QUALITY_DRAFT && intvalue <= IPP_QUALITY_HIGH && errno != ERANGE && !*end) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "print-quality-default" : "print-quality", intvalue); } if ((value = cupsGetOption("print-scaling", num_options, options)) == NULL) value = cupsGetOption("print-scaling-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "print-scaling-default" : "print-scaling", NULL, value); if ((value = cupsGetOption("print-speed", num_options, options)) == NULL) value = cupsGetOption("print-speed-default", num_options, options); if (value) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "print-speed-default" : "print-speed", get_length(value)); if ((value = cupsGetOption("printer-resolution", num_options, options)) == NULL) value = cupsGetOption("printer-resolution-default", num_options, options); if (value) { int xres, yres; // Resolution values char units[32]; // Resolution units if (sscanf(value, "%dx%d%31s", &xres, &yres, units) != 3) { if (sscanf(value, "%d%31s", &xres, units) != 2) { xres = 300; papplCopyString(units, "dpi", sizeof(units)); } yres = xres; } ippAddResolution(request, group_tag, is_default ? "printer-resolution-default" : "printer-resolution", !strcmp(units, "dpi") ? IPP_RES_PER_INCH : IPP_RES_PER_CM, xres, yres); } if ((value = cupsGetOption("sides", num_options, options)) == NULL) value = cupsGetOption("sides-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "sides-default" : "sides", NULL, value); // Vendor attributes/options if ((job_attrs = ippFindAttribute(supported, "job-creation-attributes-supported", IPP_TAG_KEYWORD)) != NULL) { cups_len_t i, // Looping var count; // Count const char *name; // Attribute name char defname[128], // xxx-default name supname[128]; // xxx-supported name ipp_attribute_t *attr; // Attribute for (i = 0, count = ippGetCount(job_attrs); i < count; i ++) { name = ippGetString(job_attrs, i, NULL); snprintf(defname, sizeof(defname), "%s-default", name); snprintf(supname, sizeof(supname), "%s-supported", name); if ((value = cupsGetOption(name, num_options, options)) == NULL) value = cupsGetOption(defname, num_options, options); if (!value) continue; if (!strcmp(name, "copies") || !strcmp(name, "finishings") || !strcmp(name, "media") || !strcmp(name, "multiple-document-handling") || !strcmp(name, "orientation-requested") || !strcmp(name, "output-bin") || !strcmp(name, "print-color-mode") || !strcmp(name, "print-content-optimize") || !strcmp(name, "print-darkness") || !strcmp(name, "print-quality") || !strcmp(name, "print-scaling") || !strcmp(name, "print-speed") || !strcmp(name, "printer-resolution") || !strcmp(name, "print-speed") || !strcmp(name, "sides")) continue; if ((attr = ippFindAttribute(supported, supname, IPP_TAG_ZERO)) != NULL) { switch (ippGetValueTag(attr)) { case IPP_TAG_BOOLEAN : ippAddBoolean(request, group_tag, is_default ? defname : name, !strcmp(value, "true")); break; case IPP_TAG_INTEGER : case IPP_TAG_RANGE : intvalue = (int)strtol(value, &end, 10); if (errno != ERANGE && !*end) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? defname : name, intvalue); break; case IPP_TAG_KEYWORD : ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? defname : name, NULL, value); break; default : break; } } else { ippAddString(request, group_tag, IPP_TAG_TEXT, is_default ? defname : name, NULL, value); } } } } // // '_papplMainloopAddPrinterURI()' - Add the printer-uri attribute and return a // resource path. // void _papplMainloopAddPrinterURI( ipp_t *request, // I - IPP request const char *printer_name, // I - Printer name char *resource, // I - Resource path buffer size_t rsize) // I - Size of buffer { char uri[1024], // printer-uri value *resptr; // Pointer into resource path snprintf(resource, rsize, "/ipp/print/%s", printer_name); for (resptr = resource + 11; *resptr; resptr ++) { if ((*resptr & 255) <= ' ' || strchr("\177/\\\'\"?#", *resptr)) *resptr = '_'; } // Eliminate duplicate and trailing underscores... resptr = resource + 11; while (*resptr) { if (resptr[0] == '_' && resptr[1] == '_') memmove(resptr, resptr + 1, strlen(resptr)); // Duplicate underscores else if (resptr[0] == '_' && !resptr[1]) *resptr = '\0'; // Trailing underscore else resptr ++; } httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, resource); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); } // // '_papplMainloopConnect()' - Connect to the local server. // http_t * // O - HTTP connection _papplMainloopConnect( const char *base_name, // I - Printer application name bool auto_start) // I - `true` to start server if not running { http_t *http; // HTTP connection char sockname[1024]; // Socket filename // See if the server is running... http = httpConnect(_papplMainloopGetServerPath(base_name, getuid(), sockname, sizeof(sockname)), _papplMainloopGetServerPort(base_name), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); #if !_WIN32 if (!http && getuid()) { // Try root server... http = httpConnect(_papplMainloopGetServerPath(base_name, 0, sockname, sizeof(sockname)), _papplMainloopGetServerPort(base_name), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); } #endif // !_WIN32 if (!http && auto_start) { // Nope, start it now... int tries; // Number of retries #if !_WIN32 pid_t server_pid; // Server process ID posix_spawnattr_t server_attrs; // Server process attributes #endif // !_WIN32 char * const server_argv[] = // Server command-line { _papplMainloopPath, "server", "-o", "private-server=true", NULL }; #if _WIN32 int status = (int)_spawnvpe(_P_NOWAIT, _papplMainloopPath, server_argv, environ); if (status != 0) { char status_str[32]; // Status string snprintf(status_str, sizeof(status_str), "%d", status); _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to start server: %s"), base_name, status_str); return (NULL); } #else posix_spawnattr_init(&server_attrs); posix_spawnattr_setpgroup(&server_attrs, 0); if (posix_spawn(&server_pid, _papplMainloopPath, NULL, &server_attrs, server_argv, environ)) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to start server: %s"), base_name, strerror(errno)); posix_spawnattr_destroy(&server_attrs); return (NULL); } posix_spawnattr_destroy(&server_attrs); #endif // _WIN32 // Wait for it to start... _papplMainloopGetServerPath(base_name, getuid(), sockname, sizeof(sockname)); for (tries = 0; tries < 40; tries ++) { usleep(250000); if ((http = httpConnect(_papplMainloopGetServerPath(base_name, getuid(), sockname, sizeof(sockname)), _papplMainloopGetServerPort(base_name), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL)) != NULL) break; } if (!http) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to connect to server: %s"), base_name, cupsGetErrorString()); } return (http); } // // '_papplMainloopConnectURI()' - Connect to an IPP printer directly. // http_t * // O - HTTP connection or `NULL` on error _papplMainloopConnectURI( const char *base_name, // I - Base Name const char *printer_uri, // I - Printer URI char *resource, // I - Resource path buffer size_t rsize) // I - Size of buffer { char scheme[32], // Scheme (ipp or ipps) userpass[256], // Username/password (unused) hostname[256]; // Hostname int port; // Port number http_encryption_t encryption; // Type of encryption to use http_t *http; // HTTP connection // First extract the components of the URI... if (httpSeparateURI(HTTP_URI_CODING_ALL, printer_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, (cups_len_t)rsize) < HTTP_URI_STATUS_OK) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Bad printer URI '%s'."), base_name, printer_uri); return (NULL); } if (strcmp(scheme, "ipp") && strcmp(scheme, "ipps")) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unsupported URI scheme '%s'."), base_name, scheme); return (NULL); } if (userpass[0]) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Warning - user credentials are not supported in URIs."), base_name); if (!strcmp(scheme, "ipps") || port == 443) encryption = HTTP_ENCRYPTION_ALWAYS; else encryption = HTTP_ENCRYPTION_IF_REQUESTED; if ((http = httpConnect(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL) _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to connect to printer at '%s:%d': %s"), base_name, hostname, port, cupsGetErrorString()); return (http); } // // '_papplMainloopGetDefaultPrinter' - Get the default printer. // char * // O - Default printer or `NULL` for none _papplMainloopGetDefaultPrinter( http_t *http, // I - HTTP connection char *buffer, // I - Buffer for printer name size_t bufsize) // I - Size of buffer { ipp_t *request, // IPP request *response; // IPP response const char *printer_name; // Printer name // Ask the server for its default printer request = ippNewRequest(IPP_OP_CUPS_GET_DEFAULT); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-name"); response = cupsDoRequest(http, request, "/ipp/system"); if ((printer_name = ippGetString(ippFindAttribute(response, "printer-name", IPP_TAG_NAME), 0, NULL)) != NULL) papplCopyString(buffer, printer_name, bufsize); else *buffer = '\0'; ippDelete(response); return (*buffer ? buffer : NULL); } // // '_papplMainloopGetServerPath()' - Get the UNIX domain socket for the server. // char * // O - Socket filename _papplMainloopGetServerPath( const char *base_name, // I - Base name uid_t uid, // I - UID for server char *buffer, // I - Buffer for filename size_t bufsize) // I - Size of buffer { #if _WIN32 // Server running as local service... (void)base_name; (void)uid; papplCopyString(buffer, "localhost", bufsize); #else const char *snap_common; // SNAP_COMMON environment variable if (uid) { // Per-user server... snprintf(buffer, bufsize, "%s/%s%d.sock", papplGetTempDir(), base_name, (int)uid); } else if ((snap_common = getenv("SNAP_COMMON")) != NULL) { // System server running as root inside a snap (https://snapcraft.io)... snprintf(buffer, bufsize, "%s/%s.sock", snap_common, base_name); } else { // System server running as root snprintf(buffer, bufsize, PAPPL_SOCKDIR "/%s.sock", base_name); } _PAPPL_DEBUG("Using domain socket '%s'.\n", buffer); #endif // _WIN32 return (buffer); } // // '_papplMainloopGetServerPort()' - Get the socket port number for the server. // int // O - Port number _papplMainloopGetServerPort( const char *base_name) // I - Base name of printer application { #if _WIN32 char path[1024]; // Registry path HKEY key; // Registry key DWORD dport = 0; // Port number value for registry // The server's port number is saved in SOFTWARE\appname\port snprintf(path, sizeof(path), "SOFTWARE\\%s", base_name); if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &key)) { // Was able to open the registry, get the port number... DWORD dsize = sizeof(dport); // Size of port number value RegGetValueA(key, NULL, "port", RRF_RT_REG_DWORD, NULL, &dport, &dsize); RegCloseKey(key); } return ((int)dport); #else // POSIX platforms use domain instead of TCP/IP sockets... (void)base_name; return (0); #endif // _WIN32 } // // 'get_length()' - Get a length in hundredths of millimeters. // static int // O - Length value get_length(const char *value) // I - Length string { double n; // Number char *units; // Pointer to units n = strtod(value, &units); if (units && !strcmp(units, "cm")) return ((int)(n * 1000.0)); if (units && !strcmp(units, "in")) return ((int)(n * 2540.0)); else if (units && !strcmp(units, "mm")) return ((int)(n * 100.0)); else if (units && !strcmp(units, "m")) return ((int)(n * 100000.0)); else return ((int)n); } pappl-1.4.9/pappl/mainloop.c000066400000000000000000000410331476704353100157520ustar00rootroot00000000000000// // Command line utilities for the Printer Application Framework // // Copyright © 2020-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers // #include "pappl-private.h" #if !_WIN32 # include #endif // !_WIN32 // // Local functions // static void usage(const char *base_name, bool with_autoadd); // // 'papplMainloop()' - Run a standard main loop for printer applications. // // This function runs a standard main loop for a printer application. The // "argc" and "argv" arguments are those provided to the `main` function. // // The "version" argument specifies a numeric version number for the printer // application that conforms to semantic versioning guidelines with up to four // numbers, for example "1.2.3.4". // // The "footer_html" argument specifies HTML text to use in the footer of the // web interface. If `NULL`, the footer is omitted. // // The "num_drivers", "drivers", and "driver_cb" arguments specify a list of // drivers and the driver callback for printers. Specify `0` and `NULL` if // the drivers are configured in the system callback. The "autoadd_cb" // argument specifies a callback for automatically adding new printers with the // "autoadd" sub-command and for auto-detecting the driver when adding manually. // // The "usage_cb" argument specifies a callback that displays a usage/help // summary. If `NULL`, a generic summary is shown as needed. // // The "subcmd_name" and "subcmd_cb" arguments specify the name and a callback // for a custom sub-command. If `NULL`, no custom sub-commands will be // supported. // // The "system_cb" argument specifies a function that will create a new // `pappl_system_t` object. If `NULL`, a default system object is created. // // The "data" argument provides application-specific data for each of the // callbacks. // int // O - Exit status papplMainloop( int argc, // I - Number of command line arguments char *argv[], // I - Command line arguments const char *version, // I - Version number const char *footer_html, // I - Footer HTML or `NULL` for none int num_drivers, // I - Number of drivers pappl_pr_driver_t *drivers, // I - Drivers pappl_pr_autoadd_cb_t autoadd_cb, // I - Auto-add callback or `NULL` for none pappl_pr_driver_cb_t driver_cb, // I - Driver callback const char *subcmd_name, // I - Sub-command name or `NULL` for none pappl_ml_subcmd_cb_t subcmd_cb, // I - Sub-command callback or `NULL` for none pappl_ml_system_cb_t system_cb, // I - System callback or `NULL` for default pappl_ml_usage_cb_t usage_cb, // I - Usage callback or `NULL` for default void *data) // I - Context pointer { const char *base_name; // Base Name int i, j; // Looping vars const char *opt; // Option character const char *subcommand = NULL; // Sub-command cups_len_t num_files = 0; // File count char *files[1000]; // Files array cups_len_t num_options = 0; // Number of options cups_option_t *options = NULL; // Options static const char * const subcommands[] = { // List of standard sub-commands "add", "autoadd", "cancel", "default", "delete", "devices", "drivers", "jobs", "modify", "options", "pause", "printers", "resume", "server", "shutdown", "status", "submit" }; #ifdef __APPLE__ const char *server_argv[7]; // New command arguments #endif // __APPLE__ // Range check input... if (argc < 1 || !argv) { fputs("ERROR: No command-line arguments were passed to papplMainloop.\n", stderr); return (1); } if (!version) { fputs("ERROR: No version number string was passed to papplMainloop.\n", stderr); return (1); } // Save the path to the printer application and get the base name. _papplMainloopPath = argv[0]; #if _WIN32 if ((base_name = strrchr(argv[0], '\\')) == NULL) if ((base_name = strrchr(argv[0], '/')) == NULL) base_name = argv[0]; #else base_name = basename(argv[0]); #endif // _WIN32 #ifdef __APPLE__ // When you click on the application icon, macOS' Finder will pass "-psn_..." // on the command-line. We also recognize when running the application from // within the .app bundle. If either is true, replace argc and argv to run a // server... if ((argc > 1 && !strncmp(argv[1], "-psn", 4)) || strstr(argv[0], ".app/Contents/MacOS/") != NULL) { server_argv[0] = argv[0]; server_argv[1] = "server"; server_argv[2] = "-o"; server_argv[3] = "log-file=syslog"; server_argv[4] = "-o"; server_argv[5] = "log-level=info"; server_argv[6] = NULL; argc = 6; argv = (char **)server_argv; } #endif // __APPLE__ // Parse the command-line... for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) { if (usage_cb) (*usage_cb)(data); else usage(base_name, autoadd_cb != NULL); return (0); } else if (!strcmp(argv[i], "--version")) { puts(version); return (0); } else if (!strcmp(argv[i], "--")) { // Filename follows i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing filename after '--'."), base_name); return (1); } else if (num_files >= (int)(sizeof(files) / sizeof(files[0]))) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Too many files."), base_name); return (1); } files[num_files ++] = argv[i]; } else if (!strncmp(argv[i], "--", 2)) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unknown option '%s'."), base_name, argv[i]); return (1); } else if (argv[i][0] == '-' && argv[i][1]) { for (opt = argv[i] + 1; *opt; opt ++) { switch (argv[i][1]) { case 'a': // -a (cancel-all) num_options = cupsAddOption("cancel-all", "true", num_options, &options); break; case 'd': // -d PRINTER i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing printer name after '-d'."), base_name); return (1); } num_options = cupsAddOption("printer-name", argv[i], num_options, &options); break; case 'h': // -d HOST i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing hostname after '-h'."), base_name); return (1); } num_options = cupsAddOption("server-hostname", argv[i], num_options, &options); break; case 'j': // -j JOB-ID i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing job ID after '-j'."), base_name); return (1); } num_options = cupsAddOption("job-id", argv[i], num_options, &options); break; case 'm': // -m DRIVER-NAME i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing driver name after '-m'."), base_name); return (1); } num_options = cupsAddOption("smi55357-driver", argv[i], num_options, &options); break; case 'n': // -n COPIES i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing copy count after '-n'."), base_name); return (1); } num_options = cupsAddOption("copies", argv[i], num_options, &options); break; case 'o': // -o "NAME=VALUE [... NAME=VALUE]" if (opt[1] && strchr(opt, '=')) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing space after '-o'."), base_name); return (1); } i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing option(s) after '-o'."), base_name); return (1); } num_options = cupsParseOptions(argv[i], /*end*/NULL, num_options, &options); break; case 't' : // -t TITLE i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing title after '-t'."), base_name); return (1); } num_options = cupsAddOption("job-name", argv[i], num_options, &options); break; case 'u': // -u PRINTER-URI i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing printer URI after '-u'."), base_name); return (1); } num_options = cupsAddOption("printer-uri", argv[i], num_options, &options); break; case 'v': // -v DEVICE-URI i ++; if (i >= argc) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Missing device URI after '-v'."), base_name); return (1); } num_options = cupsAddOption("smi55357-device-uri", argv[i], num_options, &options); break; default: _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unknown option '-%c'."), base_name, *opt); return (1); } } } else { // Skip "-" as needed... if (!strcmp(argv[i], "-")) { i ++; if (i >= argc) break; } // See if this is a standard sub-command... for (j = 0; j < (int)(sizeof(subcommands) / sizeof(subcommands[0])); j ++) { if (!strcmp(argv[i], subcommands[j])) { if (subcommand) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Cannot specify more than one sub-command."), base_name); return (1); } subcommand = argv[i]; break; } } if (j >= (int)(sizeof(subcommands) / sizeof(subcommands[0]))) { // Not a standard sub-command... if (subcmd_name && !strcmp(argv[i], subcmd_name)) { // Extension sub-command... if (subcommand) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Cannot specify more than one sub-command."), base_name); return (1); } subcommand = argv[i]; } else if (access(argv[i], R_OK)) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unable to access '%s': %s"), base_name, argv[i], strerror(errno)); return (1); } else if (num_files < (int)(sizeof(files) / sizeof(files[0]))) { // Filename... files[num_files ++] = argv[i]; } else { // Too many files... _papplLocPrintf(stderr, _PAPPL_LOC("%s: Too many files."), base_name); return (1); } } } } // Process sub-commands if (!subcommand || !strcmp(subcommand, "submit")) { return (_papplMainloopSubmitJob(base_name, num_options, options, num_files, files)); } else if (subcmd_name && !strcmp(subcommand, subcmd_name)) { return ((subcmd_cb)(base_name, (int)num_options, options, (int)num_files, files, data)); } else if (num_files > 0) { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Sub-command '%s' does not accept files."), base_name, subcommand); return (1); } else if (!strcmp(subcommand, "add")) { return (_papplMainloopAddPrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "autoadd")) { if (autoadd_cb) { return (_papplMainloopAutoAddPrinters(base_name, num_options, options)); } else { _papplLocPrintf(stderr, _PAPPL_LOC("%s: Sub-command 'autoadd' is not supported."), base_name); return (1); } } else if (!strcmp(subcommand, "cancel")) { return (_papplMainloopCancelJob(base_name, num_options, options)); } else if (!strcmp(subcommand, "default")) { return (_papplMainloopGetSetDefaultPrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "delete")) { return (_papplMainloopDeletePrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "devices")) { return (_papplMainloopShowDevices(base_name, num_options, options)); } else if (!strcmp(subcommand, "drivers")) { return (_papplMainloopShowDrivers(base_name, (cups_len_t)num_drivers, drivers, autoadd_cb, driver_cb, num_options, options, system_cb, data)); } else if (!strcmp(subcommand, "jobs")) { return (_papplMainloopShowJobs(base_name, num_options, options)); } else if (!strcmp(subcommand, "modify")) { return (_papplMainloopModifyPrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "options")) { return (_papplMainloopShowOptions(base_name, num_options, options)); } else if (!strcmp(subcommand, "pause")) { return (_papplMainloopPausePrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "printers")) { return (_papplMainloopShowPrinters(base_name, num_options, options)); } else if (!strcmp(subcommand, "resume")) { return (_papplMainloopResumePrinter(base_name, num_options, options)); } else if (!strcmp(subcommand, "server")) { return (_papplMainloopRunServer(base_name, version, footer_html, (cups_len_t)num_drivers, drivers, autoadd_cb, driver_cb, num_options, &options, system_cb, data)); } else if (!strcmp(subcommand, "shutdown")) { return (_papplMainloopShutdownServer(base_name, num_options, options)); } else if (!strcmp(subcommand, "status")) { return (_papplMainloopShowStatus(base_name, num_options, options)); } else { // This should never happen... _papplLocPrintf(stderr, _PAPPL_LOC("%s: Unknown sub-command '%s'."), base_name, subcommand); return (1); } } // // 'usage()' - Show default usage. // static void usage(const char *base_name, // I - Base name of application bool with_autoadd) // I - `true` if autoadd command is supported { _papplLocPrintf(stdout, _PAPPL_LOC("Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" " %s [OPTIONS] [FILENAME]\n" " %s [OPTIONS] -"), base_name, base_name, base_name); puts(""); _papplLocPrintf(stdout, _PAPPL_LOC("Sub-commands:")); _papplLocPrintf(stdout, _PAPPL_LOC(" add PRINTER Add a printer.")); if (with_autoadd) _papplLocPrintf(stdout, _PAPPL_LOC(" autoadd Automatically add supported printers.")); _papplLocPrintf(stdout, _PAPPL_LOC(" cancel Cancel one or more jobs.")); _papplLocPrintf(stdout, _PAPPL_LOC(" default Set the default printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" delete Delete a printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" devices List devices.")); _papplLocPrintf(stdout, _PAPPL_LOC(" drivers List drivers.")); _papplLocPrintf(stdout, _PAPPL_LOC(" jobs List jobs.")); _papplLocPrintf(stdout, _PAPPL_LOC(" modify Modify a printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" options List printer options.")); _papplLocPrintf(stdout, _PAPPL_LOC(" pause Pause printing for a printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" printers List printers.")); _papplLocPrintf(stdout, _PAPPL_LOC(" resume Resume printing for a printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" server Run a server.")); _papplLocPrintf(stdout, _PAPPL_LOC(" shutdown Shutdown a running server.")); _papplLocPrintf(stdout, _PAPPL_LOC(" status Show server/printer/job status.")); _papplLocPrintf(stdout, _PAPPL_LOC(" submit Submit a file for printing.")); puts(""); _papplLocPrintf(stdout, _PAPPL_LOC("Options:")); _papplLocPrintf(stdout, _PAPPL_LOC(" -a Cancel all jobs (cancel).")); _papplLocPrintf(stdout, _PAPPL_LOC(" -d PRINTER Specify printer.")); _papplLocPrintf(stdout, _PAPPL_LOC(" -j JOB-ID Specify job ID (cancel).")); _papplLocPrintf(stdout, _PAPPL_LOC(" -m DRIVER-NAME Specify driver (add/modify).")); _papplLocPrintf(stdout, _PAPPL_LOC(" -n COPIES Specify number of copies (submit).")); _papplLocPrintf(stdout, _PAPPL_LOC(" -o NAME=VALUE Specify option (add,modify,server,submit).")); _papplLocPrintf(stdout, _PAPPL_LOC(" -u URI Specify ipp: or ipps: printer/server.")); _papplLocPrintf(stdout, _PAPPL_LOC(" -v DEVICE-URI Specify socket: or usb: device (add/modify).")); } pappl-1.4.9/pappl/mainloop.h000066400000000000000000000023731476704353100157630ustar00rootroot00000000000000// // Mainloop header file for the Printer Application Framework // // Copyright © 2020-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_MAINLOOP_H_ # define _PAPPL_MAINLOOP_H_ # include "base.h" # include "system.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Types... // typedef int (*pappl_ml_subcmd_cb_t)(const char *base_name, int num_options, cups_option_t *options, int num_files, char **files, void *data); // Sub-command callback typedef pappl_system_t *(*pappl_ml_system_cb_t)(int num_options, cups_option_t *options, void *data); // System callback typedef void (*pappl_ml_usage_cb_t)(void *data); // Program usage callback // // Functions... // extern int papplMainloop(int argc, char *argv[], const char *version, const char *footer_html, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_driver_cb_t driver_cb, const char *subcmd_name, pappl_ml_subcmd_cb_t subcmd_cb, pappl_ml_system_cb_t system_cb, pappl_ml_usage_cb_t usage_cb, void *data) _PAPPL_PUBLIC; extern void papplMainloopShutdown(void) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_MAINLOOP_H_ pappl-1.4.9/pappl/makeresheader.sh000077500000000000000000000014431476704353100171300ustar00rootroot00000000000000#!/bin/sh # # Resource generating script for the Printer Application Framework # # Copyright © 2019-2021 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # # Usage: # # pappl-makeresheader filename [ ... filename ] >filename.h # for file in "$@"; do varname=$(basename "$file" | sed -e '1,$s/[ -.]/_/g') echo "/* $file */" case $file in *.icc | *.jpg | *.otf | *.otc | *.png | *.ttc | *.ttf | *.woff | *.woff2) echo "static unsigned char $varname[] = {" od -t u1 -A n -v "$file" | awk '{for (i = 1; i <= NF; i ++) printf("%s,", $i); print "";}' echo "};" ;; *) echo "static const char * const $varname =" sed -e '1,$s/\\/\\\\/g' -e '1,$s/"/\\"/g' "$file" | awk '{print "\"" $0 "\\n\""}' echo ";" ;; esac done pappl-1.4.9/pappl/pappl-private.h000066400000000000000000000010751476704353100167270ustar00rootroot00000000000000// // Private header file for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_PAPPL_PRIVATE_H_ # define _PAPPL_PAPPL_PRIVATE_H_ # include "client-private.h" # include "device-private.h" # include "dnssd-private.h" # include "job-private.h" # include "loc-private.h" # include "log-private.h" # include "mainloop-private.h" # include "printer-private.h" # include "system-private.h" #endif // !_PAPPL_PAPPL_PRIVATE_H_ pappl-1.4.9/pappl/pappl.h000066400000000000000000000007071476704353100152600ustar00rootroot00000000000000// // Public header file for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_PAPPL_H_ # define _PAPPL_PAPPL_H_ # include "device.h" # include "system.h" # include "client.h" # include "printer.h" # include "job.h" # include "loc.h" # include "log.h" # include "mainloop.h" #endif // !_PAPPL_PAPPL_H_ pappl-1.4.9/pappl/pappl.pc.in000066400000000000000000000006771476704353100160460ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: PAPPL Description: Printer Application Framework/Library Version: @PAPPL_VERSION@ URL: https://www.msweet.org/pappl Requires: @PKGCONFIG_REQUIRES@ Requires.private: @PKGCONFIG_AVAHI@ @PKGCONFIG_LIBJPEG@ @PKGCONFIG_LIBPNG@ @PKGCONFIG_LIBUSB@ @PKGCONFIG_TLS@ zlib >= 1.0 Libs: @PKGCONFIG_LIBS@ Libs.private: @PKGCONFIG_LIBS_PRIVATE@ Cflags: @PKGCONFIG_CFLAGS@ pappl-1.4.9/pappl/parse-lock-log.c000066400000000000000000000214131476704353100167530ustar00rootroot00000000000000// // Utility to parse the PAPPL rwlock logs. // // Usage: // // ./parse-lock-log FILENAME.log // // Copyright © 2022 by Michael R Sweet // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include #include #include #include // Uncomment the following to see verbose output... //#define SHOW_BLOCKING_LOCKS 1 // // Limits... // #define MAX_THREADS 1000 #define MAX_OBJS 10000 // // Types/structures... // typedef unsigned long long log_addr_t; // Thread/object address typedef struct log_obj_s // Object information { log_addr_t address; // Object address char name[256]; // Object name int num_wr_threads; // Number of writer threads, if any log_addr_t wr_threads[MAX_THREADS]; // Writer threads char wr_functions[MAX_THREADS][32]; // Writer functions int num_rd_threads; // Number of reader threads, if any log_addr_t rd_threads[MAX_THREADS]; // Reader threads char rd_functions[MAX_THREADS][32]; } log_obj_t; // // 'main()' - Main entry. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { FILE *fp; // Log file char line[1024], // Line *ptr; // Pointer into line log_addr_t thread; // Thread char *function; // Function name char action; // First character of action ("rdlock", "wrlock", "unlock") log_addr_t obj; // Object char *objname; // Object name int i, j; // Looping vars int num_objs = 0; // Number of objects log_obj_t *objs, // Objects *curobj; // Current object int errors = 0; // Number of errors // Check command-line... if (argc != 2) { fputs("Usage: parse-lock-log FILENAME.log\n", stderr); return (1); } if ((fp = fopen(argv[1], "r")) == NULL) { perror(argv[1]); return (1); } if ((objs = calloc(MAX_OBJS, sizeof(log_obj_t))) == NULL) { perror("Unable to allocate objects"); return (1); } // Scan log... while (fgets(line, sizeof(line), fp)) { // Parse log line of the following format: // // THREAD/FUNCTION: ACTION OBJ(OBJNAME) thread = strtoull(line, &ptr, 16); if (!ptr || *ptr != '/' || !ptr[1]) continue; function = ptr + 1; if ((ptr = strchr(function, ':')) == NULL) continue; *ptr++ = '\0'; while (*ptr && isspace(*ptr)) ptr ++; if (strncmp(ptr, "rdlock ", 7) && strncmp(ptr, "unlock ", 7) && strncmp(ptr, "wrlock ", 7)) continue; action = *ptr; obj = strtoull(ptr + 7, &ptr, 16); if (!ptr || *ptr != '(') continue; objname = ptr + 1; if ((ptr = strchr(objname, ')')) == NULL) continue; *ptr = '\0'; // Find the object... for (i = 0, curobj = objs; i < num_objs; i ++, curobj ++) { if (curobj->address == obj) break; } if (i >= num_objs) { // New object... num_objs ++; if (num_objs > MAX_OBJS) { fprintf(stderr, "ERROR: Reached limit of %d objects.\n", MAX_OBJS); return (1); } memset(curobj, 0, sizeof(log_obj_t)); strncpy(curobj->name, objname, sizeof(curobj->name) - 1); curobj->address = obj; } // Now process the rdlock, unlock, or wrlock action... if (action == 'r') { // rdlock if (curobj->num_wr_threads) { // Report on active writer locks... for (i = 0; i < curobj->num_wr_threads; i ++) { if (curobj->wr_threads[i] == thread) { printf("%llX/%s trying to get a read lock while holding a write lock (%s).\n", thread, function, curobj->wr_functions[i]); errors ++; break; } } #if SHOW_BLOCKING_LOCKS if (i >= curobj->num_wr_threads) { printf("DEBUG: %llX/%s trying to get a read lock while write lock held by", thread, function); for (i = 0; i < curobj->num_wr_threads; i ++) printf(" %llX", curobj->wr_threads[i]); putchar('\n'); } #endif // SHOW_BLOCKING_LOCKS } // Check for extra read locks... for (i = 0; i < curobj->num_rd_threads; i ++) { if (curobj->rd_threads[i] == thread) { printf("%llX/%s trying to get a read lock while holding a read lock.\n", thread, function); errors ++; continue; } } // Add read lock... if (curobj->num_rd_threads >= MAX_THREADS) { fprintf(stderr, "ERROR: Reached limit of %d threads.\n", MAX_THREADS); return (1); } curobj->rd_threads[curobj->num_rd_threads] = thread; strncpy(curobj->rd_functions[curobj->num_rd_threads], function, sizeof(curobj->rd_functions[0]) - 1); curobj->num_rd_threads ++; } else if (action == 'u') { // unlock if (curobj->num_rd_threads == 0 && curobj->num_wr_threads == 0) { printf("%llX/%s trying to unlock but there are no locks.\n", thread, function); errors ++; continue; } for (i = 0; i < curobj->num_rd_threads; i ++) { if (curobj->rd_threads[i] == thread) break; } for (j = 0; j < curobj->num_wr_threads; j ++) { if (curobj->wr_threads[j] == thread) break; } if (i >= curobj->num_rd_threads && j >= curobj->num_wr_threads) { printf("%llX/%s trying to unlock but does not hold a lock.\n", thread, function); errors ++; continue; } if (i < curobj->num_rd_threads) { // Remove thread from read locks curobj->num_rd_threads --; if (i < curobj->num_rd_threads) { memmove(curobj->rd_threads + i, curobj->rd_threads + i + 1, (size_t)(curobj->num_rd_threads - i) * sizeof(log_addr_t)); memmove(curobj->rd_functions[i], curobj->rd_functions[i + 1], (size_t)(curobj->num_rd_threads - i) * sizeof(curobj->rd_functions[0])); } } if (j < curobj->num_wr_threads) { // Remove thread from write locks curobj->num_wr_threads --; if (j < curobj->num_wr_threads) { memmove(curobj->wr_threads + j, curobj->wr_threads + j + 1, (size_t)(curobj->num_wr_threads - j) * sizeof(log_addr_t)); memmove(curobj->wr_functions[j], curobj->wr_functions[j + 1], (size_t)(curobj->num_wr_threads - j) * sizeof(curobj->wr_functions[0])); } } } else { // wrlock for (i = 0; i < curobj->num_rd_threads; i ++) { if (curobj->rd_threads[i] == thread) { printf("%llX/%s trying to get a write lock while holding a read lock (%s).\n", thread, function, curobj->rd_functions[i]); errors ++; break; } } #if SHOW_BLOCKING_LOCKS if (i >= curobj->num_rd_threads && i) { printf("DEBUG: %llX/%s trying to get a write lock while read lock held by", thread, function); for (i = 0; i < curobj->num_rd_threads; i ++) printf(" %llX", curobj->rd_threads[i]); putchar('\n'); } #endif // SHOW_BLOCKING_LOCKS for (i = 0; i < curobj->num_wr_threads; i ++) { if (curobj->wr_threads[i] == thread) { printf("%llX/%s trying to get a write lock while holding a write lock.\n", thread, function); errors ++; continue; } } #if SHOW_BLOCKING_LOCKS if (i >= curobj->num_wr_threads && i) { printf("DEBUG: %llX/%s trying to get a write lock while write lock held by", thread, function); for (i = 0; i < curobj->num_wr_threads; i ++) printf(" %llX", curobj->wr_threads[i]); putchar('\n'); } #endif // SHOW_BLOCKING_LOCKS // Add write lock... if (curobj->num_wr_threads >= MAX_THREADS) { fprintf(stderr, "ERROR: Reached limit of %d threads.\n", MAX_THREADS); return (1); } curobj->wr_threads[curobj->num_wr_threads] = thread; strncpy(curobj->wr_functions[curobj->num_wr_threads], function, sizeof(curobj->wr_functions[0]) - 1); curobj->num_wr_threads ++; } } // Check objects... puts("\nSummary:\n"); printf(" %d object(s) with %d error(s) in run\n", num_objs, errors); for (i = num_objs, curobj = objs; i > 0; i --, curobj ++) { if (curobj->num_wr_threads) { printf(" %llX(%s) still has %d write lock(s):", curobj->address, curobj->name, curobj->num_wr_threads); for (j = 0; j < curobj->num_wr_threads; j ++) printf(" %llX/%s", curobj->wr_threads[j], curobj->wr_functions[j]); putchar('\n'); } if (curobj->num_rd_threads) { printf(" %llX(%s) still has %d read lock(s):", curobj->address, curobj->name, curobj->num_rd_threads); for (j = 0; j < curobj->num_rd_threads; j ++) printf(" %llX/%s", curobj->rd_threads[j], curobj->rd_functions[j]); putchar('\n'); } } // Clean up and return... fclose(fp); return (0); } pappl-1.4.9/pappl/printer-accessors.c000066400000000000000000001077161476704353100176150ustar00rootroot00000000000000// // Printer accessor functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "printer-private.h" #include "job-private.h" #include "system-private.h" // // 'papplPrinterCloseDevice()' - Close the device associated with the printer. // // This function closes the device for a printer. The device must have been // previously opened using the @link papplPrinterOpenDevice@ function. // void papplPrinterCloseDevice( pappl_printer_t *printer) // I - Printer { if (!printer) return; _papplRWLockWrite(printer); if (printer->device && printer->device_in_use) { printer->device_in_use = false; if (cupsArrayGetCount(printer->active_jobs) > 0 && !printer->processing_job) _papplPrinterCheckJobsNoLock(printer); if (printer->state != IPP_PSTATE_PROCESSING) { // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Closing device."); papplDeviceClose(printer->device); printer->device = NULL; } } _papplRWUnlock(printer); } // // 'papplPrinterDisable()' - Stop accepting jobs on a printer. // // This function stops accepting jobs on a printer. // void papplPrinterDisable( pappl_printer_t *printer) // I - Printer { if (printer) { printer->is_accepting = false; papplSystemAddEvent(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, NULL); } } // // 'papplPrinterEnable()' - Start accepting jobs on a printer. // // This function starts accepting jobs on a printer. // void papplPrinterEnable( pappl_printer_t *printer) // I - Printer { if (printer) { printer->is_accepting = true; papplSystemAddEvent(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, NULL); } } // // 'papplPrinterGetContact()' - Get the "printer-contact" value. // // This function copies the current printer contact information to the buffer // pointed to by the "contact" argument. // pappl_contact_t * // O - Contact papplPrinterGetContact( pappl_printer_t *printer, // I - Printer pappl_contact_t *contact) // O - Contact { if (!printer || !contact) { if (contact) memset(contact, 0, sizeof(pappl_contact_t)); return (contact); } _papplRWLockRead(printer); *contact = printer->contact; _papplRWUnlock(printer); return (contact); } // // 'papplPrinterGetDeviceID()' - Get the IEEE-1284 device ID of the printer. // // This function returns the IEEE-1284 device ID of the printer. // const char * // O - IEEE-1284 device ID string papplPrinterGetDeviceID( pappl_printer_t *printer) // I - Printer { return (printer ? printer->device_id : NULL); } // // 'papplPrinterGetDeviceURI()' - Get the URI of the device associated with the // printer. // // This function returns the device URI for the printer. // const char * // O - Device URI string papplPrinterGetDeviceURI( pappl_printer_t *printer) // I - Printer { return (printer ? printer->device_uri : "file:///dev/null"); } // // 'papplPrinterGetDNSSDName()' - Get the current DNS-SD service name. // // This function copies the current DNS-SD service name to the buffer pointed // to by the "buffer" argument. // char * // O - DNS-SD service name or `NULL` for none papplPrinterGetDNSSDName( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->dns_sd_name || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->dns_sd_name, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetGeoLocation()' - Get the current geo-location as a "geo:" // URI. // // This function copies the currently configured geographic location as a "geo:" // URI to the buffer pointed to by the "buffer" argument. // char * // O - "geo:" URI or `NULL` for unknown papplPrinterGetGeoLocation( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->geo_location || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->geo_location, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetID()' - Get the printer ID. // // This function returns the printer's unique positive integer identifier. // int // O - "printer-id" value or `0` for none papplPrinterGetID( pappl_printer_t *printer) // I - Printer { return (printer ? printer->printer_id : 0); } // // 'papplPrinterGetImpressionsCompleted()' - Get the number of impressions // (sides) that have been printed. // // This function returns the number of impressions that have been printed. An // impression is one side of an output page. // int // O - Number of printed impressions/sides papplPrinterGetImpressionsCompleted( pappl_printer_t *printer) // I - Printer { return (printer ? printer->impcompleted : 0); } // // 'papplPrinterGetLocation()' - Get the location string. // // This function copies the printer's human-readable location to the buffer // pointed to by the "buffer" argument. // char * // O - Location or `NULL` for none papplPrinterGetLocation( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->location || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->location, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetMaxActiveJobs()' - Get the maximum number of active (queued) // jobs allowed by the printer. // // This function returns the maximum number of active jobs that the printer // supports, as configured by the @link papplPrinterSetMaxActiveJobs@ function. // int // O - Maximum number of active jobs, `0` for unlimited papplPrinterGetMaxActiveJobs( pappl_printer_t *printer) // I - Printer { return (printer ? printer->max_active_jobs : 0); } // // 'papplPrinterGetMaxCompletedJobs()' - Get the maximum number of jobs retained // for history by the printer. // // This function returns the maximum number of jobs that are retained in the // job history as configured by the @link papplPrinterSetMaxCompletedJobs@ // function. // int // O - Maximum number of completed jobs, `0` for unlimited papplPrinterGetMaxCompletedJobs( pappl_printer_t *printer) // I - Printer { return (printer ? printer->max_completed_jobs : 0); } // // 'papplPrinterGetMaxPreservedJobs()' - Get the maximum number of jobs // preserved by the printer. // // This function returns the maximum number of jobs that are retained (including // document data) in the job history as configured by the // @link papplPrinterSetMaxPreservedJobs@ function. // int // O - Maximum number of preserved jobs, `0` for none papplPrinterGetMaxPreservedJobs( pappl_printer_t *printer) // I - Printer { return (printer ? printer->max_preserved_jobs : 0); } // // 'papplPrinterGetName()' - Get the printer name. // // This function returns the printer's human-readable name. // const char * // O - Printer name papplPrinterGetName( pappl_printer_t *printer) // I - Printer { return (printer ? printer->name : NULL); } // // 'papplPrinterGetNextJobID()' - Get the next job ID. // // This function returns the positive integer identifier that will be used for // the next job that is created. // int // O - Next job ID or `0` for none papplPrinterGetNextJobID( pappl_printer_t *printer) // I - Printer { return (printer ? printer->next_job_id : 0); } // // 'papplPrinterGetNumberOfActiveJobs()' - Get the number of active print jobs. // // This function returns the number of print jobs that are either printing or // waiting to be printed. // int // O - Number of active print jobs papplPrinterGetNumberOfActiveJobs( pappl_printer_t *printer) // I - Printer { return (printer ? (int)cupsArrayGetCount(printer->active_jobs) : 0); } // // 'papplPrinterGetNumberOfCompletedJobs()' - Get the number of completed print // jobs. // // This function returns the number of print jobs that have been aborted, // canceled, or completed. // int // O - Number of completed print jobs papplPrinterGetNumberOfCompletedJobs( pappl_printer_t *printer) // I - Printer { return (printer ? (int)cupsArrayGetCount(printer->completed_jobs) : 0); } // // 'papplPrinterGetNumberOfJobs()' - Get the total number of print jobs. // // This function returns the number of print jobs that are printing, waiting // to be printed, have been aborted, have been canceled, or have completed. // int // O - Total number of print jobs papplPrinterGetNumberOfJobs( pappl_printer_t *printer) // I - Printer { return (printer ? (int)cupsArrayGetCount(printer->all_jobs) : 0); } // // 'papplPrinterGetOrganization()' - Get the organization name. // // This function copies the printer's organization name to the buffer pointed // to by the "buffer" argument. // char * // O - Organization name or `NULL` for none papplPrinterGetOrganization( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->organization || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->organization, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetOrganizationalUnit()' - Get the organizational unit name. // // This function copies the printer's organizational unit name to the buffer // pointed to by the "buffer" argument. // char * // O - Organizational unit name or `NULL` for none papplPrinterGetOrganizationalUnit( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->org_unit || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->org_unit, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetPath()' - Get the URL path for a printer web page. // // This function generates and returns the URL path for the printer's web page. // The "subpath" argument specifies an optional sub-path for a specific printer // web page. // char * // O - URI path or `NULL` on error papplPrinterGetPath( pappl_printer_t *printer, // I - Printer const char *subpath, // I - Sub-path or `NULL` for none char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !buffer || bufsize < 32) { if (buffer) *buffer = '\0'; return (NULL); } if (subpath) snprintf(buffer, bufsize, "%s/%s", printer->uriname, subpath); else papplCopyString(buffer, printer->uriname, bufsize); return (buffer); } // // 'papplPrinterGetPrintGroup()' - Get the print authorization group, if any. // // This function copies the printer's authorization group name to the buffer // pointed to by the "buffer" argument. // char * // O - Print authorization group name or `NULL` for none papplPrinterGetPrintGroup( pappl_printer_t *printer, // I - Printer char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (!printer || !printer->print_group || !buffer || bufsize == 0) { if (buffer) *buffer = '\0'; return (NULL); } _papplRWLockRead(printer); papplCopyString(buffer, printer->print_group, bufsize); _papplRWUnlock(printer); return (buffer); } // // 'papplPrinterGetReasons()' - Get the current "printer-state-reasons" bit values. // // This function returns the current printer state reasons bitfield, which can // be updated by the printer driver and/or by the @link papplPrinterSetReasons@ // function. // pappl_preason_t // O - "printer-state-reasons" bit values papplPrinterGetReasons( pappl_printer_t *printer) // I - Printer { pappl_preason_t ret = PAPPL_PREASON_NONE; // Return value if (printer) { _papplRWLockRead(printer); if (!printer->device_in_use && !printer->processing_job && (time(NULL) - printer->status_time) > 1 && printer->driver_data.status_cb) { // Update printer status... _papplRWUnlock(printer); (printer->driver_data.status_cb)(printer); _papplRWLockRead(printer); printer->status_time = time(NULL); } ret = printer->state_reasons; _papplRWUnlock(printer); } return (ret); } // // 'papplPrinterGetState()' - Get the current "printer-state" value. // // This function returns the current printer state as an enumeration: // // - `IPP_PSTATE_IDLE`: The printer is idle and has no jobs to process. // - `IPP_PSTATE_PROCESSING`: The printer is processing a job and/or producing // output. // - `IPP_PSTATE_STOPPED`: The printer is stopped for maintenance. // ipp_pstate_t // O - "printer-state" value papplPrinterGetState( pappl_printer_t *printer) // I - Printer { return (printer ? printer->state : IPP_PSTATE_STOPPED); } // // 'papplPrinterGetSupplies()' - Get the current "printer-supplies" values. // // This function copies the current printer supply values to the specified // array. The "max_supplies" and "supplies" arguments can be `0` and `NULL` // to query the number of supplies used. // // The return value is the actual number of supplies used by the printer, // regardless of the size of the array. // int // O - Number of values papplPrinterGetSupplies( pappl_printer_t *printer, // I - Printer int max_supplies, // I - Maximum number of supplies pappl_supply_t *supplies) // I - Array for supplies { int count; // Number of supplies if (!printer || max_supplies < 0 || (max_supplies > 0 && !supplies)) return (0); if (max_supplies == 0) return (printer->num_supply); memset(supplies, 0, (size_t)max_supplies * sizeof(pappl_supply_t)); _papplRWLockRead(printer); if ((count = printer->num_supply) > max_supplies) count = max_supplies; memcpy(supplies, printer->supply, (size_t)count * sizeof(pappl_supply_t)); _papplRWUnlock(printer); return (count); } // // 'papplPrinterGetSystem()' - Get the system associated with the printer. // // This function returns a pointer to the system object that contains the // printer. // pappl_system_t * // O - System papplPrinterGetSystem( pappl_printer_t *printer) // I - Printer { return (printer ? printer->system : NULL); } // // 'papplPrinterHoldNewJobs()' - Hold new jobs for printing. // // This function holds any new jobs for printing and is typically used prior to // performing printer maintenance. Existing jobs will finish printing but new // jobs will be held until you call @link papplPrinterReleaseHeldNewJobs@. // bool // O - `true` on success, `false` on failure papplPrinterHoldNewJobs( pappl_printer_t *printer) // I - Printer { bool ret = false; // Return value // Range check input... if (!printer) return (false); // See if we need to change things... _papplRWLockWrite(printer); if (!printer->hold_new_jobs) { // Set the 'hold-new-jobs' flag... printer->hold_new_jobs = true; printer->config_time = time(NULL); ret = true; // Notify of the change in state... _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_CONFIG_CHANGED, "Holding new jobs."); } _papplRWUnlock(printer); if (ret) _papplSystemConfigChanged(printer->system); return (ret); } // // 'papplPrinterIsAcceptingJobs()' - Return whether the printer is accepting jobs. // // This function returns a boolean value indicating whether a printer is // accepting jobs. // bool // O - `true` if the printer is accepting jobs, `false` otherwise papplPrinterIsAcceptingJobs( pappl_printer_t *printer) // I - Printer { bool is_accepting; // Return value // Range check input... if (!printer) return (false); // Lock and grab value... _papplRWLockRead(printer); is_accepting = printer->is_accepting; _papplRWUnlock(printer); return (is_accepting); } // // 'papplPrinterIsDeleted()' - Return whether a printer is in the process of being deleted. // // This function returns a boolean value indicating whether a printer is being // deleted. // bool // O - `true` is printer is being deleted, `false` otherwise papplPrinterIsDeleted( pappl_printer_t *printer) // I - Printer { bool is_deleted; // Return value // Range check input... if (!printer) return (false); // Lock and grab value... _papplRWLockRead(printer); is_deleted = printer->is_deleted; _papplRWUnlock(printer); return (is_deleted); } // // 'papplPrinterIsHoldingNewJobs()' - Return whether the printer is holding new jobs. // // This function returns a boolean value indicating whether a printer is // holding new jobs. // bool // O - `true` if the printer is holding new jobs, `false` otherwise papplPrinterIsHoldingNewJobs( pappl_printer_t *printer) // I - Printer { bool hold_new_jobs; // Return value // Range check input... if (!printer) return (false); // Lock and grab value... _papplRWLockRead(printer); hold_new_jobs = printer->hold_new_jobs; _papplRWUnlock(printer); return (hold_new_jobs); } // // 'papplPrinterIterateActiveJobs()' - Iterate over the active jobs. // // This function iterates over jobs that are either printing or waiting to be // printed. The specified callback "cb" will be called once per job with the // data pointer "data". // // The "job_index" argument specifies the first job in the list to iterate, // where `1` is the first job, etc. The "limit" argument specifies the maximum // number of jobs to iterate - use `0` to iterate an unlimited number of jobs. // void papplPrinterIterateActiveJobs( pappl_printer_t *printer, // I - Printer pappl_job_cb_t cb, // I - Callback function void *data, // I - Callback data int job_index, // I - First job to iterate (1-based) int limit) // I - Maximum jobs to iterate or `0` for no limit { pappl_job_t *job; // Current job cups_len_t j, // Looping var jcount; // Number of jobs int count; // Number of jobs iterated if (!printer || !cb) return; _papplRWLockRead(printer); // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the active_jobs array. if (limit <= 0) limit = INT_MAX; for (count = 0, j = (cups_len_t)job_index - 1, jcount = cupsArrayGetCount(printer->active_jobs); j < jcount && count < limit; j ++, count ++) { job = (pappl_job_t *)cupsArrayGetElement(printer->active_jobs, j); (cb)(job, data); } _papplRWUnlock(printer); } // // 'papplPrinterIterateAllJobs()' - Iterate over all the jobs. // // This function iterates over all jobs. The specified callback "cb" will be // called once per job with the data pointer "data". // // The "job_index" argument specifies the first job in the list to iterate, // where `1` is the first job, etc. The "limit" argument specifies the maximum // number of jobs to iterate - use `0` to iterate an unlimited number of jobs. // void papplPrinterIterateAllJobs( pappl_printer_t *printer, // I - Printer pappl_job_cb_t cb, // I - Callback function void *data, // I - Callback data int job_index, // I - First job to iterate (1-based) int limit) // I - Maximum jobs to iterate, `0` for no limit { pappl_job_t *job; // Current job cups_len_t j, // Looping var jcount; // Number of jobs int count; // Number of jobs iterated if (!printer || !cb) return; _papplRWLockRead(printer); // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the all_jobs array. if (limit <= 0) limit = INT_MAX; for (count = 0, j = (cups_len_t)job_index - 1, jcount = cupsArrayGetCount(printer->all_jobs); j < jcount && count < limit; j ++, count ++) { job = (pappl_job_t *)cupsArrayGetElement(printer->all_jobs, j); (cb)(job, data); } _papplRWUnlock(printer); } // // 'papplPrinterIterateCompletedJobs()' - Iterate over the completed jobs. // // This function iterates over jobs that are aborted, canceled, or completed. // The specified callback "cb" will be called once per job with the data pointer // "data". // // The "job_index" argument specifies the first job in the list to iterate, // where `1` is the first job, etc. The "limit" argument specifies the maximum // number of jobs to iterate - use `0` to iterate an unlimited number of jobs. // void papplPrinterIterateCompletedJobs( pappl_printer_t *printer, // I - Printer pappl_job_cb_t cb, // I - Callback function void *data, // I - Callback data int job_index, // I - First job to iterate (1-based) int limit) // I - Maximum jobs to iterate, `0` for no limit { pappl_job_t *job; // Current job cups_len_t j, // Looping var jcount; // Number of jobs int count; // Number of jobs iterated if (!printer || !cb) return; _papplRWLockRead(printer); // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the completed_jobs array. if (limit <= 0) limit = INT_MAX; for (count = 0, j = (cups_len_t)job_index - 1, jcount = cupsArrayGetCount(printer->completed_jobs); j < jcount && count < limit; j ++, count ++) { job = (pappl_job_t *)cupsArrayGetElement(printer->completed_jobs, j); (cb)(job, data); } _papplRWUnlock(printer); } // // 'papplPrinterOpenDevice()' - Open the device associated with a printer. // // This function opens the printer's device. `NULL` is returned if the device // is already in use, for example while a job is being printed. // // The returned device must be closed using the @link papplPrinterCloseDevice@ // function. // pappl_device_t * // O - Device or `NULL` if not possible papplPrinterOpenDevice( pappl_printer_t *printer) // I - Printer { pappl_device_t *device = NULL; // Open device if (!printer) return (NULL); _papplRWLockWrite(printer); if (!printer->device_in_use && !printer->processing_job && printer->device_uri) { // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Opening device for status/maintenance."); printer->device = device = papplDeviceOpen(printer->device_uri, "printer", papplLogDevice, printer->system); printer->device_in_use = device != NULL; } _papplRWUnlock(printer); return (device); } // // 'papplPrinterPause()' - Pause (stop) a printer. // // This function pauses a printer. If the printer is currently processing // (printing) a job, it will be completed before the printer is stopped. // void papplPrinterPause( pappl_printer_t *printer) // I - Printer { if (!printer) return; _papplRWLockWrite(printer); if (printer->processing_job) printer->is_stopped = true; else printer->state = IPP_PSTATE_STOPPED; _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED | PAPPL_EVENT_PRINTER_STOPPED, NULL); _papplRWUnlock(printer); } // // 'papplPrinterReleaseHeldNewJobs()' - Release any previously held jobs for printing. // // This function releases all jobs that were previously held due to a prior // call to @link papplPrinterHoldNewJobs@. // bool // O - `true` on success, `false` on failure papplPrinterReleaseHeldNewJobs( pappl_printer_t *printer, // I - Printer const char *username) // I - User that released the held jobs or `NULL` for none/system { pappl_job_t *job; // Current job bool ret = false, // Return value released_jobs = false; // Have we released any jobs? // Range check input... if (!printer) return (false); // Only release if the printer is holding new jobs... _papplRWLockWrite(printer); if (printer->hold_new_jobs) { // Release jobs and clear the 'hold-new-jobs' flag... printer->hold_new_jobs = false; printer->config_time = time(NULL); ret = true; _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_CONFIG_CHANGED, "Releasing held new jobs."); for (job = (pappl_job_t *)cupsArrayGetFirst(printer->active_jobs); job; job = (pappl_job_t *)cupsArrayGetNext(printer->active_jobs)) { if (job->state == IPP_JSTATE_HELD && job->hold_until == 0 && !(job->state_reasons & PAPPL_JREASON_JOB_HOLD_UNTIL_SPECIFIED)) { // Release this job _papplRWLockWrite(job); _papplJobReleaseNoLock(job, username); _papplRWUnlock(job); released_jobs = true; } } } if (released_jobs) _papplPrinterCheckJobsNoLock(printer); _papplRWUnlock(printer); return (ret); } // // 'papplPrinterResume()' - Resume (start) a printer. // // This function resumes a printer and starts processing any pending jobs. // void papplPrinterResume( pappl_printer_t *printer) // I - Printer { if (!printer) return; _papplRWLockWrite(printer); printer->is_stopped = false; printer->state = IPP_PSTATE_IDLE; _papplSystemAddEventNoLock(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, "Resumed printer."); _papplPrinterCheckJobsNoLock(printer); _papplRWUnlock(printer); } // // 'papplPrinterSetContact()' - Set the "printer-contact" value. // // This function sets the printer's contact information. // void papplPrinterSetContact( pappl_printer_t *printer, // I - Printer pappl_contact_t *contact) // I - Contact { if (!printer || !contact) return; _papplRWLockWrite(printer); printer->contact = *contact; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetDNSSDName()' - Set the DNS-SD service name. // // This function sets the printer's DNS-SD service name. If `NULL`, the printer // will stop advertising the printer. // void papplPrinterSetDNSSDName( pappl_printer_t *printer, // I - Printer const char *value) // I - DNS-SD service name or `NULL` for none { if (!printer) return; _papplRWLockWrite(printer); free(printer->dns_sd_name); printer->dns_sd_name = value ? strdup(value) : NULL; printer->dns_sd_collision = false; printer->dns_sd_serial = 0; printer->config_time = time(NULL); if (!value) _papplPrinterUnregisterDNSSDNoLock(printer); else _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetGeoLocation()' - Set the geo-location value as a "geo:" URI. // // This function sets the printer's geographic location as a "geo:" URI. If // `NULL`, the location is cleared to the 'unknown' value. // void papplPrinterSetGeoLocation( pappl_printer_t *printer, // I - Printer const char *value) // I - "geo:" URI or `NULL` for unknown { float lat, lon; // Latitude and longitude from geo: URI if (!printer) return; // Validate geo-location - must be NULL or a "geo:" URI... if (value && *value && sscanf(value, "geo:%f,%f", &lat, &lon) != 2) return; _papplRWLockWrite(printer); free(printer->geo_location); printer->geo_location = value && *value ? strdup(value) : NULL; printer->config_time = time(NULL); _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetImpressionsCompleted()' - Add impressions (sides) to the // total count of printed impressions. // // This function adds to the printer's impressions counter. An impression is // one side of an output page. // void papplPrinterSetImpressionsCompleted( pappl_printer_t *printer, // I - Printer int add) // I - Number of impressions/sides to add { if (!printer || add <= 0) return; _papplRWLockWrite(printer); printer->impcompleted += add; printer->state_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetLocation()' - Set the location string. // // This function sets the printer's human-readable location string. If `NULL`, // the location is cleared. // void papplPrinterSetLocation( pappl_printer_t *printer, // I - Printer const char *value) // I - Location ("Bob's Office", etc.) or `NULL` for none { if (!printer) return; _papplRWLockWrite(printer); free(printer->location); printer->location = value ? strdup(value) : NULL; printer->config_time = time(NULL); _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetMaxActiveJobs()' - Set the maximum number of active jobs for // the printer. // // This function sets the maximum number of jobs that can be spooled on the // printer at one time. // // > Note: This limit does not apply to streaming raster formats such as PWG // > Raster since they are not spooled. // void papplPrinterSetMaxActiveJobs( pappl_printer_t *printer, // I - Printer int max_active_jobs) // I - Maximum number of active jobs, `0` for unlimited { if (!printer || max_active_jobs < 0) return; _papplRWLockWrite(printer); printer->max_active_jobs = max_active_jobs; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetMaxCompletedJobs()' - Set the maximum number of completed // jobs for the printer. // // This function sets the maximum number of aborted, canceled, or completed jobs // that are retained in the job history. // void papplPrinterSetMaxCompletedJobs( pappl_printer_t *printer, // I - Printer int max_completed_jobs) // I - Maximum number of completed jobs, `0` for unlimited { if (!printer || max_completed_jobs < 0) return; _papplRWLockWrite(printer); printer->max_completed_jobs = max_completed_jobs; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetMaxPreservedJobs()' - Set the maximum number of preserved // jobs for the printer. // // This function sets the maximum number of aborted, canceled, or completed jobs // that are preserved (with document data) in the job history. // void papplPrinterSetMaxPreservedJobs( pappl_printer_t *printer, // I - Printer int max_preserved_jobs) // I - Maximum number of preserved jobs, `0` for none { if (!printer || max_preserved_jobs < 0) return; _papplRWLockWrite(printer); printer->max_preserved_jobs = max_preserved_jobs; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetNextJobID()' - Set the next "job-id" value. // // This function sets the next unique positive integer identifier that will be // used for a job. // // > Note: This function is normally only called once to restore the previous // > state of the printer. // void papplPrinterSetNextJobID( pappl_printer_t *printer, // I - Printer int next_job_id) // I - Next "job-id" value { if (!printer || next_job_id < 1) return; _papplRWLockWrite(printer); printer->next_job_id = next_job_id; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetOrganization()' - Set the organization name. // // This function sets the printer's organization name. If `NULL` the value is // cleared. // void papplPrinterSetOrganization( pappl_printer_t *printer, // I - Printer const char *value) // I - Organization name or `NULL` for none { if (!printer) return; _papplRWLockWrite(printer); free(printer->organization); printer->organization = value ? strdup(value) : NULL; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetOrganizationalUnit()' - Set the organizational unit name. // // This function sets the printer's organizational unit name. If `NULL` the // value is cleared. // void papplPrinterSetOrganizationalUnit( pappl_printer_t *printer, // I - Printer const char *value) // I - Organizational unit name or `NULL` for none { if (!printer) return; _papplRWLockWrite(printer); free(printer->org_unit); printer->org_unit = value ? strdup(value) : NULL; printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetPrintGroup()' - Set the print authorization group, if any. // // This function sets the printer's authorization group. If `NULL`, the group // is cleared. // // > Note: The authorization group is only used if the system is created with a // > named authorization service. // void papplPrinterSetPrintGroup( pappl_printer_t *printer, // I - Printer const char *value) // I - Print authorization group or `NULL` for none { if (!printer) return; _papplRWLockWrite(printer); free(printer->print_group); printer->print_group = value ? strdup(value) : NULL; printer->config_time = time(NULL); #if !_WIN32 if (printer->print_group && strcmp(printer->print_group, "none")) { char buffer[8192]; // Buffer for strings struct group grpbuf, // Group buffer *grp = NULL; // Print group if (getgrnam_r(printer->print_group, &grpbuf, buffer, sizeof(buffer), &grp) || !grp) papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to find print group '%s'.", printer->print_group); else printer->print_gid = grp->gr_gid; } else #endif // !_WIN32 printer->print_gid = (gid_t)-1; _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); } // // 'papplPrinterSetReasons()' - Add or remove values from // "printer-state-reasons". // // This function updates the printer state reasons bitfield by clearing any bit // values in the "remove" argument and setting any bit values in the "add" // argument. // void papplPrinterSetReasons( pappl_printer_t *printer, // I - Printer pappl_preason_t add, // I - "printer-state-reasons" bit values to add or `PAPPL_PREASON_NONE` for none pappl_preason_t remove) // I - "printer-state-reasons" bit values to remove or `PAPPL_PREASON_NONE` for none { if (!printer) return; _papplRWLockWrite(printer); printer->state_reasons &= ~remove; printer->state_reasons |= add; printer->state_time = printer->status_time = time(NULL); _papplRWUnlock(printer); } // // 'papplPrinterSetSupplies()' - Set/update the supplies for a printer. // // This function updates the supply information for the printer. // void papplPrinterSetSupplies( pappl_printer_t *printer, // I - Printer int num_supplies, // I - Number of supplies pappl_supply_t *supplies) // I - Array of supplies { if (!printer || num_supplies < 0 || num_supplies > PAPPL_MAX_SUPPLY || (num_supplies > 0 && !supplies)) return; _papplRWLockWrite(printer); printer->num_supply = num_supplies; memset(printer->supply, 0, sizeof(printer->supply)); if (supplies) memcpy(printer->supply, supplies, (size_t)num_supplies * sizeof(pappl_supply_t)); printer->state_time = time(NULL); _papplRWUnlock(printer); } pappl-1.4.9/pappl/printer-driver.c000066400000000000000000001664151476704353100171240ustar00rootroot00000000000000// // Printer driver functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "printer-private.h" #include "system-private.h" // // Local functions... // static ipp_t *make_attrs(pappl_system_t *system, pappl_printer_t *printer, pappl_pr_driver_data_t *data); static bool validate_defaults(pappl_printer_t *printer, pappl_pr_driver_data_t *driver_data, pappl_pr_driver_data_t *data); static bool validate_driver(pappl_printer_t *printer, pappl_pr_driver_data_t *data); static bool validate_ready(pappl_printer_t *printer, pappl_pr_driver_data_t *driver_data, int num_ready, pappl_media_col_t *ready); // // 'papplPrinterGetDriverAttributes()' - Get a copy of the current driver // attributes. // // This function returns a copy the current driver attributes. Use the // `ippDelete` function to free the memory used for the attributes when you // are done. // ipp_t * // O - Copy of driver attributes papplPrinterGetDriverAttributes( pappl_printer_t *printer) // I - Printer { ipp_t *attrs; // Copy of driver attributes if (!printer) return (NULL); _papplRWLockRead(printer); attrs = ippNew(); ippCopyAttributes(attrs, printer->driver_attrs, 1, NULL, NULL); _papplRWUnlock(printer); return (attrs); } // // 'papplPrinterGetDriverData()' - Get the current print driver data. // // This function copies the current print driver data, defaults, and ready // (loaded) media information into the specified buffer. // pappl_pr_driver_data_t * // O - Driver data or `NULL` if none papplPrinterGetDriverData( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *data) // I - Pointer to driver data structure to fill { if (!printer || !printer->driver_name || !data) { if (data) _papplPrinterInitDriverData(data); return (NULL); } memcpy(data, &printer->driver_data, sizeof(pappl_pr_driver_data_t)); return (data); } // // 'papplPrinterGetDriverName()' - Get the driver name for a printer. // // This function returns the driver name for the printer. // const char * // O - Driver name or `NULL` for none papplPrinterGetDriverName( pappl_printer_t *printer) // I - Printer { return (printer ? printer->driver_name : NULL); } // // '_papplPrinterInitDriverData()' - Initialize a print driver data structure. // void _papplPrinterInitDriverData( pappl_pr_driver_data_t *d) // I - Driver data { static const pappl_dither_t clustered = { // Clustered-Dot Dither Matrix { 96, 40, 48, 104, 140, 188, 196, 148, 97, 41, 49, 105, 141, 189, 197, 149 }, { 32, 0, 8, 56, 180, 236, 244, 204, 33, 1, 9, 57, 181, 237, 245, 205 }, { 88, 24, 16, 64, 172, 228, 252, 212, 89, 25, 17, 65, 173, 229, 253, 213 }, { 120, 80, 72, 112, 132, 164, 220, 156, 121, 81, 73, 113, 133, 165, 221, 157 }, { 136, 184, 192, 144, 100, 44, 52, 108, 137, 185, 193, 145, 101, 45, 53, 109 }, { 176, 232, 240, 200, 36, 4, 12, 60, 177, 233, 241, 201, 37, 5, 13, 61 }, { 168, 224, 248, 208, 92, 28, 20, 68, 169, 225, 249, 209, 93, 29, 21, 69 }, { 128, 160, 216, 152, 124, 84, 76, 116, 129, 161, 217, 153, 125, 85, 77, 117 }, { 98, 42, 50, 106, 142, 190, 198, 150, 99, 43, 51, 107, 143, 191, 199, 151 }, { 34, 2, 10, 58, 182, 238, 246, 206, 35, 3, 11, 59, 183, 239, 247, 207 }, { 90, 26, 18, 66, 174, 230, 254, 214, 91, 27, 19, 67, 175, 231, 254, 215 }, { 122, 82, 74, 114, 134, 166, 222, 158, 123, 83, 75, 115, 135, 167, 223, 159 }, { 138, 186, 194, 146, 102, 46, 54, 110, 139, 187, 195, 147, 103, 47, 55, 111 }, { 178, 234, 242, 202, 38, 6, 14, 62, 179, 235, 243, 203, 39, 7, 15, 63 }, { 170, 226, 250, 210, 94, 30, 22, 70, 171, 227, 251, 211, 95, 31, 23, 71 }, { 130, 162, 218, 154, 126, 86, 78, 118, 131, 163, 219, 155, 127, 87, 79, 119 } }; static const pappl_dither_t blue = // Blue-noise dither array { { 111, 49, 142, 162, 113, 195, 71, 177, 201, 50, 151, 94, 66, 37, 85, 252 }, { 25, 99, 239, 222, 32, 250, 148, 19, 38, 106, 220, 170, 194, 138, 13, 167 }, { 125, 178, 79, 15, 65, 173, 123, 87, 213, 131, 247, 23, 116, 54, 229, 212 }, { 41, 202, 152, 132, 189, 104, 53, 236, 161, 62, 1, 181, 77, 241, 147, 68 }, { 2, 244, 56, 91, 230, 5, 204, 28, 187, 101, 144, 206, 33, 92, 190, 107 }, { 223, 164, 114, 36, 214, 156, 139, 70, 245, 84, 226, 48, 126, 158, 17, 135 }, { 83, 196, 21, 254, 76, 45, 179, 115, 12, 40, 169, 105, 253, 176, 211, 59 }, { 100, 180, 145, 122, 172, 97, 235, 129, 215, 149, 199, 8, 72, 26, 238, 44 }, { 232, 31, 69, 11, 205, 58, 18, 193, 88, 60, 112, 221, 140, 86, 120, 153 }, { 208, 130, 243, 160, 224, 110, 34, 248, 165, 24, 234, 184, 52, 198, 171, 6 }, { 108, 188, 51, 89, 137, 186, 154, 78, 47, 134, 98, 157, 35, 249, 95, 63 }, { 16, 75, 219, 39, 0, 67, 228, 121, 197, 240, 3, 74, 127, 20, 227, 143 }, { 246, 175, 119, 200, 251, 103, 146, 14, 209, 174, 109, 218, 192, 82, 203, 163 }, { 29, 93, 150, 22, 166, 182, 55, 30, 90, 64, 42, 141, 168, 57, 117, 46 }, { 216, 233, 61, 128, 81, 237, 217, 118, 159, 255, 185, 27, 242, 102, 4, 133 }, { 73, 191, 9, 210, 43, 96, 7, 136, 231, 80, 10, 124, 225, 207, 155, 183 } }; memset(d, 0, sizeof(pappl_pr_driver_data_t)); memcpy(d->gdither, clustered, sizeof(d->gdither)); memcpy(d->pdither, blue, sizeof(d->pdither)); d->orient_default = IPP_ORIENT_NONE; d->content_default = PAPPL_CONTENT_AUTO; d->darkness_configured = 50; d->quality_default = IPP_QUALITY_NORMAL; d->scaling_default = PAPPL_SCALING_AUTO; d->sides_supported = PAPPL_SIDES_ONE_SIDED; d->sides_default = PAPPL_SIDES_ONE_SIDED; } // // 'papplPrinterSetDriverData()' - Set the driver data. // // This function validates and sets the driver data, including all defaults and // ready (loaded) media. // // > Note: This function regenerates all of the driver-specific capability // > attributes like "media-col-database", "sides-supported", and so forth. // > Use the @link papplPrinterSetDriverDefaults@ or // > @link papplPrinterSetReadyMedia@ functions to efficiently change the // > "xxx-default" or "xxx-ready" values, respectively. // bool // O - `true` on success, `false` on failure papplPrinterSetDriverData( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *data, // I - Driver data ipp_t *attrs) // I - Additional capability attributes or `NULL` for none { if (!printer || !data) return (false); // Validate data... if (!validate_defaults(printer, data, data) || !validate_driver(printer, data) || !validate_ready(printer, data, data->num_source, data->media_ready)) return (false); _papplRWLockWrite(printer); // Copy driver data to printer memcpy(&printer->driver_data, data, sizeof(printer->driver_data)); printer->num_ready = data->num_source; // Create printer (capability) attributes based on driver data... ippDelete(printer->driver_attrs); printer->driver_attrs = make_attrs(printer->system, printer, &printer->driver_data); if (attrs) ippCopyAttributes(printer->driver_attrs, attrs, 0, NULL, NULL); _papplRWUnlock(printer); return (true); } // // 'papplPrinterSetDriverDefaults()' - Set the default print option values. // // This function validates and sets the printer's default print options. // // > Note: Unlike @link papplPrinterSetPrintDriverData@, this function only // > changes the "xxx_default" members of the driver data and is considered // > lightweight. // bool // O - `true` on success or `false` on failure papplPrinterSetDriverDefaults( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *data, // I - Driver data int num_vendor, // I - Number of vendor options cups_option_t *vendor) // I - Vendor options { int i; // Looping var const char *value; // Vendor value int intvalue; // Integer value char *end, // End of value defname[128], // xxx-default name supname[128]; // xxx-supported name ipp_attribute_t *supported; // xxx-supported attribute if (!printer || !data) return (false); if (!validate_defaults(printer, &printer->driver_data, data)) return (false); _papplRWLockWrite(printer); // Copy xxx_default values... printer->driver_data.bin_default = data->bin_default; printer->driver_data.color_default = data->color_default; printer->driver_data.content_default = data->content_default; printer->driver_data.darkness_configured = data->darkness_configured; printer->driver_data.darkness_default = data->darkness_default; printer->driver_data.identify_default = data->identify_default; printer->driver_data.media_default = data->media_default; printer->driver_data.mode_configured = data->mode_configured; printer->driver_data.orient_default = data->orient_default; printer->driver_data.quality_default = data->quality_default; printer->driver_data.scaling_default = data->scaling_default; printer->driver_data.sides_default = data->sides_default; printer->driver_data.speed_default = data->speed_default; printer->driver_data.tear_offset_configured = data->tear_offset_configured; printer->driver_data.x_default = data->x_default; printer->driver_data.y_default = data->y_default; // Copy any vendor-specific xxx-default values... for (i = 0; i < data->num_vendor; i ++) { if ((value = cupsGetOption(data->vendor[i], (cups_len_t)num_vendor, vendor)) == NULL) continue; snprintf(defname, sizeof(defname), "%s-default", data->vendor[i]); snprintf(supname, sizeof(supname), "%s-supported", data->vendor[i]); ippDeleteAttribute(printer->driver_attrs, ippFindAttribute(printer->driver_attrs, defname, IPP_TAG_ZERO)); if ((supported = ippFindAttribute(printer->driver_attrs, supname, IPP_TAG_ZERO)) != NULL) { switch (ippGetValueTag(supported)) { case IPP_TAG_INTEGER : case IPP_TAG_RANGE : intvalue = (int)strtol(value, &end, 10); if (errno != ERANGE && !*end) ippAddInteger(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, defname, intvalue); break; case IPP_TAG_BOOLEAN : ippAddBoolean(printer->driver_attrs, IPP_TAG_PRINTER, defname, !strcmp(value, "true") || !strcmp(value, "on")); break; case IPP_TAG_KEYWORD : ippAddString(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, defname, NULL, value); break; default : papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver '%s' attribute syntax not supported, only boolean, integer, keyword, and rangeOfInteger are supported.", supname); break; } } else { // Default to simple text values... ippAddString(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, defname, NULL, value); } } printer->config_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); return (true); } // // 'papplPrinterSetReadyMedia()' - Set the ready (loaded) media. // // This function validates and sets the printer's ready (loaded) media. // bool // O - `true` on success or `false` on failure papplPrinterSetReadyMedia( pappl_printer_t *printer, // I - Printer int num_ready, // I - Number of ready media pappl_media_col_t *ready) // I - Array of ready media { int i; // Looping vars if (!printer || num_ready <= 0 || !ready) return (false); if (!validate_ready(printer, &printer->driver_data, num_ready, ready)) return (false); _papplRWLockWrite(printer); // Copy new ready media to printer data... if (num_ready > PAPPL_MAX_SOURCE) num_ready = PAPPL_MAX_SOURCE; memset(printer->driver_data.media_ready, 0, sizeof(printer->driver_data.media_ready)); memcpy(printer->driver_data.media_ready, ready, (size_t)num_ready * sizeof(pappl_media_col_t)); printer->num_ready = num_ready; // Update default media from ready media... for (i = 0; i < num_ready; i ++) { if (!strcmp(ready[i].source, printer->driver_data.media_default.source)) { printer->driver_data.media_default = ready[i]; break; } } printer->state_time = time(NULL); _papplRWUnlock(printer); _papplSystemConfigChanged(printer->system); return (true); } // // 'make_attrs()' - Make the capability attributes for the given driver data. // static ipp_t * // O - Driver attributes make_attrs( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *data) // I - Driver data { ipp_t *attrs; // Driver attributes bool jpeg_supported, // Is JPEG supported? pdf_supported; // Is PDF supported? unsigned bit; // Current bit value cups_len_t i, j, // Looping vars num_values; // Number of values const char *svalues[PAPPL_MAX_MEDIA]; // String values int ivalues[PAPPL_MAX_MEDIA]; // Integer values ipp_t *cvalues[PAPPL_MAX_MEDIA * 2]; // Collection values char vvalues[PAPPL_MAX_VENDOR][128]; // Vendor xxx-default values char fn[32], // FN (finishings) values *ptr; // Pointer into value const char *preferred; // "document-format-preferred" value const char *prefix; // Prefix string const char *max_name = NULL,// Maximum size *min_name = NULL;// Minimum size char output_tray[256];// "printer-output-tray" value _pappl_mime_filter_t *filter; // Current filter ipp_attribute_t *attr; // Attribute static const char * const job_creation_attributes[] = { // job-creation-attributes-supported values "copies", "document-format", "document-name", "ipp-attribute-fidelity", "job-hold-until", "job-hold-until-time", "job-name", "job-priority", "job-retain-until", "job-retain-until-interval", "job-retain-until-time", "media", "media-col", "multiple-document-handling", "orientation-requested", "print-color-mode", "print-content-optimize", "print-quality", "printer-resolution" }; static const char * const media_col[] = { // media-col-supported values "media-bottom-margin", "media-left-margin", "media-right-margin", "media-size", "media-size-name", "media-top-margin" }; static const char * const pdf_versions_supported[] = { // "pdf-versions-supported" values "adobe-1.3", "adobe-1.4", "adobe-1.5", "adobe-1.6", "iso-32000-1_2008", // PDF 1.7 "iso-32000-2_2017" // PDF 2.0 }; static const char * const printer_settable_attributes[] = { // printer-settable-attributes values "copies-default", "media-col-default", "media-col-ready", "media-default", "media-ready", "multiple-document-handling-default", "orientation-requested-default", "print-color-mode-default", "print-content-optimize-default", "print-quality-default", "printer-contact-col", "printer-geo-location", "printer-location", "printer-organization", "printer-organizational-unit", "printer-resolution-default" }; // Are JPEG and PDF supported? jpeg_supported = _papplSystemFindMIMEFilter(system, "image/jpeg", "image/pwg-raster") != NULL || _papplSystemFindMIMEFilter(system, "image/jpeg", data->format) != NULL; pdf_supported = (data->format && !strcmp(data->format, "application/pdf")) || _papplSystemFindMIMEFilter(system, "application/pdf", "image/pwg-raster") != NULL || _papplSystemFindMIMEFilter(system, "application/pdf", data->format) != NULL; papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "JPEG is %s, PDF is %s.", jpeg_supported ? "supported" : "not supported", pdf_supported ? "supported" : "not supported"); // Create an empty IPP message for the attributes... attrs = ippNew(); // color-supported ippAddBoolean(attrs, IPP_TAG_PRINTER, "color-supported", data->ppm_color > 0); // document-format-supported num_values = 0; svalues[num_values ++] = "application/octet-stream"; svalues[num_values ++] = "image/pwg-raster"; svalues[num_values ++] = "image/urf"; if (data->format && strcmp(data->format, "application/octet-stream")) svalues[num_values ++] = data->format; for (preferred = "image/urf", filter = (_pappl_mime_filter_t *)cupsArrayGetFirst(system->filters); filter; filter = (_pappl_mime_filter_t *)cupsArrayGetNext(system->filters)) { if ((data->format && !strcmp(filter->dst, data->format)) || !strcmp(filter->dst, "image/pwg-raster")) { for (i = 0; i < num_values; i ++) { if (!strcmp(filter->src, svalues[i])) break; } if (i >= num_values && num_values < (int)(sizeof(svalues) / sizeof(svalues[0]))) { svalues[num_values ++] = filter->src; if (!strcmp(filter->src, "application/pdf")) preferred = "application/pdf"; } } } ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format-preferred", NULL, preferred); ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, "document-format-supported", num_values, NULL, svalues); // Assemble finishings-xxx values... num_values = 0; cvalues[num_values ] = ippNew(); ippAddString(cvalues[num_values], IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "finishing-template", NULL, "none"); ivalues[num_values ] = IPP_FINISHINGS_NONE; svalues[num_values ++] = "none"; papplCopyString(fn, "FN3", sizeof(fn)); for (ptr = fn + 3, i = 0, bit = PAPPL_FINISHINGS_PUNCH; bit <= PAPPL_FINISHINGS_TRIM; i ++, bit *= 2) { if (data->finishings & bit) { cvalues[num_values ] = ippNew(); ippAddString(cvalues[num_values], IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "finishing-template", NULL, _papplFinishingsString(bit)); ivalues[num_values ] = (int)_papplFinishingsEnum(bit); svalues[num_values ++] = _papplFinishingsString(bit); snprintf(ptr, sizeof(fn) - (size_t)(ptr - fn), "-%d", (int)_papplFinishingsEnum(bit)); ptr += strlen(ptr); } } *ptr = '\0'; // finishing-template-supported ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "finishing-template-supported", num_values, NULL, svalues); // finishing-col-database ippAddCollections(attrs, IPP_TAG_PRINTER, "finishing-col-database", num_values, (const ipp_t **)cvalues); // finishing-col-default ippAddCollection(attrs, IPP_TAG_PRINTER, "finishing-col-default", cvalues[0]); // finishing-col-supported ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "finishing-col-supported", NULL, "finishing-template"); // finishings-default ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-default", IPP_FINISHINGS_NONE); // finishings-supported ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-supported", num_values, ivalues); for (i = 0; i < num_values; i ++) ippDelete(cvalues[i]); // identify-actions-supported for (num_values = 0, bit = PAPPL_IDENTIFY_ACTIONS_DISPLAY; bit <= PAPPL_IDENTIFY_ACTIONS_SPEAK; bit *= 2) { if (data->identify_supported & bit) svalues[num_values ++] = _papplIdentifyActionsString(bit); } if (num_values > 0) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "identify-actions-supported", num_values, NULL, svalues); // ipp-features-supported if ((num_values = (cups_len_t)data->num_features) > PAPPL_MAX_VENDOR) num_values = PAPPL_MAX_VENDOR; if (num_values > 0) memcpy((void *)svalues, data->features, (size_t)num_values * sizeof(char *)); svalues[num_values ++] = "ipp-everywhere"; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-features-supported", num_values, NULL, svalues); // job-creation-attributes-supported memcpy((void *)svalues, job_creation_attributes, sizeof(job_creation_attributes)); num_values = (int)(sizeof(job_creation_attributes) / sizeof(job_creation_attributes[0])); if (data->finishings) { svalues[num_values ++] = "finishings"; svalues[num_values ++] = "finishings-col"; } if (data->num_bin) svalues[num_values ++] = "output-bin"; if (pdf_supported) svalues[num_values ++] = "page-ranges"; if (data->darkness_supported) svalues[num_values ++] = "print-darkness"; if (data->speed_supported[1]) svalues[num_values ++] = "print-speed"; if (data->sides_supported != PAPPL_SIDES_ONE_SIDED) svalues[num_values ++] = "sides"; for (i = 0; i < (cups_len_t)data->num_vendor && i < (cups_len_t)(sizeof(data->vendor) / sizeof(data->vendor[0])); i ++) svalues[num_values ++] = data->vendor[i]; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-creation-attributes-supported", num_values, NULL, svalues); if (jpeg_supported) { // jpeg-features-supported static const char * const jpeg_features_supported[] = { // "jpeg-features-supported" values "arithmetic", "cmyk", "progressive" }; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "jpeg-features-supported", (int)(sizeof(jpeg_features_supported) / sizeof(jpeg_features_supported[0])), NULL, jpeg_features_supported); // jpeg-k-octets-supported int upper = 0, lower = ippGetRange(ippFindAttribute(printer->attrs, "job-k-octets-supported", IPP_TAG_RANGE), 0, &upper); // Range of k-octets-supported... ippAddRange(attrs, IPP_TAG_PRINTER, "jpeg-k-octets-supported", lower, upper); // jpeg-x-dimension-supported ippAddRange(attrs, IPP_TAG_PRINTER, "jpeg-x-dimension-supported", 0, system->max_image_width); // jpeg-y-dimension-supported ippAddRange(attrs, IPP_TAG_PRINTER, "jpeg-y-dimension-supported", 1, system->max_image_height); } // label-mode-supported for (num_values = 0, bit = PAPPL_LABEL_MODE_APPLICATOR; bit <= PAPPL_LABEL_MODE_TEAR_OFF; bit *= 2) { if (data->mode_supported & bit) svalues[num_values ++] = _papplLabelModeString((pappl_label_mode_t)bit); } if (num_values > 0) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "label-mode-supported", num_values, NULL, svalues); // label-tear-offset-supported if (data->tear_offset_supported[0] || data->tear_offset_supported[1]) ippAddRange(attrs, IPP_TAG_PRINTER, "label-tear-offset-supported", data->tear_offset_supported[0], data->tear_offset_supported[1]); // landscape-orientation-requested-preferred ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "landscape-orientation-requested-preferred", IPP_ORIENT_LANDSCAPE); // max-page-ranges-supported if (pdf_supported) ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "max-page-ranges-supported", 1); // media-bottom-margin-supported num_values = 0; if (data->borderless) ivalues[num_values ++] = 0; ivalues[num_values ++] = data->bottom_top; ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin-supported", num_values, ivalues); // media-col-database for (i = 0, num_values = 0; i < (cups_len_t)data->num_media; i ++) { if (!strncmp(data->media[i], "custom_max_", 11) || !strncmp(data->media[i], "roll_max_", 9)) { max_name = data->media[i]; } else if (!strncmp(data->media[i], "custom_min_", 11) || !strncmp(data->media[i], "roll_min_", 9)) { min_name = data->media[i]; } else { pappl_media_col_t col; // Media collection pwg_media_t *pwg; // PWG media size info memset(&col, 0, sizeof(col)); papplCopyString(col.size_name, data->media[i], sizeof(col.size_name)); if ((pwg = pwgMediaForPWG(data->media[i])) != NULL) { col.size_width = pwg->width; col.size_length = pwg->length; } if (data->borderless && data->bottom_top > 0 && data->left_right > 0) cvalues[num_values ++] = _papplMediaColExport(data, &col, true); col.bottom_margin = col.top_margin = data->bottom_top; col.left_margin = col.right_margin = data->left_right; if ((cvalues[num_values] = _papplMediaColExport(data, &col, true)) != NULL) num_values ++; } } if (min_name && max_name) { pwg_media_t *pwg, // Current media size info max_pwg, // PWG maximum media size info min_pwg; // PWG minimum media size info ipp_t *col; // media-size collection if ((pwg = pwgMediaForPWG(max_name)) != NULL) max_pwg = *pwg; else memset(&max_pwg, 0, sizeof(max_pwg)); if ((pwg = pwgMediaForPWG(min_name)) != NULL) min_pwg = *pwg; else memset(&min_pwg, 0, sizeof(min_pwg)); col = ippNew(); ippAddRange(col, IPP_TAG_PRINTER, "x-dimension", min_pwg.width, max_pwg.width); ippAddRange(col, IPP_TAG_PRINTER, "y-dimension", min_pwg.length, max_pwg.length); cvalues[num_values] = ippNew(); ippAddCollection(cvalues[num_values], IPP_TAG_PRINTER, "media-size", col); if (data->borderless && data->bottom_top > 0 && data->left_right > 0) { ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin", 0); ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin", 0); ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin", 0); ippAddInteger(cvalues[num_values ++], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin", 0); cvalues[num_values] = ippNew(); ippAddCollection(cvalues[num_values], IPP_TAG_PRINTER, "media-size", col); } ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin", data->bottom_top); ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin", data->left_right); ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin", data->left_right); ippAddInteger(cvalues[num_values ++], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin", data->bottom_top); ippDelete(col); } if (num_values > 0) { ippAddCollections(attrs, IPP_TAG_PRINTER, "media-col-database", num_values, (const ipp_t **)cvalues); for (i = 0; i < num_values; i ++) ippDelete(cvalues[i]); } // media-col-supported memcpy((void *)svalues, media_col, sizeof(media_col)); num_values = (int)(sizeof(media_col) / sizeof(media_col[0])); if (data->left_offset_supported[1]) svalues[num_values ++] = "media-left-offset"; if (data->num_source) svalues[num_values ++] = "media-source"; if (data->top_offset_supported[1]) svalues[num_values ++] = "media-top-offset"; if (data->tracking_supported) svalues[num_values ++] = "media-tracking"; if (data->num_type) svalues[num_values ++] = "media-type"; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-col-supported", num_values, NULL, svalues); // media-left-margin-supported num_values = 0; if (data->borderless) ivalues[num_values ++] = 0; ivalues[num_values ++] = data->left_right; ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin-supported", num_values, ivalues); // media-left-offset-supported if (data->left_offset_supported[1]) ippAddRange(attrs, IPP_TAG_PRINTER, "media-left-offset-supported", data->left_offset_supported[0], data->left_offset_supported[1]); // media-right-margin-supported num_values = 0; if (data->borderless) ivalues[num_values ++] = 0; ivalues[num_values ++] = data->left_right; ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin-supported", num_values, ivalues); // media-size-supported for (i = 0, num_values = 0; i < (cups_len_t)data->num_media; i ++) { pwg_media_t *pwg; // PWG media size info if (!strncmp(data->media[i], "custom_max_", 11) || !strncmp(data->media[i], "roll_max_", 9)) { max_name = data->media[i]; } else if (!strncmp(data->media[i], "custom_min_", 11) || !strncmp(data->media[i], "roll_min_", 9)) { min_name = data->media[i]; } else if ((pwg = pwgMediaForPWG(data->media[i])) != NULL) { cvalues[num_values] = ippNew(); ippAddInteger(cvalues[num_values], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "x-dimension", pwg->width); ippAddInteger(cvalues[num_values ++], IPP_TAG_PRINTER, IPP_TAG_INTEGER, "y-dimension", pwg->length); } } if (min_name && max_name) { pwg_media_t *pwg, // Current media size info max_pwg, // PWG maximum media size info min_pwg; // PWG minimum media size info if ((pwg = pwgMediaForPWG(max_name)) != NULL) max_pwg = *pwg; else memset(&max_pwg, 0, sizeof(max_pwg)); if ((pwg = pwgMediaForPWG(min_name)) != NULL) min_pwg = *pwg; else memset(&min_pwg, 0, sizeof(min_pwg)); cvalues[num_values] = ippNew(); ippAddRange(cvalues[num_values], IPP_TAG_PRINTER, "x-dimension", min_pwg.width, max_pwg.width); ippAddRange(cvalues[num_values ++], IPP_TAG_PRINTER, "y-dimension", min_pwg.length, max_pwg.length); } if (num_values > 0) { ippAddCollections(attrs, IPP_TAG_PRINTER, "media-size-supported", num_values, (const ipp_t **)cvalues); for (i = 0; i < num_values; i ++) ippDelete(cvalues[i]); } // media-source-supported if ((num_values = (cups_len_t)data->num_source) > 0) { if (num_values > PAPPL_MAX_SOURCE) num_values = PAPPL_MAX_SOURCE; memcpy((void *)svalues, data->source, (size_t)num_values * sizeof(char *)); } svalues[num_values ++] = "auto"; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-source-supported", num_values, NULL, svalues); // media-supported if (data->num_media) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-supported", (cups_len_t)data->num_media, NULL, data->media); // media-top-margin-supported num_values = 0; if (data->borderless) ivalues[num_values ++] = 0; ivalues[num_values ++] = data->bottom_top; ippAddIntegers(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin-supported", num_values, ivalues); // media-top-offset-supported if (data->top_offset_supported[1]) ippAddRange(attrs, IPP_TAG_PRINTER, "media-top-offset-supported", data->top_offset_supported[0], data->top_offset_supported[1]); // media-tracking-supported if (data->tracking_supported) { for (num_values = 0, bit = PAPPL_MEDIA_TRACKING_CONTINUOUS; bit <= PAPPL_MEDIA_TRACKING_WEB; bit *= 2) { if (data->tracking_supported & bit) svalues[num_values ++] = _papplMediaTrackingString((pappl_media_tracking_t)bit); } ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-tracking-supported", num_values, NULL, svalues); } // media-type-supported if (data->num_type) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-type-supported", (cups_len_t)data->num_type, NULL, data->type); // mopria-certified (Mopria-specific attribute) if (!ippFindAttribute(attrs, "mopria-certified", IPP_TAG_ZERO)) ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_TEXT), "mopria-certified", NULL, "1.3"); // output-bin-supported if (data->num_bin) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-supported", (cups_len_t)data->num_bin, NULL, data->bin); else if (data->output_face_up) ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-supported", NULL, "face-up"); else ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-supported", NULL, "face-down"); // page-ranges-supported if (pdf_supported) ippAddBoolean(attrs, IPP_TAG_PRINTER, "page-ranges-supported", 1); // pages-per-minute if (data->ppm > 0) ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "pages-per-minute", data->ppm); else ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "pages-per-minute", 1); // pages-per-minute-color if (data->ppm_color > 0) ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "pages-per-minute-color", data->ppm_color); if (pdf_supported) { // pdf-k-octets-supported int upper = 0, lower = ippGetRange(ippFindAttribute(printer->attrs, "job-k-octets-supported", IPP_TAG_RANGE), 0, &upper); // Range of k-octets-supported... ippAddRange(attrs, IPP_TAG_PRINTER, "pdf-k-octets-supported", lower, upper); // pdf-versions-supported ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pdf-versions-supported", (int)(sizeof(pdf_versions_supported) / sizeof(pdf_versions_supported[0])), NULL, pdf_versions_supported); } // print-color-mode-supported for (num_values = 0, bit = PAPPL_COLOR_MODE_AUTO; bit <= PAPPL_COLOR_MODE_PROCESS_MONOCHROME; bit *= 2) { if (bit & data->color_supported) svalues[num_values ++] = _papplColorModeString(bit); } if (num_values > 0) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-supported", num_values, NULL, svalues); // print-darkness-supported if (data->darkness_supported) ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "print-darkness-supported", 2 * data->darkness_supported); // print-speed-supported if (data->speed_supported[1]) ippAddRange(attrs, IPP_TAG_PRINTER, "print-speed-supported", data->speed_supported[0], data->speed_supported[1]); // printer-darkness-supported if (data->darkness_supported) ippAddInteger(attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-darkness-supported", data->darkness_supported); // printer-device-id if (printer->device_id) { ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, printer->device_id); } else { // Generate printer-device-id value as needed... char mfg[128], // Manufacturer name *mdl, // Model name cmd[128]; // Command (format) list ipp_attribute_t *formats; // "document-format-supported" attribute cups_len_t count; // Number of values // Assume make and model are separated by a space... papplCopyString(mfg, data->make_and_model, sizeof(mfg)); if ((mdl = strchr(mfg, ' ')) != NULL) *mdl++ = '\0'; // Nul-terminate the make else mdl = mfg; // No separator, so assume the make and model are the same formats = ippFindAttribute(attrs, "document-format-supported", IPP_TAG_MIMETYPE); count = ippGetCount(formats); for (i = 0, ptr = cmd; i < count; i ++) { const char *format = ippGetString(formats, i, NULL); // Current MIME media type if (!strcmp(format, "application/pdf")) format = "PDF"; else if (!strcmp(format, "application/postscript")) format = "PS"; else if (!strcmp(format, "application/vnd.eltron-epl")) format = "EPL"; else if (!strcmp(format, "application/vnd.hp-pcl")) format = "PCL"; else if (!strcmp(format, "application/vnd.sii-slp")) format = "SIISLP"; else if (!strcmp(format, "application/vnd.tsc-tspl")) format = "TSPL"; else if (!strcmp(format, "application/vnd.zebra-cpcl")) format = "CPCL"; else if (!strcmp(format, "application/vnd.zebra-zpl")) format = "ZPL"; else if (!strcmp(format, "image/jpeg")) format = "JPEG"; else if (!strcmp(format, "image/png")) format = "PNG"; else if (!strcmp(format, "image/pwg-raster")) format = "PWGRaster"; else if (!strcmp(format, "image/urf")) format = "URF"; else if (!strcmp(format, "text/plain")) format = "TXT"; else if (!strcmp(format, "application/octet-stream")) continue; if (ptr > cmd) snprintf(ptr, sizeof(cmd) - (size_t)(ptr - cmd), ",%s", format); else papplCopyString(cmd, format, sizeof(cmd)); ptr += strlen(ptr); } *ptr = '\0'; ippAddStringf(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, "MFG:%s;MDL:%s;CMD:%s;", mfg, mdl, cmd); } // printer-kind for (num_values = 0, bit = PAPPL_KIND_DISC; bit <= PAPPL_KIND_ROLL; bit *= 2) { if (bit & data->kind) svalues[num_values ++] = _papplKindString(bit); } if (num_values > 0) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-kind", num_values, NULL, svalues); // printer-make-and-model ippAddString(attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, data->make_and_model); // printer-output-tray if (data->num_bin > 0) { for (i = 0, attr = NULL; i < (cups_len_t)data->num_bin; i ++) { snprintf(output_tray, sizeof(output_tray), "type=unRemovableBin;maxcapacity=-2;remaining=-2;status=0;name=%s;%s", data->bin[i], data->output_face_up ? "stackingorder=lastToFirst;pagedelivery=faceUp;" : "stackingorder=firstToLast;pagedelivery=faceDown;"); if (attr) ippSetOctetString(attrs, &attr, ippGetCount(attr), output_tray, (cups_len_t)strlen(output_tray)); else attr = ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-output-tray", output_tray, (cups_len_t)strlen(output_tray)); } } else if (data->output_face_up) { papplCopyString(output_tray, "type=unRemovableBin;maxcapacity=-2;remaining=-2;status=0;name=face-up;stackingorder=lastToFirst;pagedelivery=faceUp;", sizeof(output_tray)); ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-output-tray", output_tray, (cups_len_t)strlen(output_tray)); } else { papplCopyString(output_tray, "type=unRemovableBin;maxcapacity=-2;remaining=-2;status=0;name=face-down;stackingorder=firstToLast;pagedelivery=faceDown;", sizeof(output_tray)); ippAddOctetString(attrs, IPP_TAG_PRINTER, "printer-output-tray", output_tray, (cups_len_t)strlen(output_tray)); } // printer-resolution-supported if (data->num_resolution > 0) ippAddResolutions(attrs, IPP_TAG_PRINTER, "printer-resolution-supported", (cups_len_t)data->num_resolution, IPP_RES_PER_INCH, data->x_resolution, data->y_resolution); // printer-settable-attributes memcpy((void *)svalues, printer_settable_attributes, sizeof(printer_settable_attributes)); num_values = (int)(sizeof(printer_settable_attributes) / sizeof(printer_settable_attributes[0])); if (data->finishings) { svalues[num_values ++] = "finishings-col-default"; svalues[num_values ++] = "finishings-default"; } if (data->mode_supported) svalues[num_values ++] = "label-mode-configured"; if (data->tear_offset_supported[1]) svalues[num_values ++] = "label-tear-off-configured"; if (data->num_bin) svalues[num_values ++] = "output-bin-default"; if (data->darkness_supported) svalues[num_values ++] = "print-darkness-default"; if (data->speed_supported[1]) svalues[num_values ++] = "print-speed-default"; if (data->darkness_supported) svalues[num_values ++] = "printer-darkness-configured"; if (system->wifi_join_cb) { svalues[num_values ++] = "printer-wifi-password"; svalues[num_values ++] = "printer-wifi-ssid"; } if (data->sides_supported != PAPPL_SIDES_ONE_SIDED) svalues[num_values ++] = "sides-default"; for (i = 0; i < (cups_len_t)data->num_vendor && num_values < (int)(sizeof(svalues) / sizeof(svalues[0])); i ++) { snprintf(vvalues[i], sizeof(vvalues[0]), "%s-default", data->vendor[i]); svalues[num_values ++] = vvalues[i]; } ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "printer-settable-attributes", num_values, NULL, svalues); // pwg-raster-document-resolution-supported if (data->num_resolution > 0) ippAddResolutions(attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", (cups_len_t)data->num_resolution, IPP_RES_PER_INCH, data->x_resolution, data->y_resolution); // pwg-raster-document-sheet-back if (data->duplex) { static const char * const backs[] = // "pwg-raster-document-sheet-back" values { "normal", "flipped", "rotated", "manual-tumble" }; ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pwg-raster-document-sheet-back", NULL, backs[data->duplex - 1]); } // pwg-raster-document-type-supported for (num_values = 0, bit = PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8; bit <= PAPPL_PWG_RASTER_TYPE_SRGB_16; bit *= 2) { if (data->raster_types & bit) svalues[num_values ++] = _papplRasterTypeString(bit); } if (num_values > 0) ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pwg-raster-document-type-supported", num_values, NULL, svalues); // sides-supported if (data->sides_supported) { for (num_values = 0, bit = PAPPL_SIDES_ONE_SIDED; bit <= PAPPL_SIDES_TWO_SIDED_SHORT_EDGE; bit *= 2) { if (data->sides_supported & bit) svalues[num_values ++] = _papplSidesString(bit); } ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-supported", num_values, NULL, svalues); } else ippAddString(attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-supported", NULL, "one-sided"); // urf-supported if (data->num_resolution > 0) { char dm[32], // DM (duplex mode) value is[256], // IS (media-source) values mt[256], // MT (media-type) values ob[256], // OB (output-bin) values rs[32]; // RS (resolution) values num_values = 0; svalues[num_values ++] = "V1.5"; svalues[num_values ++] = "W8"; if (data->raster_types & PAPPL_PWG_RASTER_TYPE_SRGB_8) svalues[num_values ++] = "SRGB24"; if (data->raster_types & PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_16) svalues[num_values ++] = "ADOBERGB24-48"; else if (data->raster_types & PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8) svalues[num_values ++] = "ADOBERGB24"; if (data->raster_types & PAPPL_PWG_RASTER_TYPE_BLACK_16) svalues[num_values ++] = "DEVW8-16"; else if (data->raster_types & PAPPL_PWG_RASTER_TYPE_BLACK_8) svalues[num_values ++] = "DEVW8"; if (data->raster_types & PAPPL_PWG_RASTER_TYPE_RGB_16) svalues[num_values ++] = "DEVRGB24-48"; else if (data->raster_types & PAPPL_PWG_RASTER_TYPE_RGB_8) svalues[num_values ++] = "DEVRGB24"; if (data->raster_types & PAPPL_PWG_RASTER_TYPE_CMYK_16) svalues[num_values ++] = "DEVCMYK32-64"; else if (data->raster_types & PAPPL_PWG_RASTER_TYPE_CMYK_8) svalues[num_values ++] = "DEVCMYK32"; svalues[num_values ++] = "PQ3-4-5"; if (data->duplex) { snprintf(dm, sizeof(dm), "DM%d", (int)data->duplex); svalues[num_values ++] = dm; } else if (data->sides_supported & PAPPL_SIDES_TWO_SIDED_LONG_EDGE) svalues[num_values ++] = "DM1"; if (fn[0]) svalues[num_values ++] = fn; if (data->num_source) { static const char * const iss[] = // IS/"media-source" values { "auto", "main", "alternate", "large-capacity", "manual", "envelope", "disc", "photo", "hagaki", "main-roll", "alternate-roll", "top", "middle", "bottom", "side", "left", "right", "center", "rear", "by-pass-tray", // a.k.a. multi-purpose tray "tray-1", "tray-2", "tray-3", "tray-4", "tray-5", "tray-6", "tray-7", "tray-8", "tray-9", "tray-10", "tray-11", "tray-12", "tray-13", "tray-14", "tray-15", "tray-16", "tray-17", "tray-18", "tray-19", "tray-20", "roll-1", "roll-2", "roll-3", "roll-4", "roll-5", "roll-6", "roll-7", "roll-8", "roll-9", "roll-10" }; for (i = 0, ptr = is, *ptr = '\0', prefix = "IS"; i < (cups_len_t)data->num_source; i ++) { for (j = 0; j < (int)(sizeof(iss) / sizeof(iss[0])); j ++) { if (!strcmp(iss[j], data->source[i])) { snprintf(ptr, sizeof(is) - (size_t)(ptr - is), "%s%u", prefix, (unsigned)j); ptr += strlen(ptr); prefix = "-"; } } } if (is[0]) svalues[num_values ++] = is; } if (data->num_type) { static const char * const mts[] = // MT/"media-type" values { "auto", "stationery", "transparency", "envelope", "cardstock", "labels", "stationery-letterhead", "disc", "photographic-matte", "photographic-satin", "photographic-semi-gloss", "photographic-glossy", "photographic-high-gloss", "other" }; for (i = 0, ptr = mt, *ptr = '\0', prefix = "MT"; i < (cups_len_t)data->num_type; i ++) { for (j = 0; j < (int)(sizeof(mts) / sizeof(mts[0])); j ++) { if (!strcmp(mts[j], data->type[i])) { snprintf(ptr, sizeof(mt) - (size_t)(ptr - mt), "%s%u", prefix, (unsigned)j); ptr += strlen(ptr); prefix = "-"; } } } if (mt[0]) svalues[num_values ++] = mt; } if (data->num_bin) { static const char * const obs[] = // OB/"output-bin" values { "auto", "top", "middle", "bottom", "side", "left", "right", "center", "rear", "face-up", "face-down", "large-capacity", "stacker", "my-mailbox", "mailbox-1", "mailbox-2", "mailbox-3", "mailbox-4", "mailbox-5", "mailbox-6", "mailbox-7", "mailbox-8", "mailbox-9", "mailbox-10", "stacker-1", "stacker-2", "stacker-3", "stacker-4", "stacker-5", "stacker-6", "stacker-7", "stacker-8", "stacker-9", "stacker-10", "tray-1", "tray-2", "tray-3", "tray-4", "tray-5", "tray-6", "tray-7", "tray-8", "tray-9", "tray-10" }; for (i = 0, ptr = ob, *ptr = '\0', prefix = "OB"; i < (cups_len_t)data->num_bin; i ++) { for (j = 0; j < (int)(sizeof(obs) / sizeof(obs[0])); j ++) { if (!strcmp(obs[j], data->bin[i])) { snprintf(ptr, sizeof(ob) - (size_t)(ptr - ob), "%s%u", prefix, (unsigned)j); ptr += strlen(ptr); prefix = "-"; } } } if (ob[0]) svalues[num_values ++] = ob; } else if (data->output_face_up) svalues[num_values ++] = "OB9"; else svalues[num_values ++] = "OB10"; if (data->input_face_up) svalues[num_values ++] = "IFU0"; if (data->output_face_up) svalues[num_values ++] = "OFU0"; if (data->num_resolution == 1) snprintf(rs, sizeof(rs), "RS%d", data->x_resolution[0]); else snprintf(rs, sizeof(rs), "RS%d-%d", data->x_resolution[data->num_resolution - 2], data->x_resolution[data->num_resolution - 1]); svalues[num_values ++] = rs; ippAddStrings(attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "urf-supported", num_values, NULL, svalues); } return (attrs); } // // 'validate_defaults()' - Validate the printing defaults and supported values. // static bool // O - `true` if valid, `false` otherwise validate_defaults( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *driver_data,// I - Driver values pappl_pr_driver_data_t *data) // I - Default values { bool ret = true; // Return value int i; // Looping var int max_width = 0, // Maximum media width max_length = 0, // Maximum media length min_width = 99999999, // Minimum media width min_length = 99999999; // Minimum media length pwg_media_t *pwg; // PWG media size if (!(data->identify_default & driver_data->identify_supported) && driver_data->identify_supported) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported identify-actions-default=0x%04x", data->identify_default); ret = false; } else if (driver_data->identify_supported) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "identify-actions-default=0x%04x", data->identify_default); } for (i = 0; i < driver_data->num_media; i ++) { if (!strcmp(driver_data->media[i], data->media_default.size_name)) break; if ((pwg = pwgMediaForPWG(driver_data->media[i])) != NULL) { if (pwg->width > max_width) max_width = pwg->width; if (pwg->width < min_width) min_width = pwg->width; if (pwg->length > max_length) max_length = pwg->length; if (pwg->length < min_length) min_length = pwg->length; } } if (i < driver_data->num_media || (data->media_default.size_width >= min_width && data->media_default.size_width <= max_width && data->media_default.size_length >= min_length && data->media_default.size_length <= max_length)) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "media-default=%s", data->media_default.size_name); } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-default=%s", data->media_default.size_name); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "width=%d, length=%d", data->media_default.size_width, data->media_default.size_length); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "num_media=%d, min_width=%d, max_width=%d, min_length=%d, max_length=%d", driver_data->num_media, min_width, max_width, min_length, max_length); ret = false; } papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "orientation-requested-default=%d(%s)", data->orient_default, ippEnumString("orientation-requested", (int)data->orient_default)); if (!(data->color_default & driver_data->color_supported)) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported print-color-mode-default=%s(0x%04x)", _papplColorModeString(data->color_default), data->color_default); ret = false; } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "print-color-mode-default=%s(0x%04x)", _papplColorModeString(data->color_default), data->color_default); } papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "print-content-default=%s(0x%04x)", _papplContentString(data->content_default), data->content_default); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "print-quality-default=%d(%s)", (int)data->quality_default, ippEnumString("print-quality", (int)data->quality_default)); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "print-scaling-default=%s(0x%04x)", _papplScalingString(data->scaling_default), data->scaling_default); for (i = 0; i < driver_data->num_resolution; i ++) { if (data->x_default == driver_data->x_resolution[i] && data->y_default == driver_data->y_resolution[i]) break; } if (i >= driver_data->num_resolution) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported printer-resolution-default=%dx%ddpi", data->x_default, data->y_default); ret = false; } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "printer-resolution-default=%dx%ddpi", data->x_default, data->y_default); } if (!(data->sides_default & driver_data->sides_supported) && driver_data->sides_supported) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported sides-default=%s(0x%04x)", _papplSidesString(data->sides_default), data->sides_default); ret = false; } else if (driver_data->sides_supported) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "sides-default=%s(0x%04x)", _papplSidesString(data->sides_default), data->sides_default); } return (ret); } // // 'validate_driver()' - Validate the driver-specific values. // static bool // O - `true` if valid, `false` otherwise validate_driver( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *data) // I - Driver values { bool ret = true; // Return value int i, // Looping variable num_icons; // Number of printer icons const char *venptr; // Pointer into vendor name static const char * const icon_sizes[] = { // Icon sizes "small-48x48", "medium-128x128", "large-512x512" }; // Validate all driver fields and show debug/warning/fatal errors along the way. if (data->extension) papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver uses extension data (%p) and %sdelete function.", data->extension, data->delete_cb ? "" : "no "); if (!data->identify_cb) papplLogPrinter(printer, PAPPL_LOGLEVEL_WARN, "Driver does not support identification."); if (data->printfile_cb) { if (data->format) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver supports raw printing of '%s' files.", data->format); } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver supports raw printing but hasn't set the format."); ret = false; } } if (!data->rendjob_cb || !data->rendpage_cb || !data->rstartjob_cb || !data->rstartpage_cb || !data->rwriteline_cb) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide required raster printing callbacks."); ret = false; } if (!data->status_cb) papplLogPrinter(printer, PAPPL_LOGLEVEL_WARN, "Driver does not support status updates."); if (!data->testpage_cb) papplLogPrinter(printer, PAPPL_LOGLEVEL_WARN, "Driver does not support a self-test page."); if (!data->make_and_model[0]) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide a make_and_model string."); ret = false; } if (data->ppm <= 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide a valid ppm value (%d).", data->ppm); ret = false; } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver reports ppm %d.", data->ppm); } if (data->ppm_color < 0 || data->ppm_color > data->ppm) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide a valid ppm_color value (%d).", data->ppm_color); ret = false; } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver reports ppm_color %d.", data->ppm_color); } for (i = 0, num_icons = 0; i < 3; i ++) { if (data->icons[i].filename[0]) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver provides %s icon in file '%s'.", icon_sizes[i], data->icons[i].filename); num_icons ++; } else if (data->icons[i].data && data->icons[i].datalen > 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Driver provides %s icon in memory (%u bytes).", icon_sizes[i], (unsigned)data->icons[i].datalen); num_icons ++; } } if (num_icons == 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_WARN, "Driver does not provide printer icons, using defaults."); } if (!data->raster_types) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide required raster types."); ret = false; } if (data->num_resolution <= 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Driver does not provide required raster resolutions."); ret = false; } else { for (i = 0; i < data->num_resolution; i ++) { if (data->x_resolution[i] <= 0 || data->y_resolution[i] <= 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid driver raster resolution %dx%ddpi.", data->x_resolution[i], data->y_resolution[i]); ret = false; } } } if (data->left_right < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid driver left/right margins value %d.", data->left_right); ret = false; } if (data->bottom_top < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid driver bottom/top margins value %d.", data->bottom_top); ret = false; } for (i = 0; i < data->num_media; i ++) { if (!pwgMediaForPWG(data->media[i])) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid driver media value '%s'.", data->media[i]); ret = false; } } for (i = 0; i < data->num_vendor; i ++) { for (venptr = data->vendor[i]; *venptr; venptr ++) { int vench = *venptr & 255; // Current character if (!isalnum(vench) && vench != '-' && vench != '_') break; } if (*venptr) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid vendor attribute name '%s'.", data->vendor[i]); ret = false; } } return (ret); } // // 'validate_ready()' - Validate the ready media values. // static bool // O - `true` if valid, `false` otherwise validate_ready( pappl_printer_t *printer, // I - Printer pappl_pr_driver_data_t *driver_data,// I - Driver data int num_ready, // I - Number of ready media values pappl_media_col_t *ready) // I - Ready media values { bool ret = true; // Return value int i, j; // Looping vars int max_width = 0, // Maximum media width max_length = 0, // Maximum media length min_width = 99999999, // Minimum media width min_length = 99999999; // Minimum media length pwg_media_t *pwg; // PWG media size if (num_ready > PAPPL_MAX_SOURCE) return (false); // Determine the range of media sizes... for (i = 0; i < driver_data->num_media; i ++) { if ((pwg = pwgMediaForPWG(driver_data->media[i])) != NULL) { if (pwg->width > max_width) max_width = pwg->width; if (pwg->width < min_width) min_width = pwg->width; if (pwg->length > max_length) max_length = pwg->length; if (pwg->length < min_length) min_length = pwg->length; } } for (i = 0; i < num_ready; i ++) { if (!ready[i].size_name[0]) continue; if (!pwgMediaForPWG(ready[i].size_name)) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Invalid media-ready.media-size-name='%s'.", ready[i].size_name); ret = false; } else if (ready[i].size_width < min_width || ready[i].size_width > max_width || ready[i].size_length < min_length || ready[i].size_length > max_length) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-size=%.2fx%.2fmm.", ready[i].size_width * 0.01, ready[i].size_length * 0.01); ret = false; } if (ready[i].left_margin < driver_data->left_right && !driver_data->borderless) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-left-margin=%d.", ready[i].left_margin); ret = false; } if (ready[i].right_margin < driver_data->left_right && !driver_data->borderless) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-right-margin=%d.", ready[i].right_margin); ret = false; } if (ready[i].top_margin < driver_data->bottom_top && !driver_data->borderless) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-top-margin=%d.", ready[i].top_margin); ret = false; } if (ready[i].bottom_margin < driver_data->bottom_top && !driver_data->borderless) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-bottom-margin=%d.", ready[i].bottom_margin); ret = false; } for (j = 0; j < driver_data->num_source; j ++) { if (!strcmp(ready[i].source, driver_data->source[j])) break; } if (j >= driver_data->num_source) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-source='%s'.", ready[i].source); ret = false; } for (j = 0; j < driver_data->num_type; j ++) { if (!strcmp(ready[i].type, driver_data->type[j])) break; } if (j >= driver_data->num_type) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unsupported media-ready.media-type='%s'.", ready[i].type); ret = false; } } return (ret); } pappl-1.4.9/pappl/printer-ipp.c000066400000000000000000002302521476704353100164100ustar00rootroot00000000000000// // Printer IPP processing for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local type... // typedef struct _pappl_attr_s // Input attribute structure { const char *name; // Attribute name ipp_tag_t value_tag; // Value tag cups_len_t max_count; // Max number of values } _pappl_attr_t; // // Local functions... // static pappl_job_t *create_job(pappl_client_t *client); static void ipp_cancel_current_job(pappl_client_t *client); static void ipp_cancel_jobs(pappl_client_t *client); static void ipp_create_job(pappl_client_t *client); static void ipp_disable_printer(pappl_client_t *client); static void ipp_enable_printer(pappl_client_t *client); static void ipp_get_jobs(pappl_client_t *client); static void ipp_get_printer_attributes(pappl_client_t *client); static void ipp_hold_new_jobs(pappl_client_t *client); static void ipp_identify_printer(pappl_client_t *client); static void ipp_pause_printer(pappl_client_t *client); static void ipp_print_job(pappl_client_t *client); static void ipp_release_held_new_jobs(pappl_client_t *client); static void ipp_resume_printer(pappl_client_t *client); static void ipp_set_printer_attributes(pappl_client_t *client); static void ipp_validate_job(pappl_client_t *client); static bool valid_job_attributes(pappl_client_t *client); // // '_papplPrinterCopyAttributesNoLock()' - Copy printer attributes to a response... // void _papplPrinterCopyAttributesNoLock( pappl_printer_t *printer, // I - Printer pappl_client_t *client, // I - Client cups_array_t *ra, // I - Requested attributes const char *format) // I - "document-format" value, if any { cups_len_t i, // Looping var num_values; // Number of values unsigned bit; // Current bit value const char *svalues[100]; // String values int ivalues[100]; // Integer values pappl_pr_driver_data_t *data = &printer->driver_data; // Driver data const char *webscheme = (httpAddrIsLocalhost(httpGetAddress(client->http)) || !papplSystemGetTLSOnly(client->system)) ? "http" : "https"; // URL scheme for resources _papplCopyAttributes(client->response, printer->attrs, ra, IPP_TAG_ZERO, true); _papplCopyAttributes(client->response, printer->driver_attrs, ra, IPP_TAG_ZERO, false); _papplPrinterCopyStateNoLock(printer, IPP_TAG_PRINTER, client->response, client, ra); if (!ra || cupsArrayFind(ra, "copies-supported")) { // Filter copies-supported value based on the document format... // (no copy support for streaming raster formats) if (format && (!strcmp(format, "image/pwg-raster") || !strcmp(format, "image/urf"))) ippAddRange(client->response, IPP_TAG_PRINTER, "copies-supported", 1, 1); else ippAddRange(client->response, IPP_TAG_PRINTER, "copies-supported", 1, 999); } if (!ra || cupsArrayFind(ra, "identify-actions-default")) { for (num_values = 0, bit = PAPPL_IDENTIFY_ACTIONS_DISPLAY; bit <= PAPPL_IDENTIFY_ACTIONS_SPEAK; bit *= 2) { if (data->identify_default & bit) svalues[num_values ++] = _papplIdentifyActionsString(bit); } if (num_values > 0) ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "identify-actions-default", IPP_NUM_CAST num_values, NULL, svalues); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "identify-actions-default", NULL, "none"); } if (printer->max_preserved_jobs > 0) { static const char * const job_retain_until[] = { // job-retain-until-supported values "day-time", "evening", "indefinite", "night", "no-hold", "second-shift", "third-shift", "weekend" }; if (!ra || cupsArrayFind(ra, "job-retain-until-default")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-retain-until-default", NULL, "none"); if (!ra || cupsArrayFind(ra, "job-retain-until-interval-default")) ippAddOutOfBand(client->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE, "job-retain-until-interval-default"); if (!ra || cupsArrayFind(ra, "job-retain-until-interval-supported")) ippAddRange(client->response, IPP_TAG_PRINTER, "job-retain-until-interval-supported", 0, 86400); if (!ra || cupsArrayFind(ra, "job-retain-until-supported")) ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-retain-until-supported", (cups_len_t)(sizeof(job_retain_until) / sizeof(job_retain_until[0])), NULL, job_retain_until); if (!ra || cupsArrayFind(ra, "job-retain-until-time-supported")) ippAddRange(client->response, IPP_TAG_PRINTER, "job-retain-until-time-supported", 0, 86400); } if (!ra || cupsArrayFind(ra, "job-spooling-supported")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-spooling-supported", NULL, (printer->max_active_jobs == 1 || (format && (!strcmp(format, "image/pwg-raster") || !strcmp(format, "image/urf")))) ? "stream" : "spool"); if ((!ra || cupsArrayFind(ra, "label-mode-configured")) && data->mode_configured) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "label-mode-configured", NULL, _papplLabelModeString(data->mode_configured)); if ((!ra || cupsArrayFind(ra, "label-tear-offset-configured")) && data->tear_offset_supported[1] > 0) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "label-tear-offset-configured", data->tear_offset_configured); if (printer->num_supply > 0) { pappl_supply_t *supply = printer->supply; // Supply values... if (!ra || cupsArrayFind(ra, "marker-colors")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) svalues[i] = _papplMarkerColorString(supply[i].color); ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "marker-colors", IPP_NUM_CAST printer->num_supply, NULL, svalues); } if (!ra || cupsArrayFind(ra, "marker-high-levels")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) ivalues[i] = supply[i].is_consumed ? 100 : 90; ippAddIntegers(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "marker-high-levels", IPP_NUM_CAST printer->num_supply, ivalues); } if (!ra || cupsArrayFind(ra, "marker-levels")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) ivalues[i] = supply[i].level; ippAddIntegers(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "marker-levels", IPP_NUM_CAST printer->num_supply, ivalues); } if (!ra || cupsArrayFind(ra, "marker-low-levels")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) ivalues[i] = supply[i].is_consumed ? 10 : 0; ippAddIntegers(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "marker-low-levels", IPP_NUM_CAST printer->num_supply, ivalues); } if (!ra || cupsArrayFind(ra, "marker-names")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) svalues[i] = supply[i].description; ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "marker-names", IPP_NUM_CAST printer->num_supply, NULL, svalues); } if (!ra || cupsArrayFind(ra, "marker-types")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) svalues[i] = _papplMarkerTypeString(supply[i].type); ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "marker-types", IPP_NUM_CAST printer->num_supply, NULL, svalues); } } if ((!ra || cupsArrayFind(ra, "media-col-default")) && data->media_default.size_name[0]) { ipp_t *col = _papplMediaColExport(&printer->driver_data, &data->media_default, 0); // Collection value ippAddCollection(client->response, IPP_TAG_PRINTER, "media-col-default", col); ippDelete(col); } if (!ra || cupsArrayFind(ra, "media-col-ready")) { cups_len_t j, // Looping var count; // Number of values ipp_t *col; // Collection value ipp_attribute_t *attr; // media-col-ready attribute pappl_media_col_t media; // Current media... for (i = 0, count = 0; i < (cups_len_t)printer->num_ready; i ++) { if (data->media_ready[i].size_name[0]) count ++; } if (data->borderless && (data->bottom_top != 0 || data->left_right != 0)) count *= 2; // Need to report ready media for borderless, too... if (count > 0) { attr = ippAddCollections(client->response, IPP_TAG_PRINTER, "media-col-ready", IPP_NUM_CAST count, NULL); for (i = 0, j = 0; i < (cups_len_t)printer->num_ready && j < count; i ++) { if (data->media_ready[i].size_name[0]) { if (data->borderless && (data->bottom_top != 0 || data->left_right != 0)) { // Report both bordered and borderless media-col values... media = data->media_ready[i]; media.bottom_margin = media.top_margin = data->bottom_top; media.left_margin = media.right_margin = data->left_right; col = _papplMediaColExport(&printer->driver_data, &media, 0); ippSetCollection(client->response, &attr, IPP_NUM_CAST j ++, col); ippDelete(col); media.bottom_margin = media.top_margin = 0; media.left_margin = media.right_margin = 0; col = _papplMediaColExport(&printer->driver_data, &media, 0); ippSetCollection(client->response, &attr, IPP_NUM_CAST j ++, col); ippDelete(col); } else { // Just report the single media-col value... col = _papplMediaColExport(&printer->driver_data, data->media_ready + i, 0); ippSetCollection(client->response, &attr, IPP_NUM_CAST j ++, col); ippDelete(col); } } } } } if ((!ra || cupsArrayFind(ra, "media-default")) && data->media_default.size_name[0]) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", NULL, data->media_default.size_name); if (!ra || cupsArrayFind(ra, "media-ready")) { cups_len_t j, // Looping vars count; // Number of values ipp_attribute_t *attr; // media-col-ready attribute for (i = 0, count = 0; i < (cups_len_t)printer->num_ready; i ++) { if (data->media_ready[i].size_name[0]) count ++; } if (count > 0) { attr = ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-ready", IPP_NUM_CAST count, NULL, NULL); for (i = 0, j = 0; i < (cups_len_t)printer->num_ready && j < count; i ++) { if (data->media_ready[i].size_name[0]) ippSetString(client->response, &attr, IPP_NUM_CAST j ++, data->media_ready[i].size_name); } } } if (!ra || cupsArrayFind(ra, "multiple-document-handling-default")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-document-handling-default", NULL, "separate-documents-collated-copies"); if (!ra || cupsArrayFind(ra, "orientation-requested-default")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-default", (int)data->orient_default); if (!ra || cupsArrayFind(ra, "output-bin-default")) { if (data->num_bin > 0) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-default", NULL, data->bin[data->bin_default]); else if (data->output_face_up) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-default", NULL, "face-up"); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "output-bin-default", NULL, "face-down"); } if ((!ra || cupsArrayFind(ra, "print-color-mode-default")) && data->color_default) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-default", NULL, _papplColorModeString(data->color_default)); if (!ra || cupsArrayFind(ra, "print-content-optimize-default")) { if (data->content_default) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-default", NULL, _papplContentString(data->content_default)); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-default", NULL, "auto"); } if (!ra || cupsArrayFind(ra, "print-quality-default")) { if (data->quality_default) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", (int)data->quality_default); else ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_NORMAL); } if (!ra || cupsArrayFind(ra, "print-scaling-default")) { if (data->scaling_default) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-scaling-default", NULL, _papplScalingString(data->scaling_default)); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-scaling-default", NULL, "auto"); } if (!ra || cupsArrayFind(ra, "printer-config-change-date-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time)); if (!ra || cupsArrayFind(ra, "printer-config-change-time")) { if (printer->config_time > printer->start_time) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-config-change-time", (int)(printer->config_time - printer->start_time)); else ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-config-change-time", 1); } if (!ra || cupsArrayFind(ra, "printer-contact-col")) { ipp_t *col = _papplContactExport(&printer->contact); ippAddCollection(client->response, IPP_TAG_PRINTER, "printer-contact-col", col); ippDelete(col); } if (!ra || cupsArrayFind(ra, "printer-current-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-current-time", ippTimeToDate(time(NULL))); if ((!ra || cupsArrayFind(ra, "printer-darkness-configured")) && data->darkness_supported > 0) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-darkness-configured", data->darkness_configured); if (!ra || cupsArrayFind(ra, "printer-dns-sd-name")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-dns-sd-name", NULL, printer->dns_sd_name ? printer->dns_sd_name : ""); // _papplRWLockRead(client->system); _papplSystemExportVersions(client->system, client->response, IPP_TAG_PRINTER, ra); // _papplRWUnlock(client->system); if (!ra || cupsArrayFind(ra, "printer-geo-location")) { if (printer->geo_location) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, printer->geo_location); else ippAddOutOfBand(client->response, IPP_TAG_PRINTER, IPP_TAG_UNKNOWN, "printer-geo-location"); } if (!ra || cupsArrayFind(ra, "printer-icons")) { char uris[3][1024]; // Buffers for URIs const char *values[3]; // Values for attribute httpAssembleURIf(HTTP_URI_CODING_ALL, uris[0], sizeof(uris[0]), webscheme, NULL, client->host_field, client->host_port, "%s/icon-sm.png", printer->uriname); httpAssembleURIf(HTTP_URI_CODING_ALL, uris[1], sizeof(uris[1]), webscheme, NULL, client->host_field, client->host_port, "%s/icon-md.png", printer->uriname); httpAssembleURIf(HTTP_URI_CODING_ALL, uris[2], sizeof(uris[2]), webscheme, NULL, client->host_field, client->host_port, "%s/icon-lg.png", printer->uriname); values[0] = uris[0]; values[1] = uris[1]; values[2] = uris[2]; ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-icons", 3, NULL, values); } if (!ra || cupsArrayFind(ra, "printer-impressions-completed")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-impressions-completed", printer->impcompleted); if (!ra || cupsArrayFind(ra, "printer-input-tray")) { ipp_attribute_t *attr = NULL; // "printer-input-tray" attribute char value[256]; // Value for current tray pappl_media_col_t *media; // Media in the tray for (i = 0, media = data->media_ready; i < (cups_len_t)data->num_source; i ++, media ++) { const char *type; // Tray type if (!strcmp(data->source[i], "manual")) type = "sheetFeedManual"; else if (!strcmp(data->source[i], "by-pass-tray")) type = "sheetFeedAutoNonRemovableTray"; else type = "sheetFeedAutoRemovableTray"; snprintf(value, sizeof(value), "type=%s;mediafeed=%d;mediaxfeed=%d;maxcapacity=%d;level=-2;status=0;name=%s;", type, media->size_length, media->size_width, !strcmp(media->source, "manual") ? 1 : -2, media->source); if (attr) ippSetOctetString(client->response, &attr, ippGetCount(attr), value, IPP_NUM_CAST strlen(value)); else attr = ippAddOctetString(client->response, IPP_TAG_PRINTER, "printer-input-tray", value, IPP_NUM_CAST strlen(value)); } // The "auto" tray is a dummy entry... papplCopyString(value, "type=other;mediafeed=0;mediaxfeed=0;maxcapacity=-2;level=-2;status=0;name=auto;", sizeof(value)); ippSetOctetString(client->response, &attr, ippGetCount(attr), value, IPP_NUM_CAST strlen(value)); } if (!ra || cupsArrayFind(ra, "printer-location")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL, printer->location ? printer->location : ""); if (!ra || cupsArrayFind(ra, "printer-more-info")) { char uri[1024]; // URI value httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), webscheme, NULL, client->host_field, client->host_port, "%s/", printer->uriname); ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", NULL, uri); } if (!ra || cupsArrayFind(ra, "printer-organization")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, printer->organization ? printer->organization : ""); if (!ra || cupsArrayFind(ra, "printer-organizational-unit")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, printer->org_unit ? printer->org_unit : ""); if (!ra || cupsArrayFind(ra, "printer-resolution-default")) ippAddResolution(client->response, IPP_TAG_PRINTER, "printer-resolution-default", IPP_RES_PER_INCH, data->x_default, data->y_default); if (!ra || cupsArrayFind(ra, "printer-speed-default")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-speed-default", data->speed_default); if (!ra || cupsArrayFind(ra, "printer-state-change-date-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time)); if (!ra || cupsArrayFind(ra, "printer-state-change-time")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-state-change-time", (int)(printer->state_time - printer->start_time)); if (!ra || cupsArrayFind(ra, "printer-strings-languages-supported")) { _pappl_resource_t *r; // Current resource cups_len_t rcount; // Number of resources // _papplRWLockRead(printer->system); // Cannot use cupsArrayGetFirst/Last since other threads might be iterating // this array... for (i = 0, num_values = 0, rcount = cupsArrayGetCount(printer->system->resources); i < rcount && num_values < (cups_len_t)(sizeof(svalues) / sizeof(svalues[0])); i ++) { r = (_pappl_resource_t *)cupsArrayGetElement(printer->system->resources, (size_t)i); if (r->language) svalues[num_values ++] = r->language; } // _papplRWUnlock(printer->system); if (num_values > 0) ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "printer-strings-languages-supported", IPP_NUM_CAST num_values, NULL, svalues); } if (!ra || cupsArrayFind(ra, "printer-strings-uri")) { const char *lang = ippGetString(ippFindAttribute(client->request, "attributes-natural-language", IPP_TAG_LANGUAGE), 0, NULL); // Language char baselang[3], // Base language uri[1024]; // Strings file URI _pappl_resource_t *r; // Current resource cups_len_t rcount; // Number of resources papplCopyString(baselang, lang, sizeof(baselang)); // _papplRWLockRead(printer->system); // Cannot use cupsArrayGetFirst/Last since other threads might be iterating // this array... for (i = 0, rcount = cupsArrayGetCount(printer->system->resources); i < rcount; i ++) { r = (_pappl_resource_t *)cupsArrayGetElement(printer->system->resources, i); if (r->language && (!strcmp(r->language, lang) || !strcmp(r->language, baselang))) { httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), webscheme, NULL, client->host_field, client->host_port, r->path); ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-strings-uri", NULL, uri); break; } } // _papplRWUnlock(printer->system); } if (printer->num_supply > 0) { pappl_supply_t *supply = printer->supply; // Supply values... if (!ra || cupsArrayFind(ra, "printer-supply")) { char value[256]; // "printer-supply" value ipp_attribute_t *attr = NULL; // "printer-supply" attribute for (i = 0; i < (cups_len_t)printer->num_supply; i ++) { snprintf(value, sizeof(value), "index=%u;type=%s;maxcapacity=100;level=%d;colorantname=%s;", (unsigned)i, _papplSupplyTypeString(supply[i].type), supply[i].level, _papplSupplyColorString(supply[i].color)); if (attr) ippSetOctetString(client->response, &attr, ippGetCount(attr), value, IPP_NUM_CAST strlen(value)); else attr = ippAddOctetString(client->response, IPP_TAG_PRINTER, "printer-supply", value, IPP_NUM_CAST strlen(value)); } } if (!ra || cupsArrayFind(ra, "printer-supply-description")) { for (i = 0; i < (cups_len_t)printer->num_supply; i ++) svalues[i] = supply[i].description; ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-supply-description", IPP_NUM_CAST printer->num_supply, NULL, svalues); } } if (!ra || cupsArrayFind(ra, "printer-supply-info-uri")) { char uri[1024]; // URI value httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), webscheme, NULL, client->host_field, client->host_port, "%s/supplies", printer->uriname); ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-supply-info-uri", NULL, uri); } if (!ra || cupsArrayFind(ra, "printer-up-time")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-up-time", (int)(time(NULL) - printer->start_time)); if (!ra || cupsArrayFind(ra, "printer-uri-supported")) { char uris[2][1024]; // Buffers for URIs const char *values[2]; // Values for attribute num_values = 0; if (httpAddrIsLocalhost(httpGetAddress(client->http)) || !papplSystemGetTLSOnly(client->system)) { httpAssembleURI(HTTP_URI_CODING_ALL, uris[num_values], sizeof(uris[0]), "ipp", NULL, client->host_field, client->host_port, printer->resource); values[num_values] = uris[num_values]; num_values ++; } if (!httpAddrIsLocalhost(httpGetAddress(client->http)) && !(client->system->options & PAPPL_SOPTIONS_NO_TLS)) { httpAssembleURI(HTTP_URI_CODING_ALL, uris[num_values], sizeof(uris[0]), "ipps", NULL, client->host_field, client->host_port, printer->resource); values[num_values] = uris[num_values]; num_values ++; } if (num_values > 0) ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", IPP_NUM_CAST num_values, NULL, values); } if (client->system->wifi_status_cb && httpAddrIsLocalhost(httpGetAddress(client->http)) && (!ra || cupsArrayFind(ra, "printer-wifi-ssid") || cupsArrayFind(ra, "printer-wifi-state"))) { // Get Wi-Fi status... pappl_wifi_t wifi; // Wi-Fi status if ((client->system->wifi_status_cb)(client->system, client->system->wifi_cbdata, &wifi)) { if (!ra || cupsArrayFind(ra, "printer-wifi-ssid")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-wifi-ssid", NULL, wifi.ssid); if (!ra || cupsArrayFind(ra, "printer-wifi-state")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-wifi-state", (int)wifi.state); } } if (!ra || cupsArrayFind(ra, "printer-xri-supported")) _papplPrinterCopyXRINoLock(printer, client->response, client); if (!ra || cupsArrayFind(ra, "queued-job-count")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "queued-job-count", (int)cupsArrayGetCount(printer->active_jobs)); if (!ra || cupsArrayFind(ra, "sides-default")) { if (data->sides_default) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-default", NULL, _papplSidesString(data->sides_default)); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "sides-default", NULL, "one-sided"); } if (!ra || cupsArrayFind(ra, "uri-authentication-supported")) { // For each supported printer-uri value, report whether authentication is // supported. Since we only support authentication over a secure (TLS) // channel, the value is always 'none' for the "ipp" URI and either 'none' // or 'basic' for the "ipps" URI... if (httpAddrIsLocalhost(httpGetAddress(client->http)) || (client->system->options & PAPPL_SOPTIONS_NO_TLS)) { ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", NULL, "none"); } else if (papplSystemGetTLSOnly(client->system)) { if (papplSystemGetAuthService(client->system)) ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", NULL, "basic"); else ippAddString(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", NULL, "none"); } else if (papplSystemGetAuthService(client->system)) { static const char * const uri_authentication_basic[] = { // uri-authentication-supported values "none", "basic" }; ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", 2, NULL, uri_authentication_basic); } else { static const char * const uri_authentication_none[] = { // uri-authentication-supported values "none", "none" }; ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", 2, NULL, uri_authentication_none); } } } // // '_papplPrinterCopyStateNoLock()' - Copy the printer-state-xxx attributes. // void _papplPrinterCopyStateNoLock( pappl_printer_t *printer, // I - Printer ipp_tag_t group_tag, // I - Group tag ipp_t *ipp, // I - IPP message pappl_client_t *client, // I - Client connection cups_array_t *ra) // I - Requested attributes { if (!ra || cupsArrayFind(ra, "printer-is-accepting-jobs")) ippAddBoolean(ipp, group_tag, "printer-is-accepting-jobs", printer->is_accepting); if (!ra || cupsArrayFind(ra, "printer-state")) ippAddInteger(ipp, group_tag, IPP_TAG_ENUM, "printer-state", (int)printer->state); if (!ra || cupsArrayFind(ra, "printer-state-message")) { static const char * const messages[] = { "Idle.", "Printing.", "Stopped." }; ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_TEXT), "printer-state-message", NULL, messages[printer->state - IPP_PSTATE_IDLE]); } if (!ra || cupsArrayFind(ra, "printer-state-reasons")) { ipp_attribute_t *attr = NULL; // printer-state-reasons bool wifi_not_configured = false; // Need the 'wifi-not-configured' reason? if (client && client->system->wifi_status_cb && httpAddrIsLocalhost(httpGetAddress(client->http))) { pappl_wifi_t wifi; // Wi-Fi status if ((client->system->wifi_status_cb)(client->system, client->system->wifi_cbdata, &wifi)) { if (wifi.state == PAPPL_WIFI_STATE_NOT_CONFIGURED) wifi_not_configured = true; } } if (printer->state_reasons == PAPPL_PREASON_NONE) { if (printer->is_stopped) attr = ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "moving-to-paused"); else if (printer->state == IPP_PSTATE_STOPPED) attr = ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "paused"); if (printer->hold_new_jobs) { if (attr) ippSetString(ipp, &attr, ippGetCount(attr), "hold-new-jobs"); else attr = ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "hold-new-jobs"); } if (wifi_not_configured) { if (attr) ippSetString(ipp, &attr, ippGetCount(attr), "wifi-not-configured-report"); else attr = ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "wifi-not-configured-report"); } else if (!attr) ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "none"); } else { pappl_preason_t bit; // Reason bit for (bit = PAPPL_PREASON_OTHER; bit <= PAPPL_PREASON_TONER_LOW; bit *= 2) { if (printer->state_reasons & bit) { if (attr) ippSetString(ipp, &attr, ippGetCount(attr), _papplPrinterReasonString(bit)); else attr = ippAddString(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, _papplPrinterReasonString(bit)); } } if (printer->is_stopped) ippSetString(ipp, &attr, ippGetCount(attr), "moving-to-paused"); else if (printer->state == IPP_PSTATE_STOPPED) ippSetString(ipp, &attr, ippGetCount(attr), "paused"); if (printer->hold_new_jobs) ippSetString(ipp, &attr, ippGetCount(attr), "hold-new-jobs"); if (wifi_not_configured) ippSetString(ipp, &attr, ippGetCount(attr), "wifi-not-configured-report"); } } } // // '_papplPrinterCopyXRINoLock()' - Copy the "printer-xri-supported" attribute. // void _papplPrinterCopyXRINoLock( pappl_printer_t *printer, // I - Printer ipp_t *ipp, // I - IPP message pappl_client_t *client) // I - Client { char uri[1024]; // URI value int i, // Looping var num_values = 0; // Number of values ipp_t *col, // Current collection value *values[2]; // Values for attribute if (httpAddrIsLocalhost(httpGetAddress(client->http)) || !papplSystemGetTLSOnly(client->system)) { // Add ipp: URI... httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, client->host_field, client->host_port, printer->resource); col = ippNew(); ippAddString(col, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-authentication", NULL, "none"); ippAddString(col, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-security", NULL, "none"); ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_URI, "xri-uri", NULL, uri); values[num_values ++] = col; } if (!httpAddrIsLocalhost(httpGetAddress(client->http)) && !(client->system->options & PAPPL_SOPTIONS_NO_TLS)) { // Add ipps: URI... httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, client->host_field, client->host_port, printer->resource); col = ippNew(); ippAddString(col, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-authentication", NULL, papplSystemGetAuthService(client->system) ? "basic" : "none"); ippAddString(col, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-security", NULL, "tls"); ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_URI, "xri-uri", NULL, uri); values[num_values ++] = col; } if (num_values > 0) ippAddCollections(ipp, IPP_TAG_PRINTER, "printer-xri-supported", IPP_NUM_CAST num_values, (const ipp_t **)values); for (i = 0; i < num_values; i ++) ippDelete(values[i]); } // // '_papplPrinterIsAuthorized()' - Authorize access to a printer. // bool // O - `true` on success, `false` on failure _papplPrinterIsAuthorized( pappl_client_t *client) // I - Client { http_status_t code = _papplClientIsAuthorizedForGroup(client, true, client->printer->print_group, client->printer->print_gid); if (code == HTTP_STATUS_CONTINUE && client->job && client->job->username && strcmp(client->username, client->job->username)) { // Not the owner, try authorizing with admin group... code = _papplClientIsAuthorizedForGroup(client, true, client->system->admin_group, client->system->admin_gid); } if (code == HTTP_STATUS_CONTINUE) return (true); papplClientRespond(client, code, NULL, NULL, 0, 0); return (false); } // // '_papplPrinterProcessIPP()' - Process an IPP Printer request. // void _papplPrinterProcessIPP( pappl_client_t *client) // I - Client { if (!client->printer) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No printer found."); return; } switch (ippGetOperation(client->request)) { case IPP_OP_PRINT_JOB : ipp_print_job(client); break; case IPP_OP_VALIDATE_JOB : ipp_validate_job(client); break; case IPP_OP_CREATE_JOB : ipp_create_job(client); break; case IPP_OP_CANCEL_CURRENT_JOB : ipp_cancel_current_job(client); break; case IPP_OP_CANCEL_JOBS : case IPP_OP_CANCEL_MY_JOBS : ipp_cancel_jobs(client); break; case IPP_OP_GET_JOBS : ipp_get_jobs(client); break; case IPP_OP_GET_PRINTER_ATTRIBUTES : case IPP_OP_GET_PRINTER_SUPPORTED_VALUES : case IPP_OP_CUPS_GET_DEFAULT : ipp_get_printer_attributes(client); break; case IPP_OP_SET_PRINTER_ATTRIBUTES : ipp_set_printer_attributes(client); break; case IPP_OP_IDENTIFY_PRINTER : ipp_identify_printer(client); break; case IPP_OP_PAUSE_PRINTER : case IPP_OP_PAUSE_PRINTER_AFTER_CURRENT_JOB : ipp_pause_printer(client); break; case IPP_OP_RESUME_PRINTER : ipp_resume_printer(client); break; case IPP_OP_ENABLE_PRINTER : ipp_enable_printer(client); break; case IPP_OP_DISABLE_PRINTER : ipp_disable_printer(client); break; case IPP_OP_HOLD_NEW_JOBS : ipp_hold_new_jobs(client); break; case IPP_OP_RELEASE_HELD_NEW_JOBS : ipp_release_held_new_jobs(client); break; case IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS : case IPP_OP_CREATE_JOB_SUBSCRIPTIONS : _papplSubscriptionIPPCreate(client); break; case IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES : _papplSubscriptionIPPGetAttributes(client); break; case IPP_OP_GET_SUBSCRIPTIONS : _papplSubscriptionIPPList(client); break; case IPP_OP_RENEW_SUBSCRIPTION : _papplSubscriptionIPPRenew(client); break; case IPP_OP_CANCEL_SUBSCRIPTION : _papplSubscriptionIPPCancel(client); break; case IPP_OP_GET_NOTIFICATIONS : _papplSubscriptionIPPGetNotifications(client); break; default : if (client->system->op_cb && (client->system->op_cb)(client, client->system->op_cbdata)) break; papplClientRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } } // // '_papplPrinterSetAttributes()' - Set printer attributes. // bool // O - `true` if OK, `false` otherwise _papplPrinterSetAttributes( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { int create_printer; // Create-Printer request? ipp_attribute_t *rattr; // Current request attribute ipp_tag_t value_tag; // Value tag cups_len_t count; // Number of values const char *name; // Attribute name char defname[128], // xxx-default name value[1024]; // xxx-default value cups_len_t i, j; // Looping vars pwg_media_t *pwg; // PWG media size data pappl_pr_driver_data_t driver_data; // Printer driver data bool do_defaults = false, // Update defaults? do_ready = false; // Update ready media? cups_len_t num_vendor = 0; // Number of vendor defaults cups_option_t *vendor = NULL; // Vendor defaults pappl_contact_t contact; // printer-contact value bool do_contact = false; // Update contact? const char *geo_location = NULL, // printer-geo-location value *location = NULL, // printer-location value *organization = NULL, // printer-organization value *org_unit = NULL; // printer-organizational-unit value char wifi_ssid[256] = "", // printer-wifi-ssid value wifi_password[256] = ""; // printer-wifi-password value bool do_wifi = false;// Join a Wi-Fi network? static _pappl_attr_t pattrs[] = // Settable printer attributes { { "label-mode-configured", IPP_TAG_KEYWORD, 1 }, { "label-tear-off-configured", IPP_TAG_INTEGER, 1 }, { "media-col-default", IPP_TAG_BEGIN_COLLECTION, 1 }, { "media-col-ready", IPP_TAG_BEGIN_COLLECTION, PAPPL_MAX_SOURCE }, { "media-default", IPP_TAG_KEYWORD, 1 }, { "media-ready", IPP_TAG_KEYWORD, PAPPL_MAX_SOURCE }, { "orientation-requested-default", IPP_TAG_ENUM, 1 }, { "output-bin-default", IPP_TAG_KEYWORD, 1 }, { "print-color-mode-default", IPP_TAG_KEYWORD, 1 }, { "print-content-optimize-default", IPP_TAG_KEYWORD, 1 }, { "print-darkness-default", IPP_TAG_INTEGER, 1 }, { "print-quality-default", IPP_TAG_ENUM, 1 }, { "print-speed-default", IPP_TAG_INTEGER, 1 }, { "printer-contact-col", IPP_TAG_BEGIN_COLLECTION, 1 }, { "printer-darkness-configured", IPP_TAG_INTEGER, 1 }, { "printer-geo-location", IPP_TAG_URI, 1 }, { "printer-location", IPP_TAG_TEXT, 1 }, { "printer-organization", IPP_TAG_TEXT, 1 }, { "printer-organizational-unit", IPP_TAG_TEXT, 1 }, { "printer-resolution-default", IPP_TAG_RESOLUTION, 1 }, { "printer-wifi-password", IPP_TAG_STRING, 1 }, { "printer-wifi-ssid", IPP_TAG_NAME, 1 }, { "sides-default", IPP_TAG_KEYWORD, 1 } }; // Preflight request attributes... create_printer = ippGetOperation(client->request) == IPP_OP_CREATE_PRINTER; papplPrinterGetDriverData(printer, &driver_data); for (rattr = ippGetFirstAttribute(client->request); rattr; rattr = ippGetNextAttribute(client->request)) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s %s %s%s ...", ippTagString(ippGetGroupTag(rattr)), ippGetName(rattr), ippGetCount(rattr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(rattr))); if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION || (name = ippGetName(rattr)) == NULL) { continue; } else if (ippGetGroupTag(rattr) != IPP_TAG_PRINTER) { papplClientRespondIPPUnsupported(client, rattr); continue; } if (create_printer && (!strcmp(name, "printer-device-id") || !strcmp(name, "printer-name") || !strcmp(name, "smi55357-device-uri") || !strcmp(name, "smi55357-driver"))) continue; if ((create_printer || !httpAddrIsLocalhost(httpGetAddress(client->http)) || !client->system->wifi_join_cb) && (!strcmp(name, "printer-wifi-password") || !strcmp(name, "printer-wifi-ssid"))) { // Wi-Fi configuration can only be done over localhost... papplClientRespondIPPUnsupported(client, rattr); continue; } // Validate syntax of provided attributes... value_tag = ippGetValueTag(rattr); count = ippGetCount(rattr); for (i = 0; i < (cups_len_t)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (!strcmp(name, pattrs[i].name) && value_tag == pattrs[i].value_tag && count <= pattrs[i].max_count) break; } if (i >= (int)(sizeof(pattrs) / sizeof(pattrs[0]))) { for (j = 0; j < (cups_len_t)printer->driver_data.num_vendor; j ++) { snprintf(defname, sizeof(defname), "%s-default", printer->driver_data.vendor[j]); if (!strcmp(name, defname)) { ippAttributeString(rattr, value, sizeof(value)); num_vendor = cupsAddOption(printer->driver_data.vendor[j], value, num_vendor, &vendor); do_defaults = true; break; } } if (j >= (cups_len_t)printer->driver_data.num_vendor) papplClientRespondIPPUnsupported(client, rattr); } // Then copy the xxx-default values to the if (!strcmp(name, "identify-actions-default")) { driver_data.identify_default = PAPPL_IDENTIFY_ACTIONS_NONE; for (i = 0, count = ippGetCount(rattr); i < count; i ++) driver_data.identify_default |= _papplIdentifyActionsValue(ippGetString(rattr, i, NULL)); do_defaults = true; } else if (!strcmp(name, "label-mode-configured")) { driver_data.mode_configured = _papplLabelModeValue(ippGetString(rattr, 0, NULL)); do_defaults = true; } else if (!strcmp(name, "label-tear-offset-configured")) { driver_data.tear_offset_configured = ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "media-col-default")) { _papplMediaColImport(ippGetCollection(rattr, 0), &driver_data.media_default); do_defaults = true; } else if (!strcmp(name, "media-col-ready")) { count = ippGetCount(rattr); for (i = 0; i < count; i ++) _papplMediaColImport(ippGetCollection(rattr, i), driver_data.media_ready + i); for (; i < PAPPL_MAX_SOURCE; i ++) memset(driver_data.media_ready + i, 0, sizeof(pappl_media_col_t)); do_ready = true; } else if (!strcmp(name, "media-default")) { if ((pwg = pwgMediaForPWG(ippGetString(rattr, 0, NULL))) != NULL) { papplCopyString(driver_data.media_default.size_name, pwg->pwg, sizeof(driver_data.media_default.size_name)); driver_data.media_default.size_width = pwg->width; driver_data.media_default.size_length = pwg->length; } do_defaults = true; } else if (!strcmp(name, "media-ready")) { count = ippGetCount(rattr); for (i = 0; i < count; i ++) { if ((pwg = pwgMediaForPWG(ippGetString(rattr, i, NULL))) != NULL) { papplCopyString(driver_data.media_ready[i].size_name, pwg->pwg, sizeof(driver_data.media_ready[i].size_name)); driver_data.media_ready[i].size_width = pwg->width; driver_data.media_ready[i].size_length = pwg->length; } } for (; i < PAPPL_MAX_SOURCE; i ++) { driver_data.media_ready[i].size_name[0] = '\0'; driver_data.media_ready[i].size_width = 0; driver_data.media_ready[i].size_length = 0; } do_ready = true; } else if (!strcmp(name, "orientation-requested-default")) { driver_data.orient_default = (ipp_orient_t)ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "output-bin-default")) { const char *keyword = ippGetString(rattr, 0, NULL); // Keyword value for (i = 0; i < driver_data.num_bin; i ++) { if (!strcmp(keyword, driver_data.bin[i])) { driver_data.bin_default = i; break; } } if (i >= driver_data.num_bin) papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Unsupported \"output-bin-default\" value '%s'.", keyword); else do_defaults = true; } else if (!strcmp(name, "print-color-mode-default")) { driver_data.color_default = _papplColorModeValue(ippGetString(rattr, 0, NULL)); do_defaults = true; } else if (!strcmp(name, "print-content-optimize-default")) { driver_data.content_default = _papplContentValue(ippGetString(rattr, 0, NULL)); do_defaults = true; } else if (!strcmp(name, "print-darkness-default")) { driver_data.darkness_default = ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "print-quality-default")) { driver_data.quality_default = (ipp_quality_t)ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "print-scaling-default")) { driver_data.scaling_default = _papplScalingValue(ippGetString(rattr, 0, NULL)); do_defaults = true; } else if (!strcmp(name, "print-speed-default")) { driver_data.speed_default = ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "printer-contact-col")) { _papplContactImport(ippGetCollection(rattr, 0), &contact); do_contact = true; } else if (!strcmp(name, "printer-darkness-configured")) { driver_data.darkness_configured = ippGetInteger(rattr, 0); do_defaults = true; } else if (!strcmp(name, "printer-geo-location")) { float geo_lat, geo_lon; // Latitude and longitude geo_location = ippGetString(rattr, 0, NULL); if (sscanf(geo_location, "geo:%f,%f", &geo_lat, &geo_lon) != 2 || geo_lat < -90.0 || geo_lat > 90.0 || geo_lon < -180.0 || geo_lon > 180.0) papplClientRespondIPPUnsupported(client, rattr); } else if (!strcmp(name, "printer-location")) { location = ippGetString(rattr, 0, NULL); } else if (!strcmp(name, "printer-organization")) { organization = ippGetString(rattr, 0, NULL); } else if (!strcmp(name, "printer-organization-unit")) { org_unit = ippGetString(rattr, 0, NULL); } else if (!strcmp(name, "printer-resolution-default")) { ipp_res_t units; // Resolution units driver_data.x_default = ippGetResolution(rattr, 0, &driver_data.y_default, &units); do_defaults = true; } else if (!strcmp(name, "printer-wifi-password")) { void *data; // Password cups_len_t datalen; // Length of password data = ippGetOctetString(rattr, 0, &datalen); if (datalen > ((int)sizeof(wifi_password) - 1)) { papplClientRespondIPPUnsupported(client, rattr); continue; } memcpy(wifi_password, data, datalen); wifi_password[datalen] = '\0'; do_wifi = true; } else if (!strcmp(name, "printer-wifi-ssid")) { papplCopyString(wifi_ssid, ippGetString(rattr, 0, NULL), sizeof(wifi_ssid)); do_wifi = true; } else if (!strcmp(name, "sides-default")) { pappl_sides_t sides_default = _papplSidesValue(ippGetString(rattr, 0, NULL)); // Sides value if (!sides_default || !(driver_data.sides_supported & sides_default)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Unsupported \"sides-default\" value '%s'.", ippGetString(rattr, 0, NULL)); } else { driver_data.sides_default = sides_default; do_defaults = true; } } } if (ippGetStatusCode(client->response) != IPP_STATUS_OK) { cupsFreeOptions(num_vendor, vendor); return (false); } // Now apply changes... if (do_defaults && !papplPrinterSetDriverDefaults(printer, &driver_data, (int)num_vendor, vendor)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "One or more attribute values were not supported."); cupsFreeOptions(num_vendor, vendor); return (false); } cupsFreeOptions(num_vendor, vendor); if (do_ready && !papplPrinterSetReadyMedia(printer, driver_data.num_source, driver_data.media_ready)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "One or more attribute values were not supported."); return (false); } if (do_wifi) { if (!(printer->system->wifi_join_cb)(printer->system, printer->system->wifi_cbdata, wifi_ssid, wifi_password)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Unable to join Wi-Fi network '%s'.", wifi_ssid); return (false); } } if (do_contact) papplPrinterSetContact(printer, &contact); if (geo_location) papplPrinterSetGeoLocation(printer, geo_location); if (location) papplPrinterSetGeoLocation(printer, location); if (organization) papplPrinterSetGeoLocation(printer, organization); if (org_unit) papplPrinterSetGeoLocation(printer, org_unit); papplSystemAddEvent(printer->system, printer, NULL, PAPPL_EVENT_PRINTER_CONFIG_CHANGED, NULL); return (true); } // // 'create_job()' - Create a new job object from a Print-Job or Create-Job // request. // static pappl_job_t * // O - Job create_job( pappl_client_t *client) // I - Client { ipp_attribute_t *attr; // Job attribute const char *job_name, // Job name *username; // Owner // Get the requesting-user-name, document format, and name... if (client->username[0]) username = client->username; else if ((attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) != NULL) username = ippGetString(attr, 0, NULL); else username = "guest"; if ((attr = ippFindAttribute(client->request, "job-name", IPP_TAG_NAME)) != NULL) job_name = ippGetString(attr, 0, NULL); else job_name = "Untitled"; return (_papplJobCreate(client->printer, 0, username, NULL, job_name, client->request)); } // // 'ipp_cancel_current_job()' - Cancel the current job. // static void ipp_cancel_current_job( pappl_client_t *client) // I - Client { pappl_job_t *job; // Job information // Get the job... if ((job = client->printer->processing_job) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No currently printing job."); return; } // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // See if the job is already completed, canceled, or aborted; if so, // we can't cancel... switch (job->state) { case IPP_JSTATE_CANCELED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already canceled - can\'t cancel.", job->job_id); break; case IPP_JSTATE_ABORTED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already aborted - can\'t cancel.", job->job_id); break; case IPP_JSTATE_COMPLETED : papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already completed - can\'t cancel.", job->job_id); break; default : // Cancel the job... papplJobCancel(job); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); break; } } // // 'ipp_cancel_jobs()' - Cancel all jobs. // static void ipp_cancel_jobs(pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Cancel all jobs... papplPrinterCancelAllJobs(client->printer); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_create_job()' - Create a job object. // static void ipp_create_job(pappl_client_t *client) // I - Client { pappl_job_t *job; // New job cups_array_t *ra; // Attributes to send in response // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Do we have a file to print? if (_papplClientHaveDocumentData(client)) { _papplClientFlushDocumentData(client); papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unexpected document data following request."); return; } // Are we accepting jobs? if (!client->printer->is_accepting) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, "Not accepting new jobs."); return; } // Validate print job attributes... if (!valid_job_attributes(client)) return; // Create the job... if ((job = create_job(client)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BUSY, "Currently printing another job."); return; } // Return the job info... papplClientRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-message"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); _papplJobCopyAttributesNoLock(job, client, ra); cupsArrayDelete(ra); } // // 'ipp_disable_printer()' - Stop accepting new jobs for a printer. // static void ipp_disable_printer( pappl_client_t *client) // I - Client { // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Disable the printer... papplPrinterDisable(client->printer); } // // 'ipp_enable_printer()' - Start/resume accepting new jobs for a printer. // static void ipp_enable_printer( pappl_client_t *client) // I - Client { // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Enable the printer... papplPrinterEnable(client->printer); } // // 'ipp_get_jobs()' - Get a list of job objects. // static void ipp_get_jobs(pappl_client_t *client) // I - Client { ipp_attribute_t *attr; // Current attribute const char *which_jobs = NULL; // which-jobs values int job_comparison; // Job comparison ipp_jstate_t job_state; // job-state value cups_len_t i, // Looping var limit, // Maximum number of jobs to return count; // Number of jobs that match const char *username; // Username cups_array_t *list; // Jobs list pappl_job_t *job; // Current job pointer cups_array_t *ra; // Requested attributes array // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // See if the "which-jobs" attribute have been specified... if ((attr = ippFindAttribute(client->request, "which-jobs", IPP_TAG_KEYWORD)) != NULL) { which_jobs = ippGetString(attr, 0, NULL); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Get-Jobs \"which-jobs\"='%s'", which_jobs); } if (!which_jobs || !strcmp(which_jobs, "not-completed")) { job_comparison = -1; job_state = IPP_JSTATE_STOPPED; list = client->printer->active_jobs; } else if (!strcmp(which_jobs, "completed")) { job_comparison = 1; job_state = IPP_JSTATE_CANCELED; list = client->printer->completed_jobs; } else if (!strcmp(which_jobs, "all")) { job_comparison = 1; job_state = IPP_JSTATE_PENDING; list = client->printer->all_jobs; } else { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "The \"which-jobs\" value '%s' is not supported.", which_jobs); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, "which-jobs", NULL, which_jobs); return; } // See if they want to limit the number of jobs reported... if ((attr = ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER)) != NULL) { int temp = ippGetInteger(attr, 0); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Get-Jobs \"limit\"='%d'", temp); if (temp < 0) limit = 0; else limit = (cups_len_t)temp; } else limit = 0; // See if we only want to see jobs for a specific user... username = NULL; if ((attr = ippFindAttribute(client->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL) { int my_jobs = ippGetBoolean(attr, 0); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Get-Jobs \"my-jobs\"='%s'", my_jobs ? "true" : "false"); if (my_jobs) { if ((attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Need \"requesting-user-name\" with \"my-jobs\"."); return; } username = ippGetString(attr, 0, NULL); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Get-Jobs \"requesting-user-name\"='%s'", username); } } // OK, build a list of jobs for this printer... ra = ippCreateRequestedArray(client->request); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(client->printer); count = cupsArrayGetCount(list); if (limit == 0 || limit > count) limit = count; for (count = 0, i = 0; i < limit; i ++) { job = (pappl_job_t *)cupsArrayGetElement(list, i); // Filter out jobs that don't match... if ((job_comparison < 0 && job->state > job_state) || /* (job_comparison == 0 && job->state != job_state) || */ (job_comparison > 0 && job->state < job_state) || (username && job->username && strcasecmp(username, job->username))) continue; if (count > 0) ippAddSeparator(client->response); count ++; _papplJobCopyAttributesNoLock(job, client, ra); } cupsArrayDelete(ra); _papplRWUnlock(client->printer); } // // 'ipp_get_printer_attributes()' - Get the attributes for a printer object. // static void ipp_get_printer_attributes( pappl_client_t *client) // I - Client { cups_array_t *ra; // Requested attributes array pappl_printer_t *printer = client->printer; // Printer _papplRWLockRead(printer->system); _papplRWLockRead(printer); if (!printer->device_in_use && !printer->processing_job && (time(NULL) - printer->status_time) > 1 && printer->driver_data.status_cb) { // Update printer status... _papplRWUnlock(printer); _papplRWUnlock(printer->system); (printer->driver_data.status_cb)(printer); _papplRWLockRead(printer->system); _papplRWLockWrite(printer); printer->status_time = time(NULL); } // Send the attributes... ra = ippCreateRequestedArray(client->request); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplPrinterCopyAttributesNoLock(printer, client, ra, ippGetString(ippFindAttribute(client->request, "document-format", IPP_TAG_MIMETYPE), 0, NULL)); _papplRWUnlock(printer); _papplRWUnlock(printer->system); cupsArrayDelete(ra); } // // 'ipp_hold_new_jobs()' - Hold new jobs. // static void ipp_hold_new_jobs( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Hold new jobs... if (papplPrinterHoldNewJobs(client->printer)) papplClientRespondIPP(client, IPP_STATUS_OK, "New jobs being held."); else papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Jobs already being held."); } // // 'ipp_identify_printer()' - Beep or display a message. // static void ipp_identify_printer( pappl_client_t *client) // I - Client { cups_len_t i; // Looping var ipp_attribute_t *attr; // IPP attribute pappl_identify_actions_t actions; // "identify-actions" value const char *message; // "message" value if (client->printer->driver_data.identify_cb) { if ((attr = ippFindAttribute(client->request, "identify-actions", IPP_TAG_KEYWORD)) != NULL) { actions = PAPPL_IDENTIFY_ACTIONS_NONE; for (i = 0; i < ippGetCount(attr); i ++) actions |= _papplIdentifyActionsValue(ippGetString(attr, i, NULL)); } else actions = client->printer->driver_data.identify_default; if ((attr = ippFindAttribute(client->request, "message", IPP_TAG_TEXT)) != NULL) message = ippGetString(attr, 0, NULL); else message = NULL; (client->printer->driver_data.identify_cb)(client->printer, actions, message); } papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_pause_printer()' - Stop a printer. // static void ipp_pause_printer( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } papplPrinterPause(client->printer); papplClientRespondIPP(client, IPP_STATUS_OK, "Printer paused."); } // // 'ipp_print_job()' - Create a job object with an attached document. // static void ipp_print_job(pappl_client_t *client) // I - Client { pappl_job_t *job; // New job // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; // Do we have a file to print? if (!_papplClientHaveDocumentData(client)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "No file in request."); return; } // Are we accepting jobs? if (!papplPrinterIsAcceptingJobs(client->printer)) { _papplClientFlushDocumentData(client); papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, "Not accepting new jobs."); return; } // Validate print job attributes... if (!valid_job_attributes(client)) { _papplClientFlushDocumentData(client); return; } // Create the job... if ((job = create_job(client)) == NULL) { _papplClientFlushDocumentData(client); papplClientRespondIPP(client, IPP_STATUS_ERROR_BUSY, "Currently printing another job."); return; } // Then finish getting the document data and process things... _papplJobCopyDocumentData(client, job); } // // 'ipp_release_held_new_jobs()' - Release held (new) jobs. // static void ipp_release_held_new_jobs( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Hold new jobs... if (papplPrinterReleaseHeldNewJobs(client->printer, client->username)) papplClientRespondIPP(client, IPP_STATUS_OK, "Released all held jobs."); else papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Jobs not being held."); } // // 'ipp_resume_printer()' - Start a printer. // static void ipp_resume_printer( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } papplPrinterResume(client->printer); papplClientRespondIPP(client, IPP_STATUS_OK, "Printer resumed."); } // // 'ipp_set_printer_attributes()' - Set printer attributes. // static void ipp_set_printer_attributes( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } if (!_papplPrinterSetAttributes(client, client->printer)) return; papplClientRespondIPP(client, IPP_STATUS_OK, "Printer attributes set."); } // // 'ipp_validate_job()' - Validate job creation attributes. // static void ipp_validate_job( pappl_client_t *client) // I - Client { // Authorize access... if (!_papplPrinterIsAuthorized(client)) return; if (valid_job_attributes(client)) papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'valid_job_attributes()' - Determine whether the job attributes are valid. // // When one or more job attributes are invalid, this function adds a suitable // response and attributes to the unsupported group. // static bool // O - `true` if valid, `false` if not valid_job_attributes( pappl_client_t *client) // I - Client { cups_len_t i, // Looping var count; // Number of values bool valid = true, // Valid attributes? exact; // Need attribute fidelity? ipp_attribute_t *attr, // Current attribute *supported; // xxx-supported attribute // If a shutdown is pending, do not accept more jobs... if (client->system->shutdown_time) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, "Not accepting new jobs."); return (false); } // Check operation attributes... valid = _papplJobValidateDocumentAttributes(client); _papplRWLockRead(client->printer); // Check the various job template attributes... exact = ippGetOperation(client->request) == IPP_OP_VALIDATE_JOB; if ((attr = ippFindAttribute(client->request, "ipp-attribute-fidelity", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_BOOLEAN) { papplClientRespondIPPUnsupported(client, attr); valid = false; } if (ippGetBoolean(attr, 0)) exact = true; } if ((attr = ippFindAttribute(client->request, "copies", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 999) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "job-hold-until", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } if ((supported = ippFindAttribute(client->printer->attrs, "job-hold-until", IPP_TAG_KEYWORD)) != NULL && !ippContainsString(supported, ippGetString(attr, 0, NULL))) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "job-impressions", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 0) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "job-name", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } ippSetGroupTag(client->request, &attr, IPP_TAG_JOB); } else { ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled"); } if ((attr = ippFindAttribute(client->request, "job-priority", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 100) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "job-sheets", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD) || (exact && strcmp(ippGetString(attr, 0, NULL), "none"))) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (strcmp(ippGetString(attr, 0, NULL), "none")) { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } if ((attr = ippFindAttribute(client->request, "media", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { supported = ippFindAttribute(client->printer->driver_attrs, "media-supported", IPP_TAG_KEYWORD); if (!ippContainsString(supported, ippGetString(attr, 0, NULL))) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } } if ((attr = ippFindAttribute(client->request, "media-col", IPP_TAG_ZERO)) != NULL) { ipp_t *col, // media-col collection *size; // media-size collection ipp_attribute_t *member, // Member attribute *x_dim, // x-dimension *y_dim; // y-dimension int x_value, // y-dimension value y_value; // x-dimension value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_BEGIN_COLLECTION) { papplClientRespondIPPUnsupported(client, attr); valid = false; } col = ippGetCollection(attr, 0); if ((member = ippFindAttribute(col, "media-size-name", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(member) != 1 || (ippGetValueTag(member) != IPP_TAG_NAME && ippGetValueTag(member) != IPP_TAG_NAMELANG && ippGetValueTag(member) != IPP_TAG_KEYWORD)) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { supported = ippFindAttribute(client->printer->driver_attrs, "media-supported", IPP_TAG_KEYWORD); if (!ippContainsString(supported, ippGetString(member, 0, NULL))) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } } else if ((member = ippFindAttribute(col, "media-size", IPP_TAG_BEGIN_COLLECTION)) != NULL) { if (ippGetCount(member) != 1) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { size = ippGetCollection(member, 0); if ((x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(x_dim) != 1 || (y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(y_dim) != 1) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { x_value = ippGetInteger(x_dim, 0); y_value = ippGetInteger(y_dim, 0); supported = ippFindAttribute(client->printer->driver_attrs, "media-size-supported", IPP_TAG_BEGIN_COLLECTION); count = ippGetCount(supported); for (i = 0; i < count ; i ++) { size = ippGetCollection(supported, i); x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_ZERO); y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_ZERO); if (ippContainsInteger(x_dim, x_value) && ippContainsInteger(y_dim, y_value)) break; } if (i >= count) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } } } } if ((attr = ippFindAttribute(client->request, "multiple-document-handling", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (strcmp(ippGetString(attr, 0, NULL), "separate-documents-uncollated-copies") && strcmp(ippGetString(attr, 0, NULL), "separate-documents-collated-copies")) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "orientation-requested", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (ippGetInteger(attr, 0) < IPP_ORIENT_PORTRAIT || ippGetInteger(attr, 0) > IPP_ORIENT_NONE) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "page-ranges", IPP_TAG_ZERO)) != NULL) { int upper = 0, lower = ippGetRange(attr, 0, &upper); // "page-ranges" value if (!ippGetBoolean(ippFindAttribute(client->printer->driver_attrs, "page-ranges-supported", IPP_TAG_BOOLEAN), 0) || ippGetValueTag(attr) != IPP_TAG_RANGE || ippGetCount(attr) != 1 || lower < 1 || upper < lower) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "print-color-mode", IPP_TAG_ZERO)) != NULL) { pappl_color_mode_t value = _papplColorModeValue(ippGetString(attr, 0, NULL)); // "print-color-mode" value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (!(value & client->printer->driver_data.color_supported)) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "print-content-optimize", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (!_papplContentValue(ippGetString(attr, 0, NULL))) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "print-darkness", IPP_TAG_ZERO)) != NULL) { int value = ippGetInteger(attr, 0); // "print-darkness" value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || value < -100 || value > 100) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (client->printer->driver_data.darkness_supported == 0) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "print-quality", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM || ippGetInteger(attr, 0) < IPP_QUALITY_DRAFT || ippGetInteger(attr, 0) > IPP_QUALITY_HIGH) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "print-scaling", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || !_papplScalingValue(ippGetString(attr, 0, NULL))) { papplClientRespondIPPUnsupported(client, attr); valid = false; } } if ((attr = ippFindAttribute(client->request, "print-speed", IPP_TAG_ZERO)) != NULL) { int value = ippGetInteger(attr, 0); // "print-speed" value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (value < client->printer->driver_data.speed_supported[0] || value > client->printer->driver_data.speed_supported[1] || client->printer->driver_data.speed_supported[1] == 0) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } if ((attr = ippFindAttribute(client->request, "printer-resolution", IPP_TAG_ZERO)) != NULL) { int xdpi, // Horizontal resolution ydpi; // Vertical resolution ipp_res_t units; // Resolution units xdpi = ippGetResolution(attr, 0, &ydpi, &units); if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_RESOLUTION || units != IPP_RES_PER_INCH) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { for (i = 0; i < (cups_len_t)client->printer->driver_data.num_resolution; i ++) { if (xdpi == client->printer->driver_data.x_resolution[i] && ydpi == client->printer->driver_data.y_resolution[i]) break; } if (i >= (cups_len_t)client->printer->driver_data.num_resolution) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } } if ((attr = ippFindAttribute(client->request, "sides", IPP_TAG_ZERO)) != NULL) { pappl_sides_t value = _papplSidesValue(ippGetString(attr, 0, NULL)); // "sides" value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else if (!(value & client->printer->driver_data.sides_supported)) { if (exact) { papplClientRespondIPPUnsupported(client, attr); valid = false; } else { _papplClientRespondIPPIgnored(client, attr); ippDeleteAttribute(client->request, attr); } } } _papplRWUnlock(client->printer); return (valid); } pappl-1.4.9/pappl/printer-private.h000066400000000000000000000225241476704353100173000ustar00rootroot00000000000000// // Private printer header file for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_PRINTER_PRIVATE_H_ # define _PAPPL_PRINTER_PRIVATE_H_ # include "dnssd-private.h" # include "printer.h" # include "log.h" # ifdef __APPLE__ # include # include # elif !_WIN32 # include # endif // __APPLE__ # ifdef HAVE_SYS_RANDOM_H # include # endif // HAVE_SYS_RANDOM_H # ifdef HAVE_GNUTLS_RND # include # include # endif // HAVE_GNUTLS_RND # include "base-private.h" # include "device.h" // // Types and structures... // struct _pappl_printer_s // Printer data { pthread_rwlock_t rwlock; // Reader/writer lock pappl_system_t *system; // Containing system int printer_id; // "printer-id" value char *name, // "printer-name" value *dns_sd_name, // "printer-dns-sd-name" value *location, // "printer-location" value *geo_location, // "printer-geo-location" value (geo: URI) *organization, // "printer-organization" value *org_unit; // "printer-organizational-unit" value pappl_contact_t contact; // "printer-contact" value char *resource; // Resource path of printer size_t resourcelen; // Length of resource path char *uriname; // Name for URLs ipp_pstate_t state; // "printer-state" value pappl_preason_t state_reasons; // "printer-state-reasons" values time_t state_time; // "printer-state-change-time" value bool is_accepting, // Are we accepting jobs? is_stopped, // Are we stopping this printer? is_deleted; // Has this printer been deleted? char *device_id, // "printer-device-id" value *device_uri; // Device URI pappl_device_t *device; // Current connection to device (if any) bool device_in_use; // Is the device in use? char *driver_name; // Driver name pappl_pr_driver_data_t driver_data; // Driver data ipp_t *driver_attrs; // Driver attributes int num_ready; // Number of ready media ipp_t *attrs; // Other (static) printer attributes time_t start_time; // Startup time time_t config_time; // "printer-config-change-time" value time_t status_time; // Last time status was updated char *print_group; // PAM printing group, if any gid_t print_gid; // PAM printing group ID int num_supply; // Number of "printer-supply" values pappl_supply_t supply[PAPPL_MAX_SUPPLY]; // "printer-supply" values pappl_job_t *processing_job; // Currently printing job, if any bool hold_new_jobs; // Hold new jobs int max_active_jobs, // Maximum number of active jobs to accept max_completed_jobs, // Maximum number of completed jobs to retain in history max_preserved_jobs; // Maximum number of completed jobs to preserve in history cups_array_t *active_jobs, // Array of active jobs *all_jobs, // Array of all jobs *completed_jobs; // Array of completed jobs int next_job_id, // Next "job-id" value impcompleted; // "printer-impressions-completed" value cups_array_t *links; // Web navigation links # ifdef HAVE_MDNSRESPONDER _pappl_srv_t dns_sd_ipp_ref, // DNS-SD IPP service dns_sd_ipps_ref, // DNS-SD IPPS service dns_sd_http_ref, // DNS-SD HTTP service dns_sd_printer_ref, // DNS-SD LPD service dns_sd_pdl_ref; // DNS-SD AppSocket service DNSRecordRef dns_sd_ipp_loc_ref, // DNS-SD LOC record for IPP service dns_sd_ipps_loc_ref; // DNS-SD LOC record for IPPS service # elif defined(HAVE_AVAHI) _pappl_srv_t dns_sd_ref; // DNS-SD services # endif // HAVE_MDNSRESPONDER unsigned char dns_sd_loc[16]; // DNS-SD LOC record data bool dns_sd_collision; // Was there a name collision? int dns_sd_serial; // DNS-SD serial number (for collisions) bool raw_active; // Raw listener active? int num_raw_listeners; // Number of raw socket listeners struct pollfd raw_listeners[2]; // Raw socket listeners bool usb_active; // USB gadget active? unsigned short usb_vendor_id, // USB vendor ID usb_product_id; // USB product ID pappl_uoptions_t usb_options; // USB gadget options char *usb_storage; // USB storage gadget file, if any pappl_pr_usb_cb_t usb_cb; // USB processing callback, if any void *usb_cbdata; // USB processing callback data, if any }; // // Functions... // extern bool _papplPrinterAddRawListeners(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void *_papplPrinterRunRaw(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void *_papplPrinterRunUSB(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterCheckJobsNoLock(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterCleanJobsNoLock(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterCopyAttributesNoLock(pappl_printer_t *printer, pappl_client_t *client, cups_array_t *ra, const char *format) _PAPPL_PRIVATE; extern void _papplPrinterCopyStateNoLock(pappl_printer_t *printer, ipp_tag_t group_tag, ipp_t *ipp, pappl_client_t *client, cups_array_t *ra) _PAPPL_PRIVATE; extern void _papplPrinterCopyXRINoLock(pappl_printer_t *printer, ipp_t *ipp, pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplPrinterDelete(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterInitDriverData(pappl_pr_driver_data_t *d) _PAPPL_PRIVATE; extern bool _papplPrinterIsAuthorized(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplPrinterProcessIPP(pappl_client_t *client) _PAPPL_PRIVATE; extern bool _papplPrinterRegisterDNSSDNoLock(pappl_printer_t *printer) _PAPPL_PRIVATE; extern bool _papplPrinterSetAttributes(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterUnregisterDNSSDNoLock(pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebCancelAllJobs(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebConfig(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebConfigFinalize(pappl_printer_t *printer, cups_len_t num_form, cups_option_t *form) _PAPPL_PRIVATE; extern void _papplPrinterWebDefaults(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebDelete(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebHome(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebIteratorCallback(pappl_printer_t *printer, pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplPrinterWebJobs(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebMedia(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern void _papplPrinterWebSupplies(pappl_client_t *client, pappl_printer_t *printer) _PAPPL_PRIVATE; extern const char *_papplColorModeString(pappl_color_mode_t value) _PAPPL_PRIVATE; extern pappl_color_mode_t _papplColorModeValue(const char *value) _PAPPL_PRIVATE; extern const char *_papplContentString(pappl_content_t value) _PAPPL_PRIVATE; extern pappl_content_t _papplContentValue(const char *value) _PAPPL_PRIVATE; extern ipp_t *_papplCreateMediaSize(const char *size_name) _PAPPL_PRIVATE; extern ipp_finishings_t _papplFinishingsEnum(pappl_finishings_t v) _PAPPL_PRIVATE; extern const char *_papplFinishingsString(pappl_finishings_t v) _PAPPL_PRIVATE; extern pappl_finishings_t _papplFinishingsValue(const char *s) _PAPPL_PRIVATE; extern const char *_papplIdentifyActionsString(pappl_identify_actions_t v) _PAPPL_PRIVATE; extern pappl_identify_actions_t _papplIdentifyActionsValue(const char *s) _PAPPL_PRIVATE; extern const char *_papplKindString(pappl_kind_t v) _PAPPL_PRIVATE; extern const char *_papplLabelModeString(pappl_label_mode_t v) _PAPPL_PRIVATE; extern pappl_label_mode_t _papplLabelModeValue(const char *s) _PAPPL_PRIVATE; extern const char *_papplMarkerColorString(pappl_supply_color_t v) _PAPPL_PRIVATE; extern const char *_papplMarkerTypeString(pappl_supply_type_t v) _PAPPL_PRIVATE; extern ipp_t *_papplMediaColExport(pappl_pr_driver_data_t *driver_data, pappl_media_col_t *media, bool db) _PAPPL_PRIVATE; extern void _papplMediaColImport(ipp_t *col, pappl_media_col_t *media) _PAPPL_PRIVATE; extern const char *_papplMediaTrackingString(pappl_media_tracking_t v); extern pappl_media_tracking_t _papplMediaTrackingValue(const char *s); extern const char *_papplPrinterReasonString(pappl_preason_t value) _PAPPL_PRIVATE; extern pappl_preason_t _papplPrinterReasonValue(const char *value) _PAPPL_PRIVATE; extern const char *_papplRasterTypeString(pappl_raster_type_t value) _PAPPL_PRIVATE; extern const char *_papplScalingString(pappl_scaling_t value) _PAPPL_PRIVATE; extern pappl_scaling_t _papplScalingValue(const char *value) _PAPPL_PRIVATE; extern const char *_papplSidesString(pappl_sides_t value) _PAPPL_PRIVATE; extern pappl_sides_t _papplSidesValue(const char *value) _PAPPL_PRIVATE; extern const char *_papplSupplyColorString(pappl_supply_color_t value) _PAPPL_PRIVATE; extern pappl_supply_color_t _papplSupplyColorValue(const char *value) _PAPPL_PRIVATE; extern const char *_papplSupplyTypeString(pappl_supply_type_t value) _PAPPL_PRIVATE; extern pappl_supply_type_t _papplSupplyTypeValue(const char *value) _PAPPL_PRIVATE; #endif // !_PAPPL_PRINTER_PRIVATE_H_ pappl-1.4.9/pappl/printer-raw.c000066400000000000000000000160411476704353100164070ustar00rootroot00000000000000// // Raw printing support for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // '_papplPrinterAddRawListeners()' - Create listener sockets for raw print queues. // bool // O - `true` on success, `false` otherwise _papplPrinterAddRawListeners( pappl_printer_t *printer) // I - Printer { int sock, // Listener socket port; // Listener port http_addrlist_t *addrlist; // Listen addresses char service[255]; // Service port // Listen on port 9100, 9101, etc. port = 9099 + printer->printer_id; snprintf(service, sizeof(service), "%d", port); if ((addrlist = httpAddrGetList(NULL, AF_INET, service)) != NULL) { if ((sock = httpAddrListen(&(addrlist->addr), port)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create socket print listener for '*:%d': %s", port, cupsGetErrorString()); } else { printer->raw_listeners[printer->num_raw_listeners].fd = sock; printer->raw_listeners[printer->num_raw_listeners].events = POLLIN | POLLERR; printer->num_raw_listeners ++; } httpAddrFreeList(addrlist); } if ((addrlist = httpAddrGetList(NULL, AF_INET6, service)) != NULL) { if ((sock = httpAddrListen(&(addrlist->addr), port)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create socket print listener for '*:%d': %s", port, cupsGetErrorString()); } else { printer->raw_listeners[printer->num_raw_listeners].fd = sock; printer->raw_listeners[printer->num_raw_listeners].events = POLLIN | POLLERR; printer->num_raw_listeners ++; } httpAddrFreeList(addrlist); } if (printer->num_raw_listeners > 0) papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Listening for socket print jobs on '*:%d'.", port); return (printer->num_raw_listeners > 0); } // // '_papplPrinterRunRaw()' - Accept raw print requests over sockets. // void * // O - Thread exit value _papplPrinterRunRaw( pappl_printer_t *printer) // I - Printer { int i; // Looping var int count; // Return value from poll() papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Socket listener thread starting with %d listeners.", printer->num_raw_listeners); _papplRWLockWrite(printer); printer->raw_active = true; _papplRWUnlock(printer); while (!papplPrinterIsDeleted(printer) && !_papplSystemIsShutdownNoLock(printer->system)) { // Don't accept connections if we can't accept a new job... _papplRWLockRead(printer); if (printer->max_active_jobs > 0) { while ((int)cupsArrayGetCount(printer->active_jobs) >= printer->max_active_jobs && !printer->is_deleted && !_papplSystemIsShutdownNoLock(printer->system)) { _papplRWUnlock(printer); usleep(1000); _papplRWLockRead(printer); } } _papplRWUnlock(printer); if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) break; // Wait 1 second for new connections... if ((count = poll(printer->raw_listeners, (nfds_t)printer->num_raw_listeners, 250)) > 0) { if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) break; // Got a new connection request, accept from the corresponding listener... for (i = 0; i < printer->num_raw_listeners; i ++) { if (printer->raw_listeners[i].revents & POLLIN) { time_t activity; // Network activity watchdog int sock; // Client socket http_addr_t sockaddr; // Client address socklen_t sockaddrlen; // Length of client address struct pollfd sockp; // poll() data for client socket pappl_job_t *job; // New print job ssize_t bytes; // Bytes read from socket char buffer[8192]; // Copy buffer char filename[1024]; // Job filename // Accept the connection... sockaddrlen = sizeof(sockaddr); if ((sock = (int)accept(printer->raw_listeners[i].fd, (struct sockaddr *)&sockaddr, &sockaddrlen)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to accept socket print connection: %s", strerror(errno)); continue; } // Create a new job with default attributes... papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Accepted socket print connection from '%s'.", httpAddrGetString(&sockaddr, buffer, sizeof(buffer))); if ((job = _papplJobCreate(printer, 0, "guest", printer->driver_data.format ? printer->driver_data.format : "application/octet-stream", "Untitled", NULL)) == NULL) { close(sock); continue; } // Read the print data from the socket... if ((job->fd = papplJobOpenFile(job, filename, sizeof(filename), printer->system->directory, NULL, "w")) < 0) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to create print file: %s", strerror(errno)); goto abort_job; } if ((job->filename = strdup(filename)) == NULL) { unlink(filename); goto abort_job; } papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Created job file \"%s\", format \"%s\".", filename, job->format); activity = time(NULL); sockp.fd = sock; sockp.events = POLLIN | POLLERR; for (;;) { if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) { bytes = -1; break; } if ((bytes = poll(&sockp, 1, 1000)) <= 0) { if ((time(NULL) - activity) >= 60) break; else continue; } if (sockp.revents & POLLIN) { activity = time(NULL); if ((bytes = recv(sock, buffer, sizeof(buffer), 0)) > 0) write(job->fd, buffer, (size_t)bytes); else break; } else if (sockp.revents & POLLERR) { bytes = -1; break; } else if (sockp.revents & POLLHUP) { break; } } close(sock); close(job->fd); job->fd = -1; if (bytes < 0) { // Error while reading goto abort_job; } // Finish the job... job->state = IPP_JSTATE_PENDING; _papplRWLockWrite(printer); _papplPrinterCheckJobsNoLock(printer); _papplRWUnlock(printer); continue; // Abort the job... abort_job: job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); _papplRWLockWrite(printer); cupsArrayRemove(printer->active_jobs, job); cupsArrayAdd(printer->completed_jobs, job); _papplSystemNeedClean(printer->system); _papplRWUnlock(printer); } } } else if (count < 0 && errno != EAGAIN) break; } _papplRWLockWrite(printer); printer->raw_active = false; _papplRWUnlock(printer); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Socket listener thread exiting on shutdown/delete."); return (NULL); } pappl-1.4.9/pappl/printer-support.c000066400000000000000000000457241476704353100173440ustar00rootroot00000000000000// // Printer support functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // Local globals... // static const char * const pappl_color_modes[] = { "auto", "auto-monochrome", "bi-level", "color", "monochrome", "process-monochrome" }; static const char * const pappl_contents[] = { "auto", "graphic", "photo", "text", "text-and-graphic" }; static const char * const pappl_finishings[] = { "punch", "staple", "trim", "booklet-maker", "fold-double-gate", "fold-half", "fold-letter", "fold-parallel", "fold-z", "punch-dual-left", "punch-dual-top", "punch-triple-left", "punch-triple-top", "punch-multiple-left", "punch-multiple-top", "saddle-stitch", "staple-top-left", "staple-bottom-left", "staple-top-right", "staple-bottom-right", "staple-dual-left", "staple-dual-top" }; static const char * const pappl_identify_actions[] = { "display", "flash", "sound", "speak" }; static const char * const pappl_kinds[] = { "disc", "document", "envelope", "label", "large-format", "photo", "postcard", "receipt", "roll" }; static const char * const pappl_label_modes[] = { "applicator", "cutter", "cutter-delayed", "kiosk", "peel-off", "peel-off-prepeel", "rewind", "rfid", "tear-off" }; static const char * const pappl_marker_colors[] = { "#777777", "#000000", "#00FFFF", "#777777", "#00CC00", "#77FFFF", "#CCCCCC", "#FFCCFF", "#FF00FF", "#FF7700", "#770077", "#FFFF00", "#00FFFF#FF00FF#FFFF00" }; static const char * const pappl_marker_types[] = { "banding-supply", "binding-supply", "cleaner-unit", "corona-wire", "covers", "developer", "fuser-cleaning-pad", "fuser-oil-wick", "fuser-oil", "fuser-oiler", "fuser", "ink-cartridge", "ink-ribbon", "ink", "inserts", "opc", "paper-wrap", "ribbon-wax", "solid-wax", "staples", "stitching-wire", "toner-cartridge", "toner", "transfer-unit", "waste-ink", "waste-toner", "waste-water", "waste-wax", "water", "glue-water-additive", "waste-paper", "shrink-wrap", "other", "unknown" }; static const char * const pappl_media_trackings[] = { "continuous", "gap", "mark", "web" }; static const char * const pappl_preasons[] = { "other", "cover-open", "input-tray-missing", "marker-supply-empty", "marker-supply-low", "marker-waste-almost-full", "marker-waste-full", "media-empty", "media-jam", "media-low", "media-needed", "offline", "spool-area-full", "toner-empty", "toner-low", "door-open", "identify-printer-requested" }; static const char * const pappl_raster_types[] = { "adobe-rgb_8", "adobe-rgb_16", "black_1", "black_8", "black_16", "cmyk_8", "cmyk_8", "rgb_8", "rgb_16", "sgray_8", "sgray_16", "srgb_8", "srgb_16" }; static const char * const pappl_scalings[] = { "auto", "auto-fit", "fill", "fit", "none" }; static const char * const pappl_sides[] = { "one-sided", "two-sided-long-edge", "two-sided-short-edge" }; static const char * const pappl_supply_colors[] = { "no-color", "black", "cyan", "gray", "green", "light-cyan", "light-gray", "light-magenta", "magenta", "orange", "violet", "yellow", "multi-color" }; static const char * const pappl_supply_types[] = { "bandingSupply", "bindingSupply", "cleanerUnit", "coronaWire", "covers", "developer", "fuserCleaningPad", "fuserOilWick", "fuserOil", "fuserOiler", "fuser", "inkCartridge", "inkRibbon", "ink", "inserts", "opc", "paperWrap", "ribbonWax", "solidWax", "staples", "stitchingWire", "tonerCartridge", "toner", "transferUnit", "wasteInk", "wasteToner", "wasteWater", "wasteWax", "water", "glueWaterAdditive", "wastePaper", "shrinkWrap", "other", "unknown" }; // // '_papplColorModeString()' - Return the keyword value associated with the IPP "print-color-mode" bit value. // const char * // O - IPP "print-color-mode" keyword value _papplColorModeString( pappl_color_mode_t value) // I - IPP "print-color-mode" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_color_modes)); } // // '_papplColorModeValue()' - Return the bit value associated with the IPP "print-color-mode" keyword value. // pappl_color_mode_t // O - IPP "print-color-mode" bit value _papplColorModeValue(const char *value) // I - IPP "print-color-mode" keyword value { return ((pappl_color_mode_t)_PAPPL_LOOKUP_VALUE(value, pappl_color_modes)); } // // '_papplContentString()' - Return the keyword associated with an IPP "print-content-optimize" bit value. // const char * // O - IPP "print-content-optimize" keyword value _papplContentString( pappl_content_t value) // I - IPP "print-content-optimize" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_contents)); } // // '_papplContentValue()' - Return the bit value associated with an IPP "print-content-optimize" keyword value. // pappl_content_t // O - IPP "print-content-optimize" bit value _papplContentValue(const char *value) // I - IPP "print-content-optimize" keyword value { return ((pappl_content_t)_PAPPL_LOOKUP_VALUE(value, pappl_contents)); } // // '_papplCreateMediaSize()' - Create a media-size collection. // ipp_t * // O - Collection value _papplCreateMediaSize( const char *size_name) // I - Media size name { pwg_media_t *pwg = pwgMediaForPWG(size_name); // Size information if (pwg) { ipp_t *col = ippNew(); // Collection value ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", pwg->width); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", pwg->length); return (col); } else { return (NULL); } } // // '_papplFinishingsEnum()' - Return the enum value associated with a finishings bit value. // ipp_finishings_t // O - IPP "finishings" enum value _papplFinishingsEnum( pappl_finishings_t v) // I - IPP "finishings" bit value { int i; // Looping var pappl_finishings_t fin; // Current finishings bit value static const ipp_finishings_t values[] = { // IPP "finishings" enum values IPP_FINISHINGS_PUNCH, IPP_FINISHINGS_STAPLE, IPP_FINISHINGS_TRIM }; for (i = 0, fin = PAPPL_FINISHINGS_PUNCH; fin <= PAPPL_FINISHINGS_TRIM; i ++, fin *= 2) { if (v & fin) return (values[i]); } return (IPP_FINISHINGS_NONE); } // // '_papplFinishingsString()' - Return the keyword value associated with a finishings bit value. // const char * // O - IPP "finishings" keyword value _papplFinishingsString( pappl_finishings_t v) // I - IPP "finishings" bit value { return (_PAPPL_LOOKUP_STRING(v, pappl_finishings)); } // // '_papplFinishingsValue()' - Return the bit value associated with a finishings keyword value. // pappl_finishings_t // O - IPP "finishings" bit value _papplFinishingsValue(const char *s) // I - IPP "finishings" keyword value { return ((pappl_finishings_t)_PAPPL_LOOKUP_VALUE(s, pappl_finishings)); } // // '_papplIdentifyActionsString()' - Return the keyword value associated with the IPP "identify-actions" bit value. // const char * // O - IPP "identify-actions" keyword value _papplIdentifyActionsString( pappl_identify_actions_t v) // I - IPP "identify-actions" bit value { return (_PAPPL_LOOKUP_STRING(v, pappl_identify_actions)); } // // '_papplIdentifyActionsValue()' - Return the bit value associated with the IPP "identify-actions" keyword value. // pappl_identify_actions_t // O - IPP "identify-actions" bit value _papplIdentifyActionsValue( const char *s) // I - IPP "identify-actions" keyword value { return ((pappl_identify_actions_t)_PAPPL_LOOKUP_VALUE(s, pappl_identify_actions)); } // // '_papplKindString()' - Return the keyword value associated with the IPP "printer-kind" bit value. // const char * // O - IPP "printer-kind" keyword value _papplKindString( pappl_kind_t value) // I - IPP "printer-kind" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_kinds)); } // // '_papplLabelModeString()' - Return the keyword value associated with the IPP "label-mode-xxx" git value. // const char * // O - IPP "label-mode-xxx" keyword value _papplLabelModeString( pappl_label_mode_t value) // I - IPP "label-mode-xxx" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_label_modes)); } // // '_papplLabelModeValue()' - Return the bit value associated with the IPP "label-mode-xxx" keyword value. // pappl_label_mode_t // O - IPP "label-mode-xxx" bit value _papplLabelModeValue(const char *value) // I - IPP "label-mode-xxx" keyword value { return ((pappl_label_mode_t)_PAPPL_LOOKUP_VALUE(value, pappl_label_modes)); } // // '_papplMarkerColorString()' - Return the IPP "marker-colors" name string associated with the supply color enumeration value. // const char * // O - IPP "marker-colors" name string _papplMarkerColorString( pappl_supply_color_t value) // I - Supply color enumeration value { if (value >= PAPPL_SUPPLY_COLOR_NO_COLOR && value <= PAPPL_SUPPLY_COLOR_YELLOW) return (pappl_marker_colors[(int)value]); else return ("unknown"); } // // '_papplMarkerTypeString()' - Return the IPP "marker-types" keyword associated with the supply type enumeration value. // const char * // O - IPP "marker-types" keyword _papplMarkerTypeString( pappl_supply_type_t value) // I - Supply type enumeration value { if (value >= PAPPL_SUPPLY_TYPE_BANDING_SUPPLY && value <= PAPPL_SUPPLY_TYPE_UNKNOWN) return (pappl_marker_types[(int)value]); else return ("unknown"); } // // '_papplMediaColExport()' - Convert media values to a collection value. // ipp_t * // O - IPP "media-col" value _papplMediaColExport( pappl_pr_driver_data_t *driver_data,// I - Driver data pappl_media_col_t *media, // I - Media values bool db) // I - Create a "media-col-database" value? { ipp_t *col = NULL, // Collection value *size = _papplCreateMediaSize(media->size_name); // media-size value if (size) { col = ippNew(); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-bottom-margin", media->bottom_margin); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-margin", media->left_margin); if (driver_data->left_offset_supported[1] && !db) ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-offset", media->left_offset); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-right-margin", media->right_margin); ippAddCollection(col, IPP_TAG_ZERO, "media-size", size); ippDelete(size); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-size-name", NULL, media->size_name); if (driver_data->num_source > 0 && media->source[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-source", NULL, media->source); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-margin", media->top_margin); if (driver_data->top_offset_supported[1] && !db) ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-offset", media->top_offset); if (driver_data->tracking_supported && media->tracking) ippAddString(col, IPP_TAG_ZERO, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-tracking", NULL, _papplMediaTrackingString(media->tracking)); if (driver_data->num_type > 0 && media->type[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-type", NULL, media->type); } return (col); } // // '_papplMediaColImport()' - Convert a collection value to media values. // void _papplMediaColImport( ipp_t *col, // I - IPP "media-col" value pappl_media_col_t *media) // O - Media values { ipp_attribute_t *size_name = ippFindAttribute(col, "media-size-name", IPP_TAG_ZERO), *x_dimension = ippFindAttribute(col, "media-size/x-dimension", IPP_TAG_INTEGER), *y_dimension = ippFindAttribute(col, "media-size/y-dimension", IPP_TAG_INTEGER), *bottom_margin = ippFindAttribute(col, "media-bottom-margin", IPP_TAG_INTEGER), *left_margin = ippFindAttribute(col, "media-left-margin", IPP_TAG_INTEGER), *left_offset = ippFindAttribute(col, "media-left-offset", IPP_TAG_INTEGER), *right_margin = ippFindAttribute(col, "media-right-margin", IPP_TAG_INTEGER), *source = ippFindAttribute(col, "media-source", IPP_TAG_ZERO), *top_margin = ippFindAttribute(col, "media-top-margin", IPP_TAG_INTEGER), *top_offset = ippFindAttribute(col, "media-top-offset", IPP_TAG_INTEGER), *tracking = ippFindAttribute(col, "media-tracking", IPP_TAG_ZERO), *type = ippFindAttribute(col, "media-type", IPP_TAG_ZERO); if (size_name) { const char *pwg_name = ippGetString(size_name, 0, NULL); pwg_media_t *pwg_media = pwgMediaForPWG(pwg_name); papplCopyString(media->size_name, pwg_name, sizeof(media->size_name)); media->size_width = pwg_media->width; media->size_length = pwg_media->length; } else if (x_dimension && y_dimension) { pwg_media_t *pwg_media = pwgMediaForSize(ippGetInteger(x_dimension, 0), ippGetInteger(y_dimension, 0)); papplCopyString(media->size_name, pwg_media->pwg, sizeof(media->size_name)); media->size_width = pwg_media->width; media->size_length = pwg_media->length; } if (bottom_margin) media->bottom_margin = ippGetInteger(bottom_margin, 0); if (left_margin) media->left_margin = ippGetInteger(left_margin, 0); if (left_offset) media->left_offset = ippGetInteger(left_offset, 0); if (right_margin) media->right_margin = ippGetInteger(right_margin, 0); if (source) papplCopyString(media->source, ippGetString(source, 0, NULL), sizeof(media->source)); if (top_margin) media->top_margin = ippGetInteger(top_margin, 0); if (top_offset) media->top_offset = ippGetInteger(top_offset, 0); if (tracking) media->tracking = _papplMediaTrackingValue(ippGetString(tracking, 0, NULL)); if (type) papplCopyString(media->type, ippGetString(type, 0, NULL), sizeof(media->type)); } // // '_papplMediaTrackingString()' - Return the keyword value associated with the IPP "media-tracking" bit value. // const char * // O - IPP "media-tracking" keyword value _papplMediaTrackingString( pappl_media_tracking_t value) // I - IPP "media-tracking" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_media_trackings)); } // // '_papplMediaTrackingValue()' - Return the bit value associated with the IPP "media-tracking" keyword value. // pappl_media_tracking_t // O - IPP "media-tracking" bit value _papplMediaTrackingValue( const char *value) // I - IPP "media-tracking" keyword value { return ((pappl_media_tracking_t)_PAPPL_LOOKUP_VALUE(value, pappl_media_trackings)); } // // '_papplPrinterReasonString()' - Return the keyword value associated with the IPP "printer-state-reasons" bit value. // const char * // O - IPP "printer-state-reasons" keyword value _papplPrinterReasonString( pappl_preason_t value) // I - IPP "printer-state-reasons" bit value { if (value == PAPPL_PREASON_NONE) return ("none"); else return (_PAPPL_LOOKUP_STRING(value, pappl_preasons)); } // // '_papplPrinterReasonValue()' - Return the bit value associated with the IPP "printer-state-reasons" keyword value. // pappl_preason_t // O - IPP "printer-state-reasons" bit value _papplPrinterReasonValue( const char *value) // I - IPP "printer-state-reasons" keyword value { return ((pappl_preason_t)_PAPPL_LOOKUP_VALUE(value, pappl_preasons)); } // // '_papplRasterTypeString()' - Return the keyword associated with an IPP "pwg-raster-document-type-supported" bit value. // const char * // O - IPP "pwg-raster-document-type-supported" keyword value _papplRasterTypeString( pappl_raster_type_t value) // I - IPP "pwg-raster-document-type-supported" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_raster_types)); } // // '_papplScalingString()' - Return the keyword associated with an IPP "print-scaling" bit value. // const char * // O - IPP "print-scaling" keyword value _papplScalingString( pappl_scaling_t value) // I - IPP "print-scaling" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_scalings)); } // // '_papplScalingValue()' - Return the bit value associated with an IPP "print-scaling" keyword value. // pappl_scaling_t // O - IPP "print-scaling" bit value _papplScalingValue(const char *value) // I - IPP "print-scaling" keyword value { return ((pappl_scaling_t)_PAPPL_LOOKUP_VALUE(value, pappl_scalings)); } // // '_papplSidesString()' - Return the keyword associated with an IPP "sides" bit value. // const char * // O - IPP "sides" keyword value _papplSidesString(pappl_sides_t value) // I - IPP "sides" bit value { return (_PAPPL_LOOKUP_STRING(value, pappl_sides)); } // // '_papplSidesValue()' - Return the bit value associated with an IPP "sides" keyword value. // pappl_sides_t // O - IPP "sides" bit value _papplSidesValue(const char *value) // I - IPP "sides" keyword value { return ((pappl_sides_t)_PAPPL_LOOKUP_VALUE(value, pappl_sides)); } // // '_papplSupplyColorString()' - Return the IPP "printer-supply" color string associated with the supply color enumeration value. // const char * // O - IPP "printer-supply" color string _papplSupplyColorString( pappl_supply_color_t value) // I - Supply color enumeration value { if (value >= PAPPL_SUPPLY_COLOR_NO_COLOR && value <= PAPPL_SUPPLY_COLOR_MULTIPLE) return (pappl_supply_colors[(int)value]); else return ("unknown"); } // // '_papplSupplyColorValue()' - Return the IPP "printer-supply" color enumeration value associated with the supply color string. // pappl_supply_color_t // O - IPP "printer-supply" color enumeration value _papplSupplyColorValue( const char *value) // I - Supply color string { int i; // Looping var for (i = 0; i < (int)(sizeof(pappl_supply_colors) / sizeof(pappl_supply_colors[0])); i ++) { if (!strcmp(value, pappl_supply_colors[i])) return ((pappl_supply_color_t)i); } if (!strcmp(value, "color")) return (PAPPL_SUPPLY_COLOR_MULTIPLE); return (PAPPL_SUPPLY_COLOR_NO_COLOR); } // // '_papplSupplyTypeString()' - Return the IPP "printer-supply" type string associated with the supply type enumeration value. // const char * // O - IPP "printer-supply" type string _papplSupplyTypeString( pappl_supply_type_t value) // I - Supply type enumeration value { if (value >= PAPPL_SUPPLY_TYPE_BANDING_SUPPLY && value <= PAPPL_SUPPLY_TYPE_UNKNOWN) return (pappl_supply_types[(int)value]); else return ("unknown"); } // // '_papplSupplyColorValue()' - Return the IPP "printer-supply" color enumeration value associated with the supply color string. // pappl_supply_type_t // O - IPP "printer-supply" type enumeration value _papplSupplyTypeValue( const char *value) // I - Supply type string { int i; // Looping var for (i = 0; i < (int)(sizeof(pappl_supply_types) / sizeof(pappl_supply_types[0])); i ++) { if (!strcmp(value, pappl_supply_types[i])) return ((pappl_supply_type_t)i); } return (PAPPL_SUPPLY_TYPE_UNKNOWN); } pappl-1.4.9/pappl/printer-usb.c000066400000000000000000001240731476704353100164140ustar00rootroot00000000000000// // USB printer class support for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" #include #ifdef __linux # include # include # include # include # include # include "httpmon-private.h" #endif // __linux // // Local constants... // #ifdef __linux # define NUM_IPP_USB 3 # define LINUX_USB_CONTROLLER "/sys/class/udc" # define LINUX_USB_GADGET "/sys/kernel/config/usb_gadget/g1" # define LINUX_IPPUSB_FFSPATH "/dev/ffs-ippusb%d" #endif // __linux // // Local types... // #ifdef __linux typedef struct _ipp_usb_descriptors_s // IPP-USB descriptors { struct usb_functionfs_descs_head_v2 header; // Descriptor header __le32 fs_count; // Number of full-speed endpoints __le32 hs_count; // Number of high-speed endpoints __le32 ss_count; // Number of super-speed endpoints struct { struct usb_interface_descriptor intf; // Interface descriptor struct usb_endpoint_descriptor_no_audio ipp_to_device, // IPP/HTTP requests ipp_to_host; // IPP/HTTP responses } __attribute__((packed)) fs_descs, // Full-speed endpoints hs_descs, // High-speed endpoints ss_descs; // Super-speed endpoints } __attribute__((packed)) _ipp_usb_descriptors_t; typedef struct _ipp_usb_iface_s // IPP-USB interface data { pthread_mutex_t mutex; // Mutex for accessing socket pappl_printer_t *printer; // Printer _pappl_http_monitor_t monitor; // HTTP state monitor int number, // Interface number (0-N) ipp_control, // IPP-USB control file ipp_to_device, // IPP/HTTP requests file ipp_to_host, // IPP/HTTP responses file ipp_sock; // Local IPP socket connection, if any http_addrlist_t *addrlist; // Local socket address pthread_t host_thread, // Thread ID for "to host" comm device_thread; // Thread ID for "to printer" comm } _ipp_usb_iface_t; #endif // __linux // // Local functions... // #ifdef __linux static bool create_directory(pappl_printer_t *printer, const char *filename); static bool create_ipp_usb_iface(pappl_printer_t *printer, int number, _ipp_usb_iface_t *iface); static bool create_string_file(pappl_printer_t *printer, const char *filename, const char *data); static bool create_symlink(pappl_printer_t *printer, const char *filename, const char *destname); static void delete_ipp_usb_iface(_ipp_usb_iface_t *data); static void disable_usb_printer(pappl_printer_t *printer, _ipp_usb_iface_t *ifaces); static bool enable_usb_printer(pappl_printer_t *printer, _ipp_usb_iface_t *ifaces); static void *run_ipp_usb_iface(_ipp_usb_iface_t *iface); #endif // __linux // // '_papplPrinterRunUSB() ' - Run the USB printer thread. // void * // O - Thread exit status (not used) _papplPrinterRunUSB( pappl_printer_t *printer) // I - Printer { #ifdef __linux int i; // Looping var struct pollfd data[NUM_IPP_USB + 1]; // USB printer gadget listeners _ipp_usb_iface_t ifaces[NUM_IPP_USB]; // IPP-USB gadget interfaces int count; // Number of file descriptors from poll() pappl_device_t *device = NULL; // Printer port data char buffer[8192]; // Print data buffer ssize_t bytes; // Bytes in buffer time_t status_time = 0; // Last port status update time_t device_time = 0; // Last time moving data... papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "USB listener thread starting."); while (!papplPrinterIsDeleted(printer) && !_papplSystemIsShutdownNoLock(printer->system)) { _papplRWLockWrite(printer); if (!enable_usb_printer(printer, ifaces)) { disable_usb_printer(printer, ifaces); _papplRWUnlock(printer); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "USB listener thread exiting on unrecoverable gadget error."); return (NULL); } printer->usb_active = true; _papplRWUnlock(printer); sleep(1); while ((data[0].fd = open("/dev/g_printer0", O_RDWR | O_EXCL)) < 0 && !papplPrinterIsDeleted(printer) && !_papplSystemIsShutdownNoLock(printer->system)) { if (errno != EBUSY && errno != ENODEV) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to open USB printer gadget: %s", strerror(errno)); goto close_gadgets; } sleep(1); } if (data[0].fd < 0) goto close_gadgets; data[0].events = POLLIN | POLLRDNORM; for (i = 0; i < NUM_IPP_USB; i ++) { data[i + 1].fd = ifaces[i].ipp_control; data[i + 1].events = POLLIN; } papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Monitoring USB for incoming print jobs."); while (!papplPrinterIsDeleted(printer) && !_papplSystemIsShutdownNoLock(printer->system)) { if ((count = poll(data, NUM_IPP_USB + 1, 1000)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "USB poll failed: %s", strerror(errno)); if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) break; sleep(1); } else if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) { break; } else if (count > 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "USB poll returned %d, revents=[%d %d %d %d].", count, data[0].revents, data[1].revents, data[2].revents, data[3].revents); if (data[0].revents & (POLLERR | POLLHUP)) { // Hard error, need to close down the gadgets goto close_gadgets; } else if (data[0].revents) { if (!device) { papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Starting USB print job."); while (!papplPrinterIsDeleted(printer) && (device = papplPrinterOpenDevice(printer)) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Waiting for USB access."); sleep(1); } if (papplPrinterIsDeleted(printer) || _papplSystemIsShutdownNoLock(printer->system)) { papplPrinterCloseDevice(printer); break; } // Start looking for back-channel data and port status status_time = 0; device_time = time(NULL); data[0].events = POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM; } if ((time(NULL) - status_time) >= 1) { // Update port status once a second... pappl_preason_t reasons = papplDeviceGetStatus(device); // Current USB status bits unsigned char port_status = PRINTER_NOT_ERROR | PRINTER_SELECTED; // Current port status bits if (reasons & PAPPL_PREASON_OTHER) port_status &= ~PRINTER_NOT_ERROR; if (reasons & PAPPL_PREASON_MEDIA_EMPTY) port_status |= PRINTER_PAPER_EMPTY; if (reasons & PAPPL_PREASON_MEDIA_JAM) port_status |= 0x40; // Extension if (reasons & PAPPL_PREASON_COVER_OPEN) port_status |= 0x80; // Extension ioctl(data[0].fd, GADGET_SET_PRINTER_STATUS, (unsigned char)port_status); status_time = time(NULL); } if (data[0].revents & POLLRDNORM) { if ((bytes = read(data[0].fd, buffer, sizeof(buffer))) > 0) { device_time = time(NULL); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Read %d bytes from USB port.", (int)bytes); if (printer->usb_cb) { if ((bytes = (printer->usb_cb)(printer, device, buffer, sizeof(buffer), (size_t)bytes, printer->usb_cbdata)) > 0) { data[0].revents = 0; // Don't try reading back from printer if (write(data[0].fd, buffer, (size_t)bytes) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to write %d bytes to host: %s", (int)bytes, strerror(errno)); goto close_gadgets; } } } else { papplDeviceWrite(device, buffer, (size_t)bytes); papplDeviceFlush(device); } } else { if (bytes < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Read error from USB host: %s", strerror(errno)); goto close_gadgets; } papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Finishing USB print job."); papplPrinterCloseDevice(printer); device = NULL; } } else if (data[0].revents & POLLWRNORM) { if ((bytes = papplDeviceRead(device, buffer, sizeof(buffer))) > 0) { device_time = time(NULL); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Read %d bytes from printer.", (int)bytes); if (write(data[0].fd, buffer, (size_t)bytes) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to write %d bytes to host: %s", (int)bytes, strerror(errno)); goto close_gadgets; } } } } // Check for IPP-USB control messages... for (i = 0; i < NUM_IPP_USB; i ++) { if (data[i + 1].revents & (POLLERR | POLLHUP)) { // Hard error, need to close down the gadgets goto close_gadgets; } else if (data[i + 1].revents) { struct usb_functionfs_event *event; // IPP-USB control event if (read(ifaces[i].ipp_control, buffer, sizeof(buffer)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_WARN, "IPP-USB event read error: %s", strerror(errno)); goto close_gadgets; } event = (struct usb_functionfs_event *)buffer; switch (event->type) { case FUNCTIONFS_BIND : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "BIND%d", i); break; case FUNCTIONFS_UNBIND : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "UNBIND%d", i); break; case FUNCTIONFS_ENABLE : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "ENABLE%d", i); break; case FUNCTIONFS_DISABLE : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "DISABLE%d", i); break; case FUNCTIONFS_SETUP : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "SETUP%d bRequestType=%d, bRequest=%d, wValue=%d, wIndex=%d, wLength=%d", i, event->u.setup.bRequestType, event->u.setup.bRequest, le16toh(event->u.setup.wValue), le16toh(event->u.setup.wIndex), le16toh(event->u.setup.wLength)); break; case FUNCTIONFS_SUSPEND : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "SUSPEND%d", i); break; case FUNCTIONFS_RESUME : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "RESUME%d", i); break; default : papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "UNKNOWN%d type=%d", i, event->type); break; } } } } else { // No new data, sleep 1ms to prevent excessive CPU usage... usleep(1000); } if (device && (time(NULL) - device_time) > 5) { // Finish talking to the printer... papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Finishing USB print job."); papplPrinterCloseDevice(printer); device = NULL; // Stop doing back-channel data data[0].events = POLLIN | POLLRDNORM; } } close_gadgets: papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Disabling USB for incoming print jobs."); if (device) { papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "Finishing USB print job."); papplPrinterCloseDevice(printer); } if (data[0].fd >= 0) { close(data[0].fd); data[0].fd = -1; } _papplRWLockWrite(printer); disable_usb_printer(printer, ifaces); _papplRWUnlock(printer); } #else (void)printer; #endif // __linux papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "USB listener thread exiting on shutdown/delete."); return (NULL); } // // 'papplPrinterSetUSB()' - Set the USB vendor and product IDs for a printer. // // This function sets the USB vendor and product IDs for a printer as well as // specifying USB gadget options when the printer is registered with the USB // device controller. // // The `usb_cb` argument specifies a processing callback that is called for // every byte of data sent from the USB host and which is responsible for // interpreting the data, writing data to the device, and handling back-channel // data. // // > Note: USB gadget functionality is currently only available when running // > on Linux with compatible hardware such as the Raspberry Pi Zero and 4B. // void papplPrinterSetUSB( pappl_printer_t *printer, // I - Printer unsigned vendor_id, // I - USB vendor ID unsigned product_id, // I - USB product ID pappl_uoptions_t options, // I - USB gadget options const char *storagefile, // I - USB storage file, if any pappl_pr_usb_cb_t usb_cb, // I - USB processing callback, if any void *usb_cbdata) // I - USB processing callback data, if any { if (printer) { // Don't allow changes once the gadget is running... _papplRWLockWrite(printer); if (printer->usb_active) { _papplRWUnlock(printer); papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "USB gadget options already set, unable to change."); return; } // Update the USB gadget settings... printer->usb_vendor_id = (unsigned short)vendor_id; printer->usb_product_id = (unsigned short)product_id; printer->usb_options = options; printer->usb_cb = usb_cb; printer->usb_cbdata = usb_cbdata; free(printer->usb_storage); if (storagefile) printer->usb_storage = strdup(storagefile); else printer->usb_storage = NULL; _papplRWUnlock(printer); // Start USB gadget if needed... if (papplSystemIsRunning(printer->system) && papplSystemGetDefaultPrinterID(printer->system) == printer->printer_id && (printer->system->options & PAPPL_SOPTIONS_USB_PRINTER)) { pthread_t tid; // Thread ID if (pthread_create(&tid, NULL, (void *(*)(void *))_papplPrinterRunUSB, printer)) { // Unable to create USB thread... papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget thread: %s", strerror(errno)); } else { // Detach the main thread from the USB thread to prevent hangs... pthread_detach(tid); _papplRWLockRead(printer); while (!printer->usb_active) { _papplRWUnlock(printer); usleep(1000); // Wait for USB thread to start _papplRWLockRead(printer); } _papplRWUnlock(printer); } } } } #ifdef __linux // // 'create_directory()' - Create a directory. // static bool // O - `true` on success, `false` otherwise create_directory( pappl_printer_t *printer, // I - Printer const char *filename) // I - Directory path { if (mkdir(filename, 0777) && errno != EEXIST) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget directory '%s': %s", filename, strerror(errno)); return (false); } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Created USB gadget directory '%s'.", filename); return (true); } } // // 'create_ipp_usb()' - Create an IPP-USB gadget instance. // // Each instance provides a single socket pair. // static bool // O - `true` on success, `false` otherwise create_ipp_usb_iface( pappl_printer_t *printer, // I - Printer int number, // I - Interface number (0-N) _ipp_usb_iface_t *iface) // O - IPP-USB interface data { int count; // Number of times we've tried to create this interface char filename[1024], // Filename destname[1024], // Destination filename for symlink devpath[256]; // Device directory _ipp_usb_descriptors_t descriptors; // IPP-USB descriptors struct usb_functionfs_strings_head strings; // IPP-USB strings (none) // Initialize IPP-USB data... pthread_mutex_init(&iface->mutex, NULL); _papplHTTPMonitorInit(&iface->monitor); iface->printer = printer; iface->host_thread = 0; iface->device_thread = 0; iface->number = number; iface->ipp_control = -1; iface->ipp_to_device = -1; iface->ipp_to_host = -1; iface->ipp_sock = -1; iface->addrlist = NULL; // Start by creating the function in the configfs directory... snprintf(filename, sizeof(filename), LINUX_USB_GADGET "/functions/ffs.ippusb%d", number); if (!create_directory(printer, filename)) return (false); // Failed snprintf(destname, sizeof(destname), LINUX_USB_GADGET "/configs/c.1/ffs.ippusb%d", number); if (!create_symlink(printer, filename, destname)) return (false); // Failed // Then mount the filesystem... snprintf(filename, sizeof(filename), "ippusb%d", number); snprintf(devpath, sizeof(devpath), LINUX_IPPUSB_FFSPATH, number); if (!create_directory(printer, devpath)) return (false); // Failed count = 0; while (mount(filename, devpath, "functionfs", 0, NULL)) { count ++; if (errno != EBUSY || count >= 10) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to mount USB gadget filesystem '%s': %s", devpath, strerror(errno)); return (false); } papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Unable to mount USB gadget filesystem '%s' (retrying in 1 second): %s", devpath, strerror(errno)); sleep(1); } // Try opening the control file... snprintf(filename, sizeof(filename), "%s/ep0", devpath); count = 0; while ((iface->ipp_control = open(filename, O_RDWR)) < 0) { count ++; if ((errno != EBUSY && errno != ENODEV) || count >= 10) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to open USB gadget control file '%s': %s", filename, strerror(errno)); return (false); } papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Unable to open USB gadget control file '%s' (retrying in 1 second): %s", filename, strerror(errno)); sleep(1); } // Now fill out the USB descriptors... memset(&descriptors, 0, sizeof(descriptors)); descriptors.header.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2); descriptors.header.flags = htole32(FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | FUNCTIONFS_HAS_SS_DESC); descriptors.header.length = htole32(sizeof(descriptors)); descriptors.fs_count = htole32(3); descriptors.hs_count = htole32(3); descriptors.ss_count = htole32(3); descriptors.fs_descs.intf.bLength = sizeof(descriptors.fs_descs.intf); descriptors.fs_descs.intf.bDescriptorType = USB_DT_INTERFACE; descriptors.fs_descs.intf.bNumEndpoints = 2; descriptors.fs_descs.intf.bInterfaceClass = USB_CLASS_PRINTER; descriptors.fs_descs.intf.bInterfaceSubClass = 1; descriptors.fs_descs.intf.bInterfaceProtocol = 4; // IPP-USB descriptors.fs_descs.ipp_to_device.bLength = sizeof(descriptors.fs_descs.ipp_to_device); descriptors.fs_descs.ipp_to_device.bDescriptorType = USB_DT_ENDPOINT; descriptors.fs_descs.ipp_to_device.bEndpointAddress = 1 | USB_DIR_OUT; descriptors.fs_descs.ipp_to_device.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.fs_descs.ipp_to_host.bLength = sizeof(descriptors.fs_descs.ipp_to_host); descriptors.fs_descs.ipp_to_host.bDescriptorType = USB_DT_ENDPOINT; descriptors.fs_descs.ipp_to_host.bEndpointAddress = 2 | USB_DIR_IN; descriptors.fs_descs.ipp_to_host.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.hs_descs.intf.bLength = sizeof(descriptors.hs_descs.intf); descriptors.hs_descs.intf.bDescriptorType = USB_DT_INTERFACE; descriptors.hs_descs.intf.bNumEndpoints = 2; descriptors.hs_descs.intf.bInterfaceClass = USB_CLASS_PRINTER; descriptors.hs_descs.intf.bInterfaceSubClass = 1; descriptors.hs_descs.intf.bInterfaceProtocol = 4; // IPP-USB descriptors.hs_descs.ipp_to_device.bLength = sizeof(descriptors.hs_descs.ipp_to_device); descriptors.hs_descs.ipp_to_device.bDescriptorType = USB_DT_ENDPOINT; descriptors.hs_descs.ipp_to_device.bEndpointAddress = 1 | USB_DIR_OUT; descriptors.hs_descs.ipp_to_device.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.hs_descs.ipp_to_device.wMaxPacketSize = htole16(512); descriptors.hs_descs.ipp_to_host.bLength = sizeof(descriptors.hs_descs.ipp_to_host); descriptors.hs_descs.ipp_to_host.bDescriptorType = USB_DT_ENDPOINT; descriptors.hs_descs.ipp_to_host.bEndpointAddress = 2 | USB_DIR_IN; descriptors.hs_descs.ipp_to_host.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.hs_descs.ipp_to_host.wMaxPacketSize = htole16(512); descriptors.ss_descs.intf.bLength = sizeof(descriptors.ss_descs.intf); descriptors.ss_descs.intf.bDescriptorType = USB_DT_INTERFACE; descriptors.ss_descs.intf.bNumEndpoints = 2; descriptors.ss_descs.intf.bInterfaceClass = USB_CLASS_PRINTER; descriptors.ss_descs.intf.bInterfaceSubClass = 1; descriptors.ss_descs.intf.bInterfaceProtocol = 4; // IPP-USB descriptors.ss_descs.ipp_to_device.bLength = sizeof(descriptors.ss_descs.ipp_to_device); descriptors.ss_descs.ipp_to_device.bDescriptorType = USB_DT_ENDPOINT; descriptors.ss_descs.ipp_to_device.bEndpointAddress = 1 | USB_DIR_OUT; descriptors.ss_descs.ipp_to_device.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.ss_descs.ipp_to_device.wMaxPacketSize = htole16(1024); descriptors.ss_descs.ipp_to_host.bLength = sizeof(descriptors.ss_descs.ipp_to_host); descriptors.ss_descs.ipp_to_host.bDescriptorType = USB_DT_ENDPOINT; descriptors.ss_descs.ipp_to_host.bEndpointAddress = 2 | USB_DIR_IN; descriptors.ss_descs.ipp_to_host.bmAttributes = USB_ENDPOINT_XFER_BULK; descriptors.ss_descs.ipp_to_host.wMaxPacketSize = htole16(1024); // and the strings (none)... memset(&strings, 0, sizeof(strings)); strings.magic = htole32(FUNCTIONFS_STRINGS_MAGIC); strings.length = htole32(sizeof(strings)); // Now write the descriptors and strings values... if (write(iface->ipp_control, &descriptors, sizeof(descriptors)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to write IPP-USB descriptors to gadget control file '%s': %s", filename, strerror(errno)); return (false); } if (write(iface->ipp_control, &strings, sizeof(strings)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to write IPP-USB strings to gadget control file '%s': %s", filename, strerror(errno)); return (false); } // At this point the endpoints should be accessible... snprintf(filename, sizeof(filename), "%s/ep1", devpath); if ((iface->ipp_to_device = open(filename, O_RDONLY)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to open IPP-USB gadget printer endpoint file '%s': %s", filename, strerror(errno)); return (false); } snprintf(filename, sizeof(filename), "%s/ep2", devpath); if ((iface->ipp_to_host = open(filename, O_WRONLY)) < 0) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to open IPP-USB gadget host endpoint file '%s': %s", filename, strerror(errno)); return (false); } // Find the address for the local TCP/IP socket... if (printer->system->domain_path) { // Use UNIX domain socket... if ((iface->addrlist = httpAddrGetList(printer->system->domain_path, AF_LOCAL, "0")) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to lookup '%s' for IPP USB gadget: %s", printer->system->domain_path, cupsGetErrorString()); return (false); } } else { // Use localhost TCP/IP port... snprintf(filename, sizeof(filename), "%d", printer->system->port); if ((iface->addrlist = httpAddrGetList("localhost", AF_UNSPEC, filename)) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to lookup 'localhost:%d' for IPP USB gadget: %s", printer->system->port, cupsGetErrorString()); return (false); } } // Start a thread to relay IPP/HTTP messages between USB and TCP/IP... if (pthread_create(&iface->device_thread, NULL, (void *(*)(void *))run_ipp_usb_iface, iface)) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to start IPP-USB gadget thread for endpoint %d: %s", number, strerror(errno)); return (false); } // If we got this far, everything is setup! return (true); } // // 'create_string_file()' - Create a file containing the specified string. // // A newline is automatically added as needed. // static bool // O - `true` on success, `false` otherwise create_string_file( pappl_printer_t *printer, // I - Printer const char *filename, // I - File path const char *data) // I - Contents of file { cups_file_t *fp; // File pointer if ((fp = cupsFileOpen(filename, "w")) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget file '%s': %s", filename, strerror(errno)); return (false); } if (!*data || data[strlen(data) - 1] != '\n') cupsFilePrintf(fp, "%s\n", data); else cupsFilePuts(fp, data); cupsFileClose(fp); papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Created USB gadget file '%s' containing '%s'.", filename, data); return (true); } // // 'create_symlink()' - Create a symbolic link. // static bool // O - `true` on success, `false` otherwise create_symlink( pappl_printer_t *printer, // I - Printer const char *filename, // I - Source filename const char *destname) // I - Destination filename { if (symlink(filename, destname) && errno != EEXIST) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget symlink '%s': %s", filename, strerror(errno)); return (false); } else { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Created USB gadget symlink '%s' to '%s'.", filename, destname); return (true); } } // // 'delete_ipp_usb_iface()' - Delete an IPP-USB gadget interface. // static void delete_ipp_usb_iface( _ipp_usb_iface_t *iface) // I - IPP-USB data { char devpath[256]; // IPP-USB device path if (iface->ipp_control >= 0) { close(iface->ipp_control); iface->ipp_control = -1; } if (iface->host_thread) { pthread_cancel(iface->host_thread); iface->host_thread = 0; } if (iface->device_thread) { pthread_cancel(iface->device_thread); iface->device_thread = 0; } pthread_mutex_destroy(&iface->mutex); if (iface->ipp_to_device >= 0) { close(iface->ipp_to_device); iface->ipp_to_device = -1; } if (iface->ipp_to_host >= 0) { close(iface->ipp_to_host); iface->ipp_to_host = -1; } if (iface->ipp_sock >= 0) { close(iface->ipp_sock); iface->ipp_sock = -1; } httpAddrFreeList(iface->addrlist); iface->addrlist = NULL; snprintf(devpath, sizeof(devpath), LINUX_IPPUSB_FFSPATH, iface->number); if (umount(devpath)) papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "Unable to unmount '%s': %s", devpath, strerror(errno)); } // // 'disable_usb_printer()' - Disable the USB printer gadget module. // static void disable_usb_printer( pappl_printer_t *printer, // I - Printer _ipp_usb_iface_t *ifaces) // I - IPP-USB interfaces { int i; // Looping var const char *gadget_dir = LINUX_USB_GADGET; // Gadget directory char filename[1024]; // Filename snprintf(filename, sizeof(filename), "%s/UDC", gadget_dir); if (!create_string_file(printer, filename, "\n")) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget file '%s': %s", filename, strerror(errno)); } for (i = 0; i < NUM_IPP_USB; i ++) delete_ipp_usb_iface(ifaces + i); printer->usb_active = false; papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "USB gadgets disabled."); } // // 'enable_usb_printer()' - Configure and enable the USB printer gadget module. // static bool // O - `true` on success, `false` otherwise enable_usb_printer( pappl_printer_t *printer, // I - Printer _ipp_usb_iface_t *ifaces) // I - IPP-USB interfaces { int i; // Looping var const char *gadget_dir = LINUX_USB_GADGET; // Gadget directory char filename[1024], // Filename destname[1024]; // Destination filename for symlinks cups_dir_t *dir; // Controller directory cups_dentry_t *dent; // Directory entry int num_devid; // Number of device ID values cups_option_t *devid; // Device ID values const char *val; // Value char temp[1024], // Temporary string mfg[256], // Manufacturer mdl[256], // Model name sn[256]; // Serial number // Get the information for this printer - vendor ID, product ID, etc. num_devid = papplDeviceParseID(printer->device_id, &devid); if (printer->driver_data.make_and_model[0]) { // Get the make and model from the driver info... char *ptr; // Pointer into make-and-model papplCopyString(mfg, printer->driver_data.make_and_model, sizeof(mfg)); if ((ptr = strstr(mfg, "Hewlett Packard")) != NULL) ptr += 15; else ptr = strchr(mfg, ' '); if (ptr && *ptr) { // Split make from model... while (*ptr && isspace(*ptr & 255)) *ptr++ = '\0'; if (*ptr) papplCopyString(mdl, ptr, sizeof(mdl)); else papplCopyString(mdl, "Printer", sizeof(mdl)); } else { // No whitespace so assume the make-and-model is just the make and use // the device ID for the model (with a default of "Printer")... val = cupsGetOption("MODEL", num_devid, devid); if (!val) val = cupsGetOption("MDL", num_devid, devid); if (val) papplCopyString(mdl, val, sizeof(mdl)); else papplCopyString(mdl, "Printer", sizeof(mdl)); } } else { // Get the make and model from the device ID fields. val = cupsGetOption("MANUFACTURER", num_devid, devid); if (!val) val = cupsGetOption("MFG", num_devid, devid); if (!val) val = cupsGetOption("MFR", num_devid, devid); if (val) papplCopyString(mfg, val, sizeof(mfg)); else papplCopyString(mfg, "Unknown", sizeof(mfg)); val = cupsGetOption("MODEL", num_devid, devid); if (!val) val = cupsGetOption("MDL", num_devid, devid); if (val) papplCopyString(mdl, val, sizeof(mdl)); else papplCopyString(mdl, "Printer", sizeof(mdl)); } val = cupsGetOption("SERIALNUMBER", num_devid, devid); if (!val) val = cupsGetOption("SN", num_devid, devid); if (!val) val = cupsGetOption("SER", num_devid, devid); if (!val) val = cupsGetOption("SERN", num_devid, devid); if (!val && (val = strstr(printer->device_uri, "?serial=")) != NULL) val += 8; if (!val && (val = strstr(printer->device_uri, "?uuid=")) != NULL) val += 6; if (val) papplCopyString(sn, val, sizeof(sn)); else papplCopyString(sn, "0", sizeof(sn)); cupsFreeOptions(num_devid, devid); // Modern Linux kernels support USB gadgets through the configfs interface. // PAPPL takes control of this interface, so if you need (for example) a // serial gadget in addition to the printer gadget you need to specify that // with a call to papplPrinterSetUSB. // // The configfs interface lives under "/sys/kernel/config/usb_gadget/". The // available USB Device Controllers can be found under "/sys/class/udc". We // currently assume there will only be one of those and will expand the USB // gadget interface later as needed. // // The typical directory structure looks like this: // // g1/ // idVendor (usb_vendor ID as a hex number, e.g. "0x12CD") // idProduct (usb product ID as a hex number, e.g. "0x34AB") // strings/0x409/ // manufacturer (manufacturer name string) // product (model name string) // serialnumber (serial number string) // configs/c.1/ // symlink to functions/printer.g_printer0 // functions/printer.g_printer0 // pnp_string (IEEE-1284 device ID string) // UDC (first entry from /sys/class/udc) // Create the gadget configuration files and directories... if (!create_directory(printer, gadget_dir)) return (false); snprintf(filename, sizeof(filename), "%s/bDeviceClass", gadget_dir); if (!create_string_file(printer, filename, "0x00\n")) return (false); snprintf(filename, sizeof(filename), "%s/bDeviceSubClass", gadget_dir); if (!create_string_file(printer, filename, "0x00\n")) return (false); snprintf(filename, sizeof(filename), "%s/bDeviceProtocol", gadget_dir); if (!create_string_file(printer, filename, "0x00\n")) return (false); snprintf(filename, sizeof(filename), "%s/bcdUSB", gadget_dir); if (!create_string_file(printer, filename, "0x0200\n")) return (false); snprintf(filename, sizeof(filename), "%s/idVendor", gadget_dir); snprintf(temp, sizeof(temp), "0x%04x\n", printer->usb_vendor_id); if (!create_string_file(printer, filename, temp)) return (false); snprintf(filename, sizeof(filename), "%s/idProduct", gadget_dir); snprintf(temp, sizeof(temp), "0x%04x\n", printer->usb_product_id); if (!create_string_file(printer, filename, temp)) return (false); snprintf(filename, sizeof(filename), "%s/strings/0x409", gadget_dir); if (!create_directory(printer, filename)) return (false); snprintf(filename, sizeof(filename), "%s/strings/0x409/manufacturer", gadget_dir); if (!create_string_file(printer, filename, mfg)) return (false); snprintf(filename, sizeof(filename), "%s/strings/0x409/product", gadget_dir); if (!create_string_file(printer, filename, mdl)) return (false); snprintf(filename, sizeof(filename), "%s/strings/0x409/serialnumber", gadget_dir); if (!create_string_file(printer, filename, sn)) return (false); snprintf(filename, sizeof(filename), "%s/configs/c.1", gadget_dir); if (!create_directory(printer, filename)) return (false); // Create the legacy USB printer gadget... snprintf(filename, sizeof(filename), "%s/functions/printer.g_printer0", gadget_dir); if (!create_directory(printer, filename)) return (false); snprintf(filename, sizeof(filename), "%s/functions/printer.g_printer0/pnp_string", gadget_dir); if (!create_string_file(printer, filename, printer->device_id)) return (false); snprintf(filename, sizeof(filename), "%s/functions/printer.g_printer0/q_len", gadget_dir); // Note: Cannot error out on this since q_len cannot be changed once the // f_printer module is instantiated - see EMBEDDED.md for details and a patch #ifdef __COVERITY__ if (!create_string_file(printer, filename, "10\n")) { papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Ignoring q_len error - known Linux bug."); } #else create_string_file(printer, filename, "10\n"); #endif // __COVERITY__ snprintf(filename, sizeof(filename), "%s/functions/printer.g_printer0", gadget_dir); snprintf(destname, sizeof(destname), "%s/configs/c.1/printer.g_printer0", gadget_dir); if (!create_symlink(printer, filename, destname)) return (false); // Create the IPP-USB printer gadget... for (i = 0; i < NUM_IPP_USB; i ++) { if (!create_ipp_usb_iface(printer, i, ifaces + i)) { while (i > 0) { i --; delete_ipp_usb_iface(ifaces + i); } return (false); } } // Add optional gadgets... if (printer->usb_options & PAPPL_UOPTIONS_ETHERNET) { // Standard USB-Ethernet interface... snprintf(filename, sizeof(filename), "%s/functions/ncm.usb0", gadget_dir); if (!create_directory(printer, filename)) goto error; snprintf(destname, sizeof(destname), "%s/configs/c.1/ncm.usb0", gadget_dir); if (!create_symlink(printer, filename, destname)) goto error; } if (printer->usb_options & PAPPL_UOPTIONS_SERIAL) { // Standard serial port... snprintf(filename, sizeof(filename), "%s/functions/acm.ttyGS0", gadget_dir); if (!create_directory(printer, filename)) goto error; snprintf(destname, sizeof(destname), "%s/configs/c.1/acm.ttyGS0", gadget_dir); if (!create_symlink(printer, filename, destname)) goto error; } if ((printer->usb_options & PAPPL_UOPTIONS_STORAGE) && printer->usb_storage) { // Standard USB mass storage device... snprintf(filename, sizeof(filename), "%s/functions/mass_storage.0", gadget_dir); if (!create_directory(printer, filename)) goto error; snprintf(filename, sizeof(filename), "%s/functions/mass_storage.0/lun.0/file", gadget_dir); if (!create_string_file(printer, filename, printer->usb_storage)) goto error; if (printer->usb_options & PAPPL_UOPTIONS_STORAGE_READONLY) { snprintf(filename, sizeof(filename), "%s/functions/mass_storage.0/lun.0/ro", gadget_dir); if (!create_string_file(printer, filename, "1\n")) goto error; } if (printer->usb_options & PAPPL_UOPTIONS_STORAGE_REMOVABLE) { snprintf(filename, sizeof(filename), "%s/functions/mass_storage.0/lun.0/removable", gadget_dir); if (!create_string_file(printer, filename, "1\n")) goto error; } snprintf(filename, sizeof(filename), "%s/functions/mass_storage.0", gadget_dir); snprintf(destname, sizeof(destname), "%s/configs/c.1/mass_storage.0", gadget_dir); if (!create_symlink(printer, filename, destname)) goto error; } // Then assign this configuration to the first USB device controller if ((dir = cupsDirOpen(LINUX_USB_CONTROLLER)) == NULL) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to find USB device controller in '%s': %s", LINUX_USB_CONTROLLER, strerror(errno)); goto error; } while ((dent = cupsDirRead(dir)) != NULL) { if (dent->filename[0] != '.' && dent->filename[0]) break; papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Ignoring UDC '%s'...", dent->filename); } if (!dent) { papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "No USB device controller in '%s': %s", LINUX_USB_CONTROLLER, strerror(errno)); cupsDirClose(dir); goto error; } papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Using UDC '%s' for USB gadgets.", dent->filename); snprintf(filename, sizeof(filename), "%s/UDC", gadget_dir); if (!create_string_file(printer, filename, dent->filename)) { cupsDirClose(dir); goto error; } cupsDirClose(dir); papplLogPrinter(printer, PAPPL_LOGLEVEL_INFO, "USB printer gadget configured."); return (true); // If we get here we need to tear down the IPP-USB interfaces... error: papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Tearing down USB printer gadget."); for (i = 0; i < NUM_IPP_USB; i ++) delete_ipp_usb_iface(ifaces + i); return (false); } // // 'run_ipp_usb_iface()' - Run an I/O thread for IPP-USB. // // This function serializes IPP/HTTP requests from the host, relays them to a // local socket, and then relays the IPP/HTTP response. // static void * // O - Thread exit status run_ipp_usb_iface( _ipp_usb_iface_t *iface) // I - Thread data { char devbuf[8192], // Device buffer hostbuf[8192]; // Host buffer const char *hostptr; // Pointer into buffer size_t hostlen; // Number of bytes in host buffer ssize_t bytes; // Bytes read papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_INFO, "IPP-USB%d: Starting.", iface->number); while (!papplPrinterIsDeleted(iface->printer) && papplSystemIsRunning(papplPrinterGetSystem(iface->printer))) { // Wait for data from the host... if ((bytes = read(iface->ipp_to_device, hostbuf, sizeof(hostbuf))) > 0) { // Got data from the host, send it to the local socket... if (iface->ipp_sock < 0) { // (Re)connect to the local service... if (!httpAddrConnect(iface->addrlist, &iface->ipp_sock, 10000, NULL)) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: Unable to connect to local socket: %s", iface->number, strerror(errno)); goto error; } papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_INFO, "IPP-USB%d: Opened socket %d.", iface->number, iface->ipp_sock); // Initialize the HTTP state monitor... _papplHTTPMonitorInit(&iface->monitor); } // Scan the incoming IPP/HTTP request and relay it to the socket... hostptr = hostbuf; hostlen = (size_t)bytes; while (hostlen > 0) { if (_papplHTTPMonitorProcessHostData(&iface->monitor, &hostptr, &hostlen) == HTTP_STATUS_ERROR) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: %s", iface->number, _papplHTTPMonitorGetError(&iface->monitor)); close(iface->ipp_sock); iface->ipp_sock = -1; break; } } if (iface->ipp_sock < 0) continue; // Send the request data to the local service... papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_DEBUG, "IPP-USB%d: Sending %d bytes to socket %d.", iface->number, (int)bytes, iface->ipp_sock); if (write(iface->ipp_sock, hostbuf, (size_t)bytes) < 0) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: Unable to send data to socket: %s", iface->number, strerror(errno)); close(iface->ipp_sock); iface->ipp_sock = -1; continue; } // If we are ready for a response, read it back... if (iface->monitor.state != HTTP_STATE_WAITING && iface->monitor.phase == _PAPPL_HTTP_PHASE_SERVER_HEADERS) { while (iface->monitor.state != HTTP_STATE_WAITING) { do { bytes = read(iface->ipp_sock, devbuf, sizeof(devbuf)); } while (bytes < 0 && (errno == EAGAIN || errno == EINTR)); if (bytes > 0) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_DEBUG, "IPP-USB%d: Returning %d bytes.", iface->number, (int)bytes); if (_papplHTTPMonitorProcessDeviceData(&iface->monitor, devbuf, bytes) == HTTP_STATUS_ERROR) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: %s", iface->number, _papplHTTPMonitorGetError(&iface->monitor)); goto error; } if (write(iface->ipp_to_host, devbuf, (size_t)bytes) < 0) { papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: Error returning data to host: %s", iface->number, strerror(errno)); goto error; } } else if (bytes < 0) { // Close socket... if (errno == EPIPE || errno == ECONNRESET) papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_INFO, "IPP-USB%d: Socket %d closed prematurely.", iface->number, iface->ipp_sock); else papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_ERROR, "IPP-USB%d: Unable to read data from socket: %s", iface->number, strerror(errno)); goto error; } else if (bytes == 0) { // Closed connection papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_INFO, "IPP-USB%d: Socket %d closed.", iface->number, iface->ipp_sock); break; } } // For now, always close socket after a completed request... close(iface->ipp_sock); iface->ipp_sock = -1; } } } error: papplLogPrinter(iface->printer, PAPPL_LOGLEVEL_INFO, "IPP-USB%d: Shutting down.", iface->number); // Shut down any socket and host thread... if (iface->ipp_sock >= 0) { close(iface->ipp_sock); iface->ipp_sock = -1; } iface->device_thread = 0; return (NULL); } #endif // __linux pappl-1.4.9/pappl/printer-webif.c000066400000000000000000002165201476704353100167160ustar00rootroot00000000000000// // Printer web interface functions for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static void job_cb(pappl_job_t *job, pappl_client_t *client); static void job_pager(pappl_client_t *client, pappl_printer_t *printer, int job_index, int limit); static char *localize_keyword(pappl_client_t *client, const char *attrname, const char *keyword, char *buffer, size_t bufsize); static char *localize_media(pappl_client_t *client, pappl_media_col_t *media, bool include_source, char *buffer, size_t bufsize); static void media_chooser(pappl_client_t *client, pappl_pr_driver_data_t *driver_data, const char *title, const char *name, pappl_media_col_t *media); static char *time_string(pappl_client_t *client, time_t tv, char *buffer, size_t bufsize); // // '_papplPrinterWebCancelAllJobs()' - Cancel all printer jobs. // void _papplPrinterWebCancelAllJobs( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { const char *status = NULL; // Status message, if any if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { char path[1024]; // Resource path papplPrinterCancelAllJobs(printer); snprintf(path, sizeof(path), "%s/jobs", printer->uriname); papplClientRespondRedirect(client, HTTP_STATUS_FOUND, path); cupsFreeOptions(num_form, form); return; } cupsFreeOptions(num_form, form); } papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Cancel All Jobs"), 0, NULL, NULL); if (status) papplClientHTMLPrintf(client, "

\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " ", papplClientGetLocString(client, _PAPPL_LOC("Confirm Cancel All"))); if (papplPrinterGetNumberOfActiveJobs(printer) > 0) { papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Job #")), papplClientGetLocString(client, _PAPPL_LOC("Name")), papplClientGetLocString(client, _PAPPL_LOC("Owner")), papplClientGetLocString(client, _PAPPL_LOC("Pages Completed")), papplClientGetLocString(client, _PAPPL_LOC("Status"))); papplPrinterIterateActiveJobs(printer, (pappl_job_cb_t)job_cb, client, 1, 0); papplClientHTMLPuts(client, " \n" "
%s%s%s%s%s
\n"); } else papplClientHTMLPrintf(client, "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("No jobs in history."))); papplClientHTMLFooter(client); } // // '_papplPrinterWebConfig()' - Show the printer configuration web page. // void _papplPrinterWebConfig( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { const char *status = NULL; // Status message, if any char dns_sd_name[64], // DNS-SD name location[128], // Location geo_location[128], // Geo-location latitude organization[128], // Organization org_unit[128]; // Organizational unit pappl_contact_t contact; // Contact info if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { _papplPrinterWebConfigFinalize(printer, num_form, form); status = _PAPPL_LOC("Changes saved."); } cupsFreeOptions(num_form, form); } papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Configuration"), 0, NULL, NULL); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); _papplClientHTMLInfo(client, true, papplPrinterGetDNSSDName(printer, dns_sd_name, sizeof(dns_sd_name)), papplPrinterGetLocation(printer, location, sizeof(location)), papplPrinterGetGeoLocation(printer, geo_location, sizeof(geo_location)), papplPrinterGetOrganization(printer, organization, sizeof(organization)), papplPrinterGetOrganizationalUnit(printer, org_unit, sizeof(org_unit)), papplPrinterGetContact(printer, &contact)); papplClientHTMLPrinterFooter(client); } // // '_papplPrinterWebConfigFinalize()' - Save the changes to the printer configuration. // void _papplPrinterWebConfigFinalize( pappl_printer_t *printer, // I - Printer cups_len_t num_form, // I - Number of form variables cups_option_t *form) // I - Form variables { const char *value, // Form value *geo_lat, // Geo-location latitude *geo_lon, // Geo-location longitude *contact_name, // Contact name *contact_email, // Contact email *contact_tel; // Contact telephone number if ((value = cupsGetOption("dns_sd_name", num_form, form)) != NULL) papplPrinterSetDNSSDName(printer, *value ? value : NULL); if ((value = cupsGetOption("location", num_form, form)) != NULL) papplPrinterSetLocation(printer, *value ? value : NULL); geo_lat = cupsGetOption("geo_location_lat", num_form, form); geo_lon = cupsGetOption("geo_location_lon", num_form, form); if (geo_lat && geo_lon) { char uri[1024]; // "geo:" URI if (*geo_lat && *geo_lon) { snprintf(uri, sizeof(uri), "geo:%g,%g", strtod(geo_lat, NULL), strtod(geo_lon, NULL)); papplPrinterSetGeoLocation(printer, uri); } else papplPrinterSetGeoLocation(printer, NULL); } if ((value = cupsGetOption("organization", num_form, form)) != NULL) papplPrinterSetOrganization(printer, *value ? value : NULL); if ((value = cupsGetOption("organizational_unit", num_form, form)) != NULL) papplPrinterSetOrganizationalUnit(printer, *value ? value : NULL); contact_name = cupsGetOption("contact_name", num_form, form); contact_email = cupsGetOption("contact_email", num_form, form); contact_tel = cupsGetOption("contact_telephone", num_form, form); if (contact_name || contact_email || contact_tel) { pappl_contact_t contact; // Contact info memset(&contact, 0, sizeof(contact)); if (contact_name) papplCopyString(contact.name, contact_name, sizeof(contact.name)); if (contact_email) papplCopyString(contact.email, contact_email, sizeof(contact.email)); if (contact_tel) papplCopyString(contact.telephone, contact_tel, sizeof(contact.telephone)); papplPrinterSetContact(printer, &contact); } } // // '_papplPrinterWebDefaults()' - Show the printer defaults web page. // void _papplPrinterWebDefaults( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { int i, j; // Looping vars pappl_pr_driver_data_t data; // Driver data const char *keyword; // Current keyword char text[256]; // Localized text for keyword const char *status = NULL; // Status message, if any bool show_source = false; // Show the media source? static const char * const orients[] = // orientation-requested strings { _PAPPL_LOC("Portrait"), _PAPPL_LOC("Landscape"), _PAPPL_LOC("Reverse Landscape"), _PAPPL_LOC("Reverse Portrait"), _PAPPL_LOC("Auto") }; static const char * const orient_svgs[] = { // orientation-requested images "%3csvg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'%3e%3crect fill='rgba(255,255,255,.5)' stroke='currentColor' stroke-width='1' x='0' y='0' width='18' height='24' rx='5' ry='5'/%3e%3ctext x='3' y='18' font-size='18' fill='currentColor' rotate='0'%3eA%3c/text%3e%3c/svg%3e", "%3csvg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'%3e%3crect fill='rgba(255,255,255,.5)' stroke='currentColor' stroke-width='1' x='0' y='0' width='18' height='24' rx='5' ry='5'/%3e%3ctext x='15' y='19' font-size='18' fill='currentColor' rotate='-90'%3eA%3c/text%3e%3c/svg%3e", "%3csvg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'%3e%3crect fill='rgba(255,255,255,.5)' stroke='currentColor' stroke-width='1' x='0' y='0' width='18' height='24' rx='5' ry='5'/%3e%3ctext x='3' y='6' font-size='18' fill='currentColor' rotate='90'%3eA%3c/text%3e%3c/svg%3e", "%3csvg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'%3e%3crect fill='rgba(255,255,255,.5)' stroke='currentColor' stroke-width='1' x='0' y='0' width='18' height='24' rx='5' ry='5'/%3e%3ctext x='15' y='7' font-size='18' fill='currentColor' rotate='180'%3eA%3c/text%3e%3c/svg%3e", "%3csvg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'%3e%3crect fill='rgba(255,255,255,.5)' stroke='currentColor' stroke-width='1' x='0' y='0' width='18' height='24' rx='5' ry='5'/%3e%3ctext x='5' y='18' font-size='18' fill='currentColor' rotate='0'%3e?%3c/text%3e%3c/svg%3e" }; if (!papplClientHTMLAuthorize(client)) return; papplPrinterGetDriverData(printer, &data); if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables int num_vendor = 0; // Number of vendor options cups_option_t *vendor = NULL; // Vendor options if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { const char *value; // Value of form variable char *end; // End of value if ((value = cupsGetOption("orientation-requested", num_form, form)) != NULL) { data.orient_default = (ipp_orient_t)strtol(value, &end, 10); if (errno == ERANGE || *end || data.orient_default < IPP_ORIENT_PORTRAIT || data.orient_default > IPP_ORIENT_NONE) data.orient_default = IPP_ORIENT_PORTRAIT; } if ((value = cupsGetOption("output-bin", num_form, form)) != NULL) { for (i = 0; i < data.num_bin; i ++) { if (!strcmp(data.bin[i], value)) { data.bin_default = i; break; } } } if ((value = cupsGetOption("print-color-mode", num_form, form)) != NULL) data.color_default = _papplColorModeValue(value); if ((value = cupsGetOption("print-content-optimize", num_form, form)) != NULL) data.content_default = _papplContentValue(value); if ((value = cupsGetOption("print-darkness", num_form, form)) != NULL) { data.darkness_configured = (int)strtol(value, &end, 10); if (errno == ERANGE || *end || data.darkness_configured < 0 || data.darkness_configured > 100) data.darkness_configured = 50; } if ((value = cupsGetOption("print-quality", num_form, form)) != NULL) data.quality_default = (ipp_quality_t)ippEnumValue("print-quality", value); if ((value = cupsGetOption("print-scaling", num_form, form)) != NULL) data.scaling_default = _papplScalingValue(value); if ((value = cupsGetOption("print-speed", num_form, form)) != NULL) { data.speed_default = (int)strtol(value, &end, 10) * 2540; if (errno == ERANGE || *end || data.speed_default < 0 || data.speed_default > data.speed_supported[1]) data.speed_default = 0; } if ((value = cupsGetOption("sides", num_form, form)) != NULL) data.sides_default = _papplSidesValue(value); if ((value = cupsGetOption("printer-resolution", num_form, form)) != NULL) { if (sscanf(value, "%dx%ddpi", &data.x_default, &data.y_default) == 1) data.y_default = data.x_default; } if ((value = cupsGetOption("media-source", num_form, form)) != NULL) { for (i = 0; i < data.num_source; i ++) { if (!strcmp(value, data.source[i])) { data.media_default = data.media_ready[i]; break; } } } for (i = 0; i < data.num_vendor; i ++) { char supattr[128]; // xxx-supported snprintf(supattr, sizeof(supattr), "%s-supported", data.vendor[i]); if ((value = cupsGetOption(data.vendor[i], num_form, form)) != NULL) num_vendor = (int)cupsAddOption(data.vendor[i], value, (cups_len_t)num_vendor, &vendor); else if (ippFindAttribute(printer->driver_attrs, supattr, IPP_TAG_BOOLEAN)) num_vendor = (int)cupsAddOption(data.vendor[i], "false", (cups_len_t)num_vendor, &vendor); } if (papplPrinterSetDriverDefaults(printer, &data, num_vendor, vendor)) status = _PAPPL_LOC("Changes saved."); else status = _PAPPL_LOC("Bad printer defaults."); cupsFreeOptions((cups_len_t)num_vendor, vendor); } cupsFreeOptions(num_form, form); } papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Printing Defaults"), 0, NULL, NULL); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPuts(client, " \n" " \n"); // media-col-default papplClientHTMLPrintf(client, " \n", printer->uriname, papplClientGetLocString(client, _PAPPL_LOC("Configure Media"))); // orientation-requested-default papplClientHTMLPrintf(client, " \n"); // print-color-mode-default papplClientHTMLPrintf(client, " \n"); if (data.sides_supported && data.sides_supported != PAPPL_SIDES_ONE_SIDED) { // sides-default papplClientHTMLPrintf(client, " \n"); } // output-bin-default if (data.num_bin > 0) { papplClientHTMLPrintf(client, " \n"); } // print-quality-default papplClientHTMLPrintf(client, " \n"); // print-darkness-configured if (data.darkness_supported) { int darkness_value = ((data.darkness_supported - 1) * data.darkness_configured + 50) / 100; // Scaled darkness value papplClientHTMLPrintf(client, " \n"); } // print-speed-default if (data.speed_supported[1]) { papplClientHTMLPrintf(client, " \n"); } // print-content-optimize-default papplClientHTMLPrintf(client, " \n"); // print-scaling-default papplClientHTMLPrintf(client, " \n"); // printer-resolution-default papplClientHTMLPrintf(client, " \n"); // Vendor options _papplRWLockRead(printer); for (i = 0; i < data.num_vendor; i ++) { char defname[128], // xxx-default name defvalue[1024], // xxx-default value supname[128]; // xxx-supported name ipp_attribute_t *defattr, // xxx-default attribute *supattr; // xxx-supported attribute int count; // Number of values snprintf(defname, sizeof(defname), "%s-default", data.vendor[i]); snprintf(supname, sizeof(defname), "%s-supported", data.vendor[i]); if ((defattr = ippFindAttribute(printer->driver_attrs, defname, IPP_TAG_ZERO)) != NULL) ippAttributeString(defattr, defvalue, sizeof(defvalue)); else defvalue[0] = '\0'; papplClientHTMLPrintf(client, " \n"); } _papplRWUnlock(printer); papplClientHTMLPrintf(client, " \n" " \n" "
%s:", papplClientGetLocString(client, "media")); if (data.num_source > 1) { papplClientHTMLPuts(client, ""); } else papplClientHTMLEscape(client, localize_media(client, data.media_ready, false, text, sizeof(text)), 0); papplClientHTMLPrintf(client, " %s
%s:", papplClientGetLocString(client, "orientation-requested")); for (i = IPP_ORIENT_PORTRAIT; i <= IPP_ORIENT_NONE; i ++) { papplClientHTMLPrintf(client, " ", i, data.orient_default == (ipp_orient_t)i ? " checked" : "", orient_svgs[i - IPP_ORIENT_PORTRAIT], orients[i - IPP_ORIENT_PORTRAIT]); } papplClientHTMLPuts(client, "
%s:", papplClientGetLocString(client, "print-color-mode")); if (data.color_supported == (PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_MONOCHROME) || data.color_supported == (PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_MONOCHROME | PAPPL_COLOR_MODE_AUTO_MONOCHROME)) { papplClientHTMLPuts(client, "B&W"); } else { for (i = PAPPL_COLOR_MODE_AUTO; i <= PAPPL_COLOR_MODE_PROCESS_MONOCHROME; i *= 2) { if ((data.color_supported & (pappl_color_mode_t)i) && i != PAPPL_COLOR_MODE_AUTO_MONOCHROME) { keyword = _papplColorModeString((pappl_color_mode_t)i); papplClientHTMLPrintf(client, " ", keyword, (pappl_color_mode_t)i == data.color_default ? " checked" : "", localize_keyword(client, "print-color-mode", keyword, text, sizeof(text))); } } } papplClientHTMLPuts(client, "
%s:", papplClientGetLocString(client, "sides")); for (i = PAPPL_SIDES_ONE_SIDED; i <= PAPPL_SIDES_TWO_SIDED_SHORT_EDGE; i *= 2) { if (data.sides_supported & (pappl_sides_t)i) { keyword = _papplSidesString((pappl_sides_t)i); papplClientHTMLPrintf(client, " ", keyword, (pappl_sides_t)i == data.sides_default ? " checked" : "", localize_keyword(client, "sides", keyword, text, sizeof(text))); } } papplClientHTMLPuts(client, "
%s:", papplClientGetLocString(client, "output-bin")); if (data.num_bin > 1) { papplClientHTMLPuts(client, ""); } else { papplClientHTMLPrintf(client, "%s", localize_keyword(client, "output-bin", data.bin[data.bin_default], text, sizeof(text))); } papplClientHTMLPuts(client, "
%s:", papplClientGetLocString(client, "print-quality")); for (i = IPP_QUALITY_DRAFT; i <= IPP_QUALITY_HIGH; i ++) { keyword = ippEnumString("print-quality", i); papplClientHTMLPrintf(client, " ", keyword, (ipp_quality_t)i == data.quality_default ? " checked" : "", localize_keyword(client, "print-quality", keyword, text, sizeof(text))); } papplClientHTMLPuts(client, "
%s:
%s:
%s:
%s:
%s:", papplClientGetLocString(client, "printer-resolution")); if (data.num_resolution == 1) { if (data.x_resolution[0] != data.y_resolution[0]) papplClientHTMLPrintf(client, papplClientGetLocString(client, _PAPPL_LOC("%dx%ddpi")), data.x_resolution[0], data.y_resolution[0]); else papplClientHTMLPrintf(client, papplClientGetLocString(client, _PAPPL_LOC("%ddpi")), data.x_resolution[0]); } else { papplClientHTMLPuts(client, ""); } papplClientHTMLPuts(client, "
%s:", papplClientGetLocString(client, data.vendor[i])); if ((supattr = ippFindAttribute(printer->driver_attrs, supname, IPP_TAG_ZERO)) != NULL) { count = (int)ippGetCount(supattr); switch (ippGetValueTag(supattr)) { case IPP_TAG_BOOLEAN : papplClientHTMLPrintf(client, "", data.vendor[i], !strcmp(defvalue, "true") ? " checked" : ""); break; case IPP_TAG_INTEGER : papplClientHTMLPrintf(client, ""); break; case IPP_TAG_RANGE : { int upper, lower = ippGetRange(supattr, 0, &upper); // Range papplClientHTMLPrintf(client, "", data.vendor[i], lower, upper, defvalue); } break; case IPP_TAG_KEYWORD : papplClientHTMLPrintf(client, ""); break; default : papplClientHTMLPuts(client, "Unsupported value syntax."); break; } } else { // Text option papplClientHTMLPrintf(client, "", data.vendor[i], defvalue); } papplClientHTMLPuts(client, "
" " \n", papplClientGetLocString(client, _PAPPL_LOC("Save Changes"))); papplClientHTMLPrinterFooter(client); } // // '_papplPrinterWebDelete()' - Show the printer delete confirmation web page. // void _papplPrinterWebDelete( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { const char *status = NULL; // Status message, if any if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if (printer->processing_job) { // Printer is processing a job... status = _PAPPL_LOC("Printer is currently active."); } else { if (!papplPrinterIsDeleted(printer)) { papplPrinterDelete(printer); printer = NULL; } papplClientRespondRedirect(client, HTTP_STATUS_FOUND, "/"); cupsFreeOptions(num_form, form); return; } cupsFreeOptions(num_form, form); } papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Delete Printer"), 0, NULL, NULL); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client," ", papplClientGetLocString(client, _PAPPL_LOC("Confirm Delete Printer"))); papplClientHTMLFooter(client); } // // '_papplPrinterWebHome()' - Show the printer home page. // void _papplPrinterWebHome( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { const char *status = NULL; // Status text, if any ipp_pstate_t printer_state; // Printer state char edit_path[1024]; // Edit configuration URL const int limit = 20; // Jobs per page int job_index = 1; // Job index char dns_sd_name[64], // Printer DNS-SD name location[128], // Printer location geo_location[128], // Printer geo-location organization[256], // Printer organization org_unit[256]; // Printer organizational unit pappl_contact_t contact; // Printer contact // Save current printer state... printer_state = papplPrinterGetState(printer); // Handle POSTs to print a test page... if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables const char *action; // Form action if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if ((action = cupsGetOption("action", num_form, form)) == NULL) { status = _PAPPL_LOC("Missing action."); } else if (!strcmp(action, "hold-new-jobs")) { papplPrinterHoldNewJobs(printer); status = _PAPPL_LOC("Holding new jobs."); } else if (!strcmp(action, "identify-printer")) { if (printer->driver_data.identify_supported && printer->driver_data.identify_cb) { (printer->driver_data.identify_cb)(printer, printer->driver_data.identify_supported, "Hello."); status = _PAPPL_LOC("Printer identified."); } else { status = _PAPPL_LOC("Unable to identify printer."); } } else if (!strcmp(action, "print-test-page")) { pappl_job_t *job; // New job const char *filename, // Test Page filename *username; // Username char buffer[1024]; // File Buffer // Get the testfile to print, if any... if (printer->driver_data.testpage_cb) filename = (printer->driver_data.testpage_cb)(printer, buffer, sizeof(buffer)); else filename = NULL; if (filename) { // Have a file to print, so create a job and print it... if (client->username[0]) username = client->username; else username = "guest"; if (access(filename, R_OK)) { status = _PAPPL_LOC("Unable to access test print file."); } else if ((job = _papplJobCreate(printer, 0, username, NULL, "Test Page", NULL)) == NULL) { status = _PAPPL_LOC("Unable to create test print job."); } else { // Submit the job for processing... _papplJobSubmitFile(job, filename); status = _PAPPL_LOC("Test page printed."); printer_state = IPP_PSTATE_PROCESSING; } } else { status = _PAPPL_LOC("Test page printed."); printer_state = IPP_PSTATE_PROCESSING; } } else if (!strcmp(action, "pause-printer")) { papplPrinterPause(printer); if (printer->state == IPP_PSTATE_STOPPED) status = _PAPPL_LOC("Printer paused."); else status = _PAPPL_LOC("Printer pausing."); } else if (!strcmp(action, "release-held-new-jobs")) { papplPrinterReleaseHeldNewJobs(printer, client->username); status = _PAPPL_LOC("Released held new jobs."); } else if (!strcmp(action, "resume-printer")) { papplPrinterResume(printer); status = _PAPPL_LOC("Printer resuming."); } else if (!strcmp(action, "set-as-default")) { papplSystemSetDefaultPrinterID(printer->system, printer->printer_id); status = _PAPPL_LOC("Default printer set."); } else status = _PAPPL_LOC("Unknown action."); cupsFreeOptions(num_form, form); } // Show status... papplClientHTMLPrinterHeader(client, printer, NULL, printer_state == IPP_PSTATE_PROCESSING ? 10 : 0, NULL, NULL); papplClientHTMLPuts(client, "
\n" "
\n"); _papplPrinterWebIteratorCallback(printer, client); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); snprintf(edit_path, sizeof(edit_path), "%s/config", printer->uriname); papplClientHTMLPrintf(client, "

%s %s

\n", papplClientGetLocString(client, _PAPPL_LOC("Configuration")), _papplClientGetAuthWebScheme(client), client->host_field, client->host_port, edit_path, papplClientGetLocString(client, _PAPPL_LOC("Change"))); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_CONFIGURATION); _papplClientHTMLInfo(client, false, papplPrinterGetDNSSDName(printer, dns_sd_name, sizeof(dns_sd_name)), papplPrinterGetLocation(printer, location, sizeof(location)), papplPrinterGetGeoLocation(printer, geo_location, sizeof(geo_location)), papplPrinterGetOrganization(printer, organization, sizeof(organization)), papplPrinterGetOrganizationalUnit(printer, org_unit, sizeof(org_unit)), papplPrinterGetContact(printer, &contact)); if (!(printer->system->options & PAPPL_SOPTIONS_MULTI_QUEUE)) _papplSystemWebSettings(client); papplClientHTMLPrintf(client, "
\n" "
\n" "

%s", printer->uriname, papplClientGetLocString(client, _PAPPL_LOC("Jobs"))); if (papplPrinterGetNumberOfJobs(printer) > 0) { if (cupsArrayGetCount(printer->active_jobs) > 0) papplClientHTMLPrintf(client, " %s

\n", _papplClientGetAuthWebScheme(client), client->host_field, client->host_port, printer->uriname, papplClientGetLocString(client, _PAPPL_LOC("Cancel All Jobs"))); else papplClientHTMLPuts(client, "\n"); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_JOB); job_pager(client, printer, job_index, limit); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Job #")), papplClientGetLocString(client, _PAPPL_LOC("Name")), papplClientGetLocString(client, _PAPPL_LOC("Owner")), papplClientGetLocString(client, _PAPPL_LOC("Pages")), papplClientGetLocString(client, _PAPPL_LOC("Status"))); papplPrinterIterateAllJobs(printer, (pappl_job_cb_t)job_cb, client, job_index, limit); papplClientHTMLPuts(client, " \n" "
%s%s%s%s%s
\n"); job_pager(client, printer, job_index, limit); } else { papplClientHTMLPuts(client, "\n"); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_JOB); papplClientHTMLPrintf(client, "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("No jobs in history."))); } papplClientHTMLPrinterFooter(client); } // // '_papplPrinterWebIteratorCallback()' - Show the printer status. // void _papplPrinterWebIteratorCallback( pappl_printer_t *printer, // I - Printer pappl_client_t *client) // I - Client { pappl_preason_t reason, // Current reason printer_reasons;// Printer state reasons ipp_pstate_t printer_state; // Printer state int printer_jobs; // Number of queued jobs char state_str[8], // State string jobs_str[256], // Number of jobs string uri[256], // Form URI text[1024]; // Localized text printer_jobs = papplPrinterGetNumberOfActiveJobs(printer); printer_state = papplPrinterGetState(printer); printer_reasons = papplPrinterGetReasons(printer); snprintf(uri, sizeof(uri), "%s/", printer->uriname); if (!strcmp(client->uri, "/") && (client->system->options & PAPPL_SOPTIONS_MULTI_QUEUE)) papplClientHTMLPrintf(client, "

%s %s

\n", printer->uriname, printer->name, _papplClientGetAuthWebScheme(client), client->host_field, client->host_port, printer->uriname, papplClientGetLocString(client, _PAPPL_LOC("Delete"))); else papplClientHTMLPrintf(client, "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("Status"))); snprintf(state_str, sizeof(state_str), "%d", (int)printer_state); papplLocFormatString(papplClientGetLoc(client), jobs_str, sizeof(jobs_str), printer_jobs == 1 ? _PAPPL_LOC("%d job") : _PAPPL_LOC("%d jobs"), printer_jobs); papplClientHTMLPrintf(client, "

%s, %s", ippEnumString("printer-state", (int)printer_state), printer->uriname, localize_keyword(client, "printer-state", state_str, text, sizeof(text)), jobs_str); if ((printer->system->options & PAPPL_SOPTIONS_MULTI_QUEUE) && printer->printer_id == papplSystemGetDefaultPrinterID(printer->system)) papplClientHTMLPrintf(client, ", %s", papplClientGetLocString(client, _PAPPL_LOC("default printer"))); if (printer->hold_new_jobs) papplClientHTMLPrintf(client, ", %s", papplClientGetLocString(client, _PAPPL_LOC("holding new jobs"))); for (reason = PAPPL_PREASON_OTHER; reason <= PAPPL_PREASON_TONER_LOW; reason *= 2) { if (printer_reasons & reason) papplClientHTMLPrintf(client, ", %s", localize_keyword(client, "printer-state-reasons", _papplPrinterReasonString(reason), text, sizeof(text))); } if (strcmp(printer->name, printer->driver_data.make_and_model)) papplClientHTMLPrintf(client, ".
%s

\n", printer->driver_data.make_and_model); else papplClientHTMLPuts(client, ".

\n"); papplClientHTMLPuts(client, "
"); _papplClientHTMLPutLinks(client, printer->links, PAPPL_LOPTIONS_STATUS); if (!printer->hold_new_jobs && papplPrinterGetMaxActiveJobs(printer) != 1) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Hold New Jobs"))); } if (printer->driver_data.identify_supported) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Identify Printer"))); } if (printer->driver_data.testpage_cb) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Print Test Page"))); } if (printer->hold_new_jobs && papplPrinterGetMaxActiveJobs(printer) != 1) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Release Held New Jobs"))); } if (printer->system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { if (printer->state == IPP_PSTATE_STOPPED) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Resume Printing"))); } else { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Pause Printing"))); } if (printer->printer_id != printer->system->default_printer_id) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplClientGetLocString(client, _PAPPL_LOC("Set as Default"))); } } if (strcmp(client->uri, "/") && (client->system->options & PAPPL_SOPTIONS_MULTI_QUEUE)) papplClientHTMLPrintf(client, " %s", _papplClientGetAuthWebScheme(client), client->host_field, client->host_port, printer->uriname, papplClientGetLocString(client, _PAPPL_LOC("Delete Printer"))); papplClientHTMLPuts(client, "
\n"); } // // '_papplPrinterWebJobs()' - Show the printer jobs web page. // void _papplPrinterWebJobs( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { ipp_pstate_t printer_state; // Printer state int job_index = 1, // Job index limit = 20; // Jobs per page const char *status = NULL; // Status message bool refresh; // Refresh the window? if (!papplClientHTMLAuthorize(client)) return; printer_state = papplPrinterGetState(printer); refresh = printer_state == IPP_PSTATE_PROCESSING; if (client->operation == HTTP_STATE_GET) { cups_option_t *form = NULL; // Form variables cups_len_t num_form = (cups_len_t)papplClientGetForm(client, &form); // Number of form variables const char *value = NULL; // Value of form variable if ((value = cupsGetOption("job-index", num_form, form)) != NULL) job_index = (int)strtol(value, NULL, 10); cupsFreeOptions(num_form, form); } else if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables const char *value; // Value of form variable int job_id = 0; // Job ID to cancel pappl_job_t *job; // Job to cancel const char *action; // Form action if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if ((value = cupsGetOption("job-id", num_form, form)) != NULL) { char *end; // End of value job_id = (int)strtol(value, &end, 10); if (errno == ERANGE || *end) { status = _PAPPL_LOC("Invalid job ID."); } else if ((job = papplPrinterFindJob(printer, job_id)) != NULL) { const char *username; // Username if (client->username[0]) username = client->username; else username = "guest"; if ((action = cupsGetOption("action", num_form, form)) == NULL) { status = _PAPPL_LOC("Missing action."); } else if (!strcmp(action, "cancel-job")) { papplJobCancel(job); status = _PAPPL_LOC("Job canceled."); } else if (!strcmp(action, "hold-job")) { papplJobHold(job, username, "indefinite", 0); status = _PAPPL_LOC("Job held."); } else if (!strcmp(action, "release-job")) { papplJobRelease(job, username); status = _PAPPL_LOC("Job released."); refresh = true; } else if (!strcmp(action, "reprint-job")) { // Copy the job... pappl_job_t *new_job; // New job if ((new_job = _papplJobCreate(printer, 0, username, job->format, job->name, job->attrs)) != NULL) { // Copy the job file... int oldfd, // Old job file newfd; // New job file char filename[1024], // Job filename buffer[8192]; // Copy buffer ssize_t bytes; // Bytes read... if ((oldfd = open(job->filename, O_RDONLY | O_BINARY)) >= 0) { if ((newfd = papplJobOpenFile(new_job, filename, sizeof(filename), printer->system->directory, NULL, "w")) >= 0) { while ((bytes = read(oldfd, buffer, sizeof(buffer))) > 0) write(newfd, buffer, (size_t)bytes); close(oldfd); close(newfd); // Submit the job for processing... _papplJobSubmitFile(new_job, filename); status = _PAPPL_LOC("Reprinted job."); refresh = true; } close(oldfd); } } if (!status) status = _PAPPL_LOC("Unable to copy print job."); } else { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "action='%s'", action); status = _PAPPL_LOC("Unknown action."); } } else { status = _PAPPL_LOC("Invalid Job ID."); } } else { status = _PAPPL_LOC("Missing job ID."); } cupsFreeOptions(num_form, form); } if (cupsArrayGetCount(printer->active_jobs) > 0) { char url[1024]; // URL for Cancel All Jobs httpAssembleURIf(HTTP_URI_CODING_ALL, url, sizeof(url), "https", NULL, client->host_field, client->host_port, "%s/cancelall", printer->uriname); papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Jobs"), refresh ? 10 : 0, _PAPPL_LOC("Cancel All Jobs"), url); } else { papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Jobs"), printer_state == IPP_PSTATE_PROCESSING ? 10 : 0, NULL, NULL); } if (status) papplClientHTMLPrintf(client, "
\n" "
\n" "
%s
\n" "
\n" "
\n", papplClientGetLocString(client, status)); if (papplPrinterGetNumberOfJobs(printer) > 0) { job_pager(client, printer, job_index, limit); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Job #")), papplClientGetLocString(client, _PAPPL_LOC("Name")), papplClientGetLocString(client, _PAPPL_LOC("Owner")), papplClientGetLocString(client, _PAPPL_LOC("Pages Completed")), papplClientGetLocString(client, _PAPPL_LOC("Status"))); papplPrinterIterateAllJobs(printer, (pappl_job_cb_t)job_cb, client, job_index, limit); papplClientHTMLPuts(client, " \n" "
%s%s%s%s%s
\n"); job_pager(client, printer, job_index, limit); } else papplClientHTMLPrintf(client, "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("No jobs in history."))); papplClientHTMLPrinterFooter(client); } // // '_papplPrinterWebMedia()' - Show the printer media web page. // void _papplPrinterWebMedia( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { int i; // Looping var pappl_pr_driver_data_t data; // Driver data char name[32], // Prefix (readyN) text[256]; // Localized media-source name const char *status = NULL; // Status message, if any if (!papplClientHTMLAuthorize(client)) return; papplPrinterGetDriverData(printer, &data); if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { pwg_media_t *pwg = NULL; // PWG media info pappl_media_col_t *ready; // Current ready media const char *value, // Value of form variable *custom_width, // Custom media width *custom_length, // Custom media length *custom_units; // Custom media units memset(data.media_ready, 0, sizeof(data.media_ready)); for (i = 0, ready = data.media_ready; i < data.num_source; i ++, ready ++) { // size snprintf(name, sizeof(name), "ready%d-size", i); if ((value = cupsGetOption(name, num_form, form)) == NULL) continue; if (!strcmp(value, "custom")) { // Custom size... snprintf(name, sizeof(name), "ready%d-custom-width", i); custom_width = cupsGetOption(name, num_form, form); snprintf(name, sizeof(name), "ready%d-custom-length", i); custom_length = cupsGetOption(name, num_form, form); snprintf(name, sizeof(name), "ready%d-custom-units", i); custom_units = cupsGetOption(name, num_form, form); if (custom_width && custom_length && custom_units) { if (!strcmp(custom_units, "in")) pwg = pwgMediaForSize((int)(2540.0 * strtod(custom_width, NULL)), (int)(2540.0 * strtod(custom_length, NULL))); else pwg = pwgMediaForSize((int)(100.0 * strtod(custom_width, NULL)), (int)(100.0 * strtod(custom_length, NULL))); } } else { // Standard size... pwg = pwgMediaForPWG(value); } papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s='%s',%d,%d", name, pwg ? pwg->pwg : "unknown", pwg ? pwg->width : 0, pwg ? pwg->length : 0); if (pwg) { papplCopyString(ready->size_name, pwg->pwg, sizeof(ready->size_name)); ready->size_width = pwg->width; ready->size_length = pwg->length; } // source papplCopyString(ready->source, data.source[i], sizeof(ready->source)); // margins snprintf(name, sizeof(name), "ready%d-borderless", i); if (cupsGetOption(name, num_form, form)) { ready->bottom_margin = ready->top_margin = 0; ready->left_margin = ready->right_margin = 0; } else { ready->bottom_margin = ready->top_margin = data.bottom_top; ready->left_margin = ready->right_margin = data.left_right; } // left-offset snprintf(name, sizeof(name), "ready%d-left-offset", i); if ((value = cupsGetOption(name, num_form, form)) != NULL) ready->left_offset = (int)(100.0 * strtod(value, NULL)); // top-offset snprintf(name, sizeof(name), "ready%d-top-offset", i); if ((value = cupsGetOption(name, num_form, form)) != NULL) ready->top_offset = (int)(100.0 * strtod(value, NULL)); // tracking snprintf(name, sizeof(name), "ready%d-tracking", i); if ((value = cupsGetOption(name, num_form, form)) != NULL) ready->tracking = _papplMediaTrackingValue(value); // type snprintf(name, sizeof(name), "ready%d-type", i); if ((value = cupsGetOption(name, num_form, form)) != NULL) papplCopyString(ready->type, value, sizeof(ready->type)); } papplPrinterSetReadyMedia(printer, data.num_source, data.media_ready); status = _PAPPL_LOC("Changes saved."); } cupsFreeOptions(num_form, form); } papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Media"), 0, NULL, NULL); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPuts(client, " \n" " \n"); for (i = 0; i < data.num_source; i ++) { if (!strcmp(data.source[i], "manual")) continue; snprintf(name, sizeof(name), "ready%d", i); media_chooser(client, &data, localize_keyword(client, "media-source", data.source[i], text, sizeof(text)), name, data.media_ready + i); } papplClientHTMLPrintf(client, " \n" " \n" "
" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Save Changes"))); papplClientHTMLPrinterFooter(client); } // // '_papplPrinterWebSupplies()' - Show the printer supplies web page. // void _papplPrinterWebSupplies( pappl_client_t *client, // I - Client pappl_printer_t *printer) // I - Printer { int i, // Looping var num_supply; // Number of supplies pappl_supply_t supply[100]; // Supplies static const char * const backgrounds[] = { "url(data:image/png;base64," "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c" "6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAAB" "AAEAAKACAAQAAAABAAAADKADAAQAAAABAAAADAAAAAATDPpdAAAAaUlEQVQo" "FY2R0Q3AIAhEa7siCet0HeKQtGeiwWKR+wH0HWAsRKTHK2ZGWEpExvmJLAuD" "LbXWNgHFV7Zzv2sTemHjCsYmS8MfjIbOEMHOsIMnQwYehiwMw6WqNxKr6F/c" "oyMYm0yGHYwtHq4fKZD9DnawAAAAAElFTkSuQmCC)", // no-color "#222", // black - not 100% black for dark mode UI "#0FF", // cyan "#777", // gray "#0C0", // green "#7FF", // light-cyan "#CCC", // light-gray "#FCF", // light-magenta "#F0F", // magenta "#F70", // orange "#707", // violet "#FF0" // yellow }; num_supply = papplPrinterGetSupplies(printer, (int)(sizeof(supply) / sizeof(supply[0])), supply); papplClientHTMLPrinterHeader(client, printer, _PAPPL_LOC("Supplies"), 0, NULL, NULL); papplClientHTMLPuts(client, " \n" " \n" " \n" " \n" " \n"); for (i = 0; i < num_supply; i ++) { papplClientHTMLPrintf(client, "\n", supply[i].description, backgrounds[supply[i].color], supply[i].level * 0.5, supply[i].level, 50.0 - supply[i].level * 0.5, supply[i].level); } papplClientHTMLPuts(client, " \n" " \n" " \n" " \n" "
%s
\n"); papplClientHTMLPrinterFooter(client); } // // 'job_cb()' - Job iterator callback. // static void job_cb(pappl_job_t *job, // I - Job pappl_client_t *client) // I - Client { bool show_cancel = false, // Show the "cancel" button? show_hold = false, // Show the "hold" button? show_release = false; // Show the "release" button? char uri[256], // Form URI when[256], // When job queued/started/finished hhmmss[64]; // Time HH:MM:SS snprintf(uri, sizeof(uri), "%s/jobs", job->printer->uriname); switch (papplJobGetState(job)) { case IPP_JSTATE_PENDING : show_cancel = true; show_hold = papplPrinterGetMaxActiveJobs(papplJobGetPrinter(job)) != 1; papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Queued %s"), time_string(client, papplJobGetTimeCreated(job), hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_HELD : show_cancel = true; show_release = true; papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Queued %s"), time_string(client, papplJobGetTimeCreated(job), hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_PROCESSING : case IPP_JSTATE_STOPPED : if (papplJobIsCanceled(job)) { papplCopyString(when, papplClientGetLocString(client, _PAPPL_LOC("Canceling")), sizeof(when)); } else { show_cancel = true; papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Started %s"), time_string(client, papplJobGetTimeProcessed(job), hhmmss, sizeof(hhmmss))); } break; case IPP_JSTATE_ABORTED : papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Aborted %s"), time_string(client, papplJobGetTimeCompleted(job), hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_CANCELED : papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Canceled %s"), time_string(client, papplJobGetTimeCompleted(job), hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_COMPLETED : papplLocFormatString(papplClientGetLoc(client), when, sizeof(when), _PAPPL_LOC("Completed %s"), time_string(client, papplJobGetTimeCompleted(job), hhmmss, sizeof(hhmmss))); break; } papplClientHTMLPrintf(client, " %d%s%s%d%s", papplJobGetID(job), papplJobGetName(job), papplJobGetUsername(job), papplJobGetImpressionsCompleted(job), when); if (show_cancel) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplJobGetID(job), papplClientGetLocString(client, _PAPPL_LOC("Cancel Job"))); } if (show_hold) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplJobGetID(job), papplClientGetLocString(client, _PAPPL_LOC("Hold Job"))); } if (show_release) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplJobGetID(job), papplClientGetLocString(client, _PAPPL_LOC("Release Job"))); } if (papplJobGetState(job) >= IPP_JSTATE_ABORTED && job->filename) { papplClientHTMLStartForm(client, uri, false); papplClientHTMLPrintf(client, "", papplJobGetID(job), papplClientGetLocString(client, _PAPPL_LOC("Reprint Job"))); } papplClientHTMLPuts(client, "\n"); } // // 'job_pager()' - Show the job paging links. // static void job_pager(pappl_client_t *client, // I - Client pappl_printer_t *printer, // I - Printer int job_index, // I - First job shown (1-based) int limit) // I - Maximum jobs shown { int num_jobs = 0, // Number of jobs num_pages = 0, // Number of pages i, // Looping var page = 0; // Current page char path[1024]; // resource path if ((num_jobs = papplPrinterGetNumberOfJobs(printer)) <= limit) return; num_pages = (num_jobs + limit - 1) / limit; page = (job_index - 1) / limit; snprintf(path, sizeof(path), "%s/jobs", printer->uriname); papplClientHTMLPuts(client, "
"); if (page > 0) papplClientHTMLPrintf(client, "«", path, (page - 1) * limit + 1); for (i = 0; i < num_pages; i ++) { if (i == page) papplClientHTMLPrintf(client, " %d", i + 1); else papplClientHTMLPrintf(client, " %d", path, i * limit + 1, i + 1); } if (page < (num_pages - 1)) papplClientHTMLPrintf(client, " »", path, (page + 1) * limit + 1); papplClientHTMLPuts(client, "
\n"); } // // 'localize_keyword()' - Localize a media keyword... // static char * // O - Localized string localize_keyword( pappl_client_t *client, // I - Client const char *attrname, // I - Attribute name const char *keyword, // I - Keyword string char *buffer, // I - String buffer size_t bufsize) // I - String buffer size { char pair[1024]; // attribute.keyword/enum pair const char *locpair; // Localized pair char *ptr; // Pointer into string // Try looking up the attribute.keyword/enum pair first... snprintf(pair, sizeof(pair), "%s.%s", attrname, keyword); locpair = papplClientGetLocString(client, pair); if (strcmp(pair, locpair)) { // Have it, copy the localized string... papplCopyString(buffer, locpair, bufsize); } else if (!strcmp(attrname, "media")) { // Show dimensional media size... pwg_media_t *pwg = pwgMediaForPWG(keyword); // PWG media size info if ((pwg->width % 100) == 0 && (pwg->width % 2540) != 0) papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC(/*Media size in millimeters*/"%d x %dmm"), pwg->width / 100, pwg->length / 100); else papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC(/*Media size in inches*/"%g x %g\""), pwg->width / 2540.0, pwg->length / 2540.0); } else { // No localization, just capitalize the hyphenated words... papplCopyString(buffer, keyword, bufsize); *buffer = (char)toupper(*buffer & 255); for (ptr = buffer + 1; *ptr; ptr ++) { if (*ptr == '-' && ptr[1]) { *ptr++ = ' '; *ptr = (char)toupper(*ptr & 255); } } } return (buffer); } // // 'localize_media()' - Localize media-col information. // static char * // O - Localized description of the media localize_media( pappl_client_t *client, // I - Client pappl_media_col_t *media, // I - Media info bool include_source, // I - Include the media source? char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char size[128], // Size name string source[128], // Source string type[128]; // Type string const char *borderless; // Borderless qualifier if (!media->size_name[0]) papplCopyString(size, papplClientGetLocString(client, _PAPPL_LOC("Unknown")), sizeof(size)); else localize_keyword(client, "media", media->size_name, size, sizeof(size)); if (!media->type[0]) papplCopyString(type, papplClientGetLocString(client, _PAPPL_LOC("Unknown")), sizeof(type)); else localize_keyword(client, "media-type", media->type, type, sizeof(type)); if (!media->left_margin && !media->right_margin && !media->top_margin && !media->bottom_margin) borderless = papplClientGetLocString(client, _PAPPL_LOC(", Borderless")); else borderless = ""; if (include_source) papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC(/*size (type+borderless) from source/tray*/"%s (%s%s) from %s"), size, type, borderless, localize_keyword(client, "media-source", media->source, source, sizeof(source))); else papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC(/*size (type+borderless)*/"%s (%s%s)"), size, type, borderless); return (buffer); } // // 'media_chooser()' - Show the media chooser. // static void media_chooser( pappl_client_t *client, // I - Client pappl_pr_driver_data_t *driver_data,// I - Driver data const char *title, // I - Label/title const char *name, // I - Base name pappl_media_col_t *media) // I - Current media values { int i, // Looping var cur_index = 0, // Current size index sel_index = 0; // Selected size index... pwg_media_t *pwg; // PWG media size info char text[256]; // Human-readable value/text const char *min_size = NULL, // Minimum size *max_size = NULL; // Maximum size // media-size papplLocFormatString(papplClientGetLoc(client), text, sizeof(text), _PAPPL_LOC(/*Source/Tray Media*/"%s Media"), title); papplClientHTMLPrintf(client, " %s:", text); for (i = 0; i < driver_data->num_media && (!min_size || !max_size); i ++) { if (!strncmp(driver_data->media[i], "custom_", 7) || !strncmp(driver_data->media[i], "roll_", 5)) { if (strstr(driver_data->media[i], "_min_")) min_size = driver_data->media[i]; else if (strstr(driver_data->media[i], "_max_")) max_size = driver_data->media[i]; } } if (min_size && max_size) { papplClientHTMLPrintf(client, "", name); for (i = 0; i < driver_data->num_media; i ++) { if (!strncmp(driver_data->media[i], "custom_", 7) || !strncmp(driver_data->media[i], "roll_", 5)) { if (strstr(driver_data->media[i], "_min_")) min_size = driver_data->media[i]; else if (strstr(driver_data->media[i], "_max_")) max_size = driver_data->media[i]; continue; } if (!strcmp(driver_data->media[i], media->size_name)) sel_index = cur_index; papplClientHTMLPrintf(client, "", driver_data->media[i], sel_index == cur_index ? " selected" : "", localize_keyword(client, "media", driver_data->media[i], text, sizeof(text))); cur_index ++; } if (min_size && max_size) { int cur_width, min_width, max_width;// Current/min/max width int cur_length, min_length, max_length; // Current/min/max length const char *cur_units; // Current units if ((pwg = pwgMediaForPWG(min_size)) != NULL) { min_width = pwg->width; min_length = pwg->length; } else { min_width = 1 * 2540; min_length = 1 * 2540; } if ((pwg = pwgMediaForPWG(max_size)) != NULL) { max_width = pwg->width; max_length = pwg->length; } else { max_width = 9 * 2540; max_length = 22 * 2540; } if ((cur_width = media->size_width) < min_width) cur_width = min_width; else if (cur_width > max_width) cur_width = max_width; if ((cur_length = media->size_length) < min_length) cur_length = min_length; else if (cur_length > max_length) cur_length = max_length; if ((cur_units = media->size_name + strlen(media->size_name) - 2) < media->size_name) cur_units = "in"; if (!strcmp(cur_units, "mm")) papplClientHTMLPrintf(client, "
x
\n", sel_index == 0 ? "inline-block" : "none", name, name, min_width / 2540.0, max_width / 100.0, cur_width / 100.0, papplClientGetLocString(client, _PAPPL_LOC("Width")), name, min_length / 2540.0, max_length / 100.0, cur_length / 100.0, papplClientGetLocString(client, _PAPPL_LOC("Height")), name, name, name, name, name, name); else papplClientHTMLPrintf(client, "
x
\n", sel_index == 0 ? "inline-block" : "none", name, name, min_width / 2540.0, max_width / 100.0, cur_width / 2540.0, papplClientGetLocString(client, _PAPPL_LOC("Width")), name, min_length / 2540.0, max_length / 100.0, cur_length / 2540.0, papplClientGetLocString(client, _PAPPL_LOC("Height")), name, name, name, name, name, name); } else papplClientHTMLPuts(client, "\n"); if (driver_data->borderless) { papplClientHTMLPrintf(client, "  %s\n", name, (!media->bottom_margin && !media->left_margin && !media->right_margin && !media->top_margin) ? " checked" : "", papplClientGetLocString(client, _PAPPL_LOC("Borderless"))); } // media-left/top-offset (if needed) if (driver_data->left_offset_supported[1] || driver_data->top_offset_supported[1]) { papplClientHTMLPrintf(client, " %s ", papplClientGetLocString(client, _PAPPL_LOC("Offset"))); if (driver_data->left_offset_supported[1]) { papplClientHTMLPrintf(client, "", name, driver_data->left_offset_supported[0] / 100.0, driver_data->left_offset_supported[1] / 100.0, media->left_offset / 100.0); if (driver_data->top_offset_supported[1]) papplClientHTMLPuts(client, " x "); } if (driver_data->top_offset_supported[1]) papplClientHTMLPrintf(client, "", name, driver_data->top_offset_supported[0] / 100.0, driver_data->top_offset_supported[1] / 100.0, media->top_offset / 100.0); papplClientHTMLPuts(client, " mm\n"); } // media-tracking (if needed) if (driver_data->tracking_supported) { papplClientHTMLPrintf(client, " \n"); } // media-type papplClientHTMLPrintf(client, " \n"); } // // 'time_string()' - Return the local time in hours, minutes, and seconds. // static char * // O - Formatted time string time_string(pappl_client_t *client, // I - Client time_t tv, // I - Time value char *buffer, // I - Buffer size_t bufsize) // I - Size of buffer { struct tm date; // Local time and date time_t age; // How old is the time? // Get the local time in hours, minutes, and seconds... localtime_r(&tv, &date); // See how long ago this was... age = time(NULL) - tv; // Format based on the age... if (age < 86400) papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC("at %02d:%02d:%02d"), date.tm_hour, date.tm_min, date.tm_sec); else if (age < (2 * 86400)) papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC("yesterday at %02d:%02d:%02d"), date.tm_hour, date.tm_min, date.tm_sec); else if (age < (31 * 86400)) papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC("%d days ago at %02d:%02d:%02d"), (int)(age / 86400), date.tm_hour, date.tm_min, date.tm_sec); else papplLocFormatString(papplClientGetLoc(client), buffer, bufsize, _PAPPL_LOC("%04d-%02d-%02d at %02d:%02d:%02d"), date.tm_year + 1900, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec); // Return the formatted string... return (buffer); } pappl-1.4.9/pappl/printer.c000066400000000000000000000752251476704353100156310ustar00rootroot00000000000000// // Printer object for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static int compare_active_jobs(pappl_job_t *a, pappl_job_t *b); static int compare_all_jobs(pappl_job_t *a, pappl_job_t *b); static int compare_completed_jobs(pappl_job_t *a, pappl_job_t *b); // // 'papplPrinterCancelAllJobs()' - Cancel all jobs on the printer. // // This function cancels all jobs on the printer. If any job is currently being // printed, it will be stopped at a convenient time (usually the end of a page) // so that the printer will be left in a known state. // void papplPrinterCancelAllJobs( pappl_printer_t *printer) // I - Printer { pappl_job_t *job; // Job information // Loop through all jobs and cancel them. // // Since we have a writer lock, it is safe to use cupsArrayGetFirst/Last... _papplRWLockWrite(printer); for (job = (pappl_job_t *)cupsArrayGetFirst(printer->active_jobs); job; job = (pappl_job_t *)cupsArrayGetNext(printer->active_jobs)) { // Cancel this job... if (job->state == IPP_JSTATE_PROCESSING || (job->state == IPP_JSTATE_HELD && job->fd >= 0)) { job->is_canceled = true; } else { job->state = IPP_JSTATE_CANCELED; job->completed = time(NULL); _papplJobRemoveFile(job); cupsArrayRemove(printer->active_jobs, job); cupsArrayAdd(printer->completed_jobs, job); } } _papplRWUnlock(printer); if (!printer->system->clean_time) printer->system->clean_time = time(NULL) + 60; } // // 'papplPrinterCreate()' - Create a new printer. // // This function creates a new printer (service) on the specified system. The // "type" argument specifies the type of service to create and must currently // be the value `PAPPL_SERVICE_TYPE_PRINT`. // // The "printer_id" argument specifies a positive integer identifier that is // unique to the system. If you specify a value of `0` a new identifier will // be assigned. // // The "driver_name" argument specifies a named driver for the printer, from // the list of drivers registered with the @link papplSystemSetPrinterDrivers@ // function. // // The "device_id" and "device_uri" arguments specify the IEEE-1284 device ID // and device URI strings for the printer. // // On error, this function sets the `errno` variable to one of the following // values: // // - `EEXIST`: A printer with the specified name already exists. // - `EINVAL`: Bad values for the arguments were specified. // - `EIO`: The driver callback failed. // - `ENOENT`: No driver callback has been set. // - `ENOMEM`: Ran out of memory. // pappl_printer_t * // O - Printer or `NULL` on error papplPrinterCreate( pappl_system_t *system, // I - System int printer_id, // I - printer-id value or `0` for new const char *printer_name, // I - Human-readable printer name const char *driver_name, // I - Driver name const char *device_id, // I - IEEE-1284 device ID const char *device_uri) // I - Device URI { pappl_printer_t *printer; // Printer char resource[1024], // Resource path *resptr, // Pointer into resource path uuid[128], // printer-uuid print_group[65];// print-group value int k_supported; // Maximum file size supported #if !_WIN32 struct statfs spoolinfo; // FS info for spool directory double spoolsize; // FS size #endif // !_WIN32 char path[256]; // Path to resource pappl_pr_driver_data_t driver_data; // Driver data ipp_t *driver_attrs; // Driver attributes static const char * const ipp_versions[] = { // ipp-versions-supported values "1.1", "2.0" }; static const int operations[] = // operations-supported values { IPP_OP_PRINT_JOB, IPP_OP_VALIDATE_JOB, IPP_OP_CREATE_JOB, IPP_OP_SEND_DOCUMENT, IPP_OP_CANCEL_JOB, IPP_OP_GET_JOB_ATTRIBUTES, IPP_OP_GET_JOBS, IPP_OP_GET_PRINTER_ATTRIBUTES, IPP_OP_PAUSE_PRINTER, IPP_OP_RESUME_PRINTER, IPP_OP_SET_PRINTER_ATTRIBUTES, IPP_OP_GET_PRINTER_SUPPORTED_VALUES, IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, IPP_OP_CREATE_JOB_SUBSCRIPTIONS, IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, IPP_OP_GET_SUBSCRIPTIONS, IPP_OP_RENEW_SUBSCRIPTION, IPP_OP_CANCEL_SUBSCRIPTION, IPP_OP_GET_NOTIFICATIONS, IPP_OP_ENABLE_PRINTER, IPP_OP_DISABLE_PRINTER, IPP_OP_PAUSE_PRINTER_AFTER_CURRENT_JOB, IPP_OP_CANCEL_CURRENT_JOB, IPP_OP_CANCEL_JOBS, IPP_OP_CANCEL_MY_JOBS, IPP_OP_CLOSE_JOB, IPP_OP_IDENTIFY_PRINTER, IPP_OP_HOLD_JOB, IPP_OP_RELEASE_JOB, IPP_OP_HOLD_NEW_JOBS, IPP_OP_RELEASE_HELD_NEW_JOBS }; static const char * const charset[] = // charset-supported values { "us-ascii", "utf-8" }; static const char * const client_info[] = { // client-info-supported values "client-name", "client-patches", "client-string-version", "client-version" }; static const char * const compression[] = { // compression-supported values "deflate", "gzip", "none" }; static const char * const job_hold_until[] = { // job-hold-until-supported values "day-time", "evening", "indefinite", "night", "no-hold", "second-shift", "third-shift", "weekend" }; static const char * const multiple_document_handling[] = { // multiple-document-handling-supported values "separate-documents-uncollated-copies", "separate-documents-collated-copies" }; static const int orientation_requested[] = { IPP_ORIENT_PORTRAIT, IPP_ORIENT_LANDSCAPE, IPP_ORIENT_REVERSE_LANDSCAPE, IPP_ORIENT_REVERSE_PORTRAIT, IPP_ORIENT_NONE }; static const char * const print_content_optimize[] = { // print-content-optimize-supported "auto", "graphic", "photo", "text-and-graphic", "text" }; static const char *print_processing[] = { // print-processing-attributes-supported "print-color-mode", "printer-resolution" }; static const int print_quality[] = // print-quality-supported { IPP_QUALITY_DRAFT, IPP_QUALITY_NORMAL, IPP_QUALITY_HIGH }; static const char * const print_scaling[] = { // print-scaling-supported "auto", "auto-fit", "fill", "fit", "none" }; static const char * const uri_security[] = { // uri-security-supported values "none", "tls" }; static const char * const which_jobs[] = { // which-jobs-supported values "completed", "not-completed", "all" }; // Range check input... if (!system || !printer_name || !driver_name || !device_uri) { errno = EINVAL; return (NULL); } if (!system->driver_cb) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "No driver callback set, unable to add printer."); errno = ENOENT; return (NULL); } // Prepare URI values for the printer attributes... if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { // Make sure printer names that start with a digit have a resource path // containing an underscore... if (isdigit(*printer_name & 255)) snprintf(resource, sizeof(resource), "/ipp/print/_%s", printer_name); else snprintf(resource, sizeof(resource), "/ipp/print/%s", printer_name); // Convert URL reserved characters to underscore... for (resptr = resource + 11; *resptr; resptr ++) { if ((*resptr & 255) <= ' ' || strchr("\177/\\\'\"?#", *resptr)) *resptr = '_'; } // Eliminate duplicate and trailing underscores... resptr = resource + 11; while (*resptr) { if (resptr[0] == '_' && resptr[1] == '_') memmove(resptr, resptr + 1, strlen(resptr)); // Duplicate underscores else if (resptr[0] == '_' && !resptr[1]) *resptr = '\0'; // Trailing underscore else resptr ++; } } else papplCopyString(resource, "/ipp/print", sizeof(resource)); // Make sure the printer doesn't already exist... if ((printer = papplSystemFindPrinter(system, resource, 0, NULL)) != NULL) { int n; // Current instance number char temp[1024]; // Temporary resource path if (!strcmp(printer_name, printer->name)) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Printer '%s' already exists.", printer_name); errno = EEXIST; return (NULL); } for (n = 2; n < 10; n ++) { snprintf(temp, sizeof(temp), "%s_%d", resource, n); if (!papplSystemFindPrinter(system, temp, 0, NULL)) break; } if (n >= 10) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Printer '%s' name conflicts with existing printer.", printer_name); errno = EEXIST; return (NULL); } papplCopyString(resource, temp, sizeof(resource)); } // Allocate memory for the printer... if ((printer = calloc(1, sizeof(pappl_printer_t))) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for printer: %s", strerror(errno)); return (NULL); } papplLog(system, PAPPL_LOGLEVEL_INFO, "Printer '%s' at resource path '%s'.", printer_name, resource); _papplSystemMakeUUID(system, printer_name, 0, uuid, sizeof(uuid)); // Get the maximum spool size based on the size of the filesystem used for // the spool directory. If the host OS doesn't support the statfs call // or the filesystem is larger than 2TiB, always report INT_MAX. #if _WIN32 k_supported = INT_MAX; #else // !_WIN32 if (statfs(system->directory, &spoolinfo)) k_supported = INT_MAX; else if ((spoolsize = (double)spoolinfo.f_bsize * spoolinfo.f_blocks / 1024) > INT_MAX) k_supported = INT_MAX; else k_supported = (int)spoolsize; #endif // _WIN32 // Initialize printer structure and attributes... pthread_rwlock_init(&printer->rwlock, NULL); printer->system = system; printer->name = strdup(printer_name); printer->dns_sd_name = strdup(printer_name); printer->resource = strdup(resource); printer->resourcelen = strlen(resource); printer->uriname = printer->resource + 10; // Skip "/ipp/print" in resource printer->device_id = device_id ? strdup(device_id) : NULL; printer->device_uri = strdup(device_uri); printer->driver_name = strdup(driver_name); printer->attrs = ippNew(); printer->start_time = time(NULL); printer->config_time = printer->start_time; printer->state = IPP_PSTATE_IDLE; printer->state_reasons = PAPPL_PREASON_NONE; printer->state_time = printer->start_time; printer->is_accepting = true; printer->all_jobs = cupsArrayNew((cups_array_cb_t)compare_all_jobs, NULL, NULL, 0, NULL, (cups_afree_cb_t)_papplJobDelete); printer->active_jobs = cupsArrayNew((cups_array_cb_t)compare_active_jobs, NULL, NULL, 0, NULL, NULL); printer->completed_jobs = cupsArrayNew((cups_array_cb_t)compare_completed_jobs, NULL, NULL, 0, NULL, NULL); printer->next_job_id = 1; printer->max_active_jobs = (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) ? 0 : 1; printer->max_completed_jobs = 100; printer->usb_vendor_id = 0x1209; // See printer->usb_product_id = 0x8011; if (!printer->name || !printer->dns_sd_name || !printer->resource || (device_id && !printer->device_id) || !printer->device_uri || !printer->driver_name || !printer->attrs) { // Failed to allocate one of the required members... _papplPrinterDelete(printer); return (NULL); } if (papplSystemGetDefaultPrintGroup(system, print_group, sizeof(print_group))) papplPrinterSetPrintGroup(printer, print_group); // If the driver is "auto", figure out the proper driver name... if (!strcmp(driver_name, "auto") && system->autoadd_cb) { // If device_id is NULL, try to look it up... if (!printer->device_id && strncmp(device_uri, "file://", 7)) { pappl_device_t *device; // Connection to printer // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Opening device for auto-setup."); if ((device = papplDeviceOpen(device_uri, "auto", papplLogDevice, system)) != NULL) { char new_id[1024]; // New 1284 device ID if (papplDeviceGetID(device, new_id, sizeof(new_id))) printer->device_id = strdup(new_id); // papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Closing device for auto-setup."); papplDeviceClose(device); } } if ((driver_name = (system->autoadd_cb)(printer_name, device_uri, printer->device_id, system->driver_cbdata)) == NULL) { errno = EIO; _papplPrinterDelete(printer); return (NULL); } } // Add static attributes... // charset-configured ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-configured", NULL, "utf-8"); // charset-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-supported", sizeof(charset) / sizeof(charset[0]), NULL, charset); // client-info-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "client-info-supported", (int)(sizeof(client_info) / sizeof(client_info[0])), NULL, client_info); // compression-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "compression-supported", (int)(sizeof(compression) / sizeof(compression[0])), NULL, compression); // copies-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "copies-default", 1); // device-uuid ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uuid", NULL, uuid); // document-format-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format-default", NULL, "application/octet-stream"); // generated-natural-language-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "generated-natural-language-supported", NULL, "en"); // ipp-versions-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-versions-supported", (cups_len_t)(sizeof(ipp_versions) / sizeof(ipp_versions[0])), NULL, ipp_versions); // job-hold-until-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-hold-until-default", NULL, "no-hold"); // job-hold-until-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-hold-until-supported", (cups_len_t)(sizeof(job_hold_until) / sizeof(job_hold_until[0])), NULL, job_hold_until); // job-hold-until-time-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-hold-until-time-supported", 1); // job-ids-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-ids-supported", 1); // job-k-octets-supported ippAddRange(printer->attrs, IPP_TAG_PRINTER, "job-k-octets-supported", 0, k_supported); // job-priority-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-default", 50); // job-priority-supported ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-supported", 1); // job-sheets-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "job-sheets-default", NULL, "none"); // job-sheets-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "job-sheets-supported", NULL, "none"); // multiple-document-handling-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-document-handling-supported", sizeof(multiple_document_handling) / sizeof(multiple_document_handling[0]), NULL, multiple_document_handling); // multiple-document-jobs-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "multiple-document-jobs-supported", 0); // multiple-operation-time-out ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "multiple-operation-time-out", 60); // multiple-operation-time-out-action ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-operation-time-out-action", NULL, "abort-job"); // natural-language-configured ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "natural-language-configured", NULL, "en"); // notify-events-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events-default", NULL, "job-completed"); // notify-events-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events-supported", (int)(sizeof(_papplEvents) / sizeof(_papplEvents[0])), NULL, _papplEvents); // notify-lease-duration-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "notify-lease-duration-default", PAPPL_LEASE_DEFAULT); // notify-lease-duration-supported ippAddRange(printer->attrs, IPP_TAG_PRINTER, "notify-lease-duration-supported", 0, PAPPL_LEASE_MAX); // notify-max-events-supported ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "notify-max-events-supported", PAPPL_MAX_EVENTS); // notify-pull-method-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-pull-method-supported", NULL, "ippget"); // operations-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported", (int)(sizeof(operations) / sizeof(operations[0])), operations); // orientation-requested-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-supported", (int)(sizeof(orientation_requested) / sizeof(orientation_requested[0])), orientation_requested); // pdl-override-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pdl-override-supported", NULL, "attempted"); // print-content-optimize-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-supported", (int)(sizeof(print_content_optimize) / sizeof(print_content_optimize[0])), NULL, print_content_optimize); // print-processing-attributes-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-processing-attributes-supported", (int)(sizeof(print_processing) / sizeof(print_processing[0])), NULL, print_processing); // print-quality-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-supported", (int)(sizeof(print_quality) / sizeof(print_quality[0])), print_quality); // print-scaling-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-scaling-supported", (int)(sizeof(print_scaling) / sizeof(print_scaling[0])), NULL, print_scaling); // printer-get-attributes-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-get-attributes-supported", NULL, "document-format"); // printer-info ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, printer_name); // printer-name ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, printer_name); // printer-uuid ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, uuid); // requesting-user-uri-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "requesting-user-uri-supported", 1); // smi55357-device-uri ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "smi55357-device-uri", NULL, printer->device_uri); // smi55357-driver ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "smi55357-driver", NULL, printer->driver_name); // uri-security-supported if (system->options & PAPPL_SOPTIONS_NO_TLS) ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-security-supported", NULL, "none"); else if (papplSystemGetTLSOnly(system)) ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-security-supported", NULL, "tls"); else ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-security-supported", 2, NULL, uri_security); // which-jobs-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "which-jobs-supported", sizeof(which_jobs) / sizeof(which_jobs[0]), NULL, which_jobs); // Initialize driver and driver-specific attributes... driver_attrs = NULL; _papplPrinterInitDriverData(&driver_data); if (!(system->driver_cb)(system, driver_name, device_uri, device_id, &driver_data, &driver_attrs, system->driver_cbdata)) { errno = EIO; _papplPrinterDelete(printer); return (NULL); } if (!papplPrinterSetDriverData(printer, &driver_data, driver_attrs)) { errno = EINVAL; _papplPrinterDelete(printer); return (NULL); } ippDelete(driver_attrs); // Add the printer to the system... _papplSystemAddPrinter(system, printer, printer_id); // printer-id _papplRWLockWrite(printer); ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-id", printer->printer_id); _papplRWUnlock(printer); // Do any post-creation work... if (system->create_cb) (system->create_cb)(printer, system->driver_cbdata); // Add socket listeners... if (system->options & PAPPL_SOPTIONS_RAW_SOCKET) { if (_papplPrinterAddRawListeners(printer) && system->is_running) { pthread_t tid; // Thread ID if (pthread_create(&tid, NULL, (void *(*)(void *))_papplPrinterRunRaw, printer)) { // Unable to create client thread... papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create raw listener thread: %s", strerror(errno)); } else { // Detach the main thread from the raw thread to prevent hangs... pthread_detach(tid); _papplRWLockRead(printer); while (!printer->raw_active) { _papplRWUnlock(printer); usleep(1000); // Wait for raw thread to start _papplRWLockRead(printer); } _papplRWUnlock(printer); } } } // Add icons... _papplSystemAddPrinterIcons(system, printer); // Add web pages, if any... if (system->options & PAPPL_SOPTIONS_WEB_INTERFACE) { snprintf(path, sizeof(path), "%s/", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebHome, printer); snprintf(path, sizeof(path), "%s/cancelall", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebCancelAllJobs, printer); if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { snprintf(path, sizeof(path), "%s/delete", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebDelete, printer); } snprintf(path, sizeof(path), "%s/config", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebConfig, printer); snprintf(path, sizeof(path), "%s/jobs", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebJobs, printer); snprintf(path, sizeof(path), "%s/media", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebMedia, printer); papplPrinterAddLink(printer, _PAPPL_LOC("Media"), path, PAPPL_LOPTIONS_NAVIGATION | PAPPL_LOPTIONS_STATUS); snprintf(path, sizeof(path), "%s/printing", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebDefaults, printer); papplPrinterAddLink(printer, _PAPPL_LOC("Printing Defaults"), path, PAPPL_LOPTIONS_NAVIGATION | PAPPL_LOPTIONS_STATUS); if (printer->driver_data.has_supplies) { snprintf(path, sizeof(path), "%s/supplies", printer->uriname); papplSystemAddResourceCallback(system, path, "text/html", (pappl_resource_cb_t)_papplPrinterWebSupplies, printer); papplPrinterAddLink(printer, _PAPPL_LOC("Supplies"), path, PAPPL_LOPTIONS_STATUS); } } _papplSystemConfigChanged(system); // Return it! return (printer); } // // '_papplPrinterDelete()' - Free memory associated with a printer. // void _papplPrinterDelete( pappl_printer_t *printer) // I - Printer { int i; // Looping var _pappl_resource_t *r; // Current resource char prefix[1024]; // Prefix for printer resources size_t prefixlen; // Length of prefix // Let USB/raw printing threads know to exit _papplRWLockWrite(printer); printer->is_deleted = true; while (printer->raw_active || printer->usb_active) { // Wait for threads to finish _papplRWUnlock(printer); usleep(1000); _papplRWLockRead(printer); } _papplRWUnlock(printer); // Close raw listener sockets... for (i = 0; i < printer->num_raw_listeners; i ++) { #if _WIN32 closesocket(printer->raw_listeners[i].fd); #else close(printer->raw_listeners[i].fd); #endif // _WIN32 printer->raw_listeners[i].fd = -1; } printer->num_raw_listeners = 0; // Remove DNS-SD registrations... _papplPrinterUnregisterDNSSDNoLock(printer); // Remove printer-specific resources... snprintf(prefix, sizeof(prefix), "%s/", printer->uriname); prefixlen = strlen(prefix); // Note: System writer lock is already held when calling cupsArrayRemove // for the system's printer object, so we don't need a separate lock here // and can safely use cupsArrayGetFirst/Next... _papplRWLockWrite(printer->system); for (r = (_pappl_resource_t *)cupsArrayGetFirst(printer->system->resources); r; r = (_pappl_resource_t *)cupsArrayGetNext(printer->system->resources)) { if (r->cbdata == printer || !strncmp(r->path, prefix, prefixlen)) cupsArrayRemove(printer->system->resources, r); } _papplRWUnlock(printer->system); // If applicable, call the delete function... if (printer->driver_data.delete_cb) (printer->driver_data.delete_cb)(printer, &printer->driver_data); // Delete jobs... cupsArrayDelete(printer->active_jobs); cupsArrayDelete(printer->completed_jobs); cupsArrayDelete(printer->all_jobs); // Free memory... free(printer->name); free(printer->dns_sd_name); free(printer->location); free(printer->geo_location); free(printer->organization); free(printer->org_unit); free(printer->resource); free(printer->device_id); free(printer->device_uri); free(printer->driver_name); free(printer->usb_storage); ippDelete(printer->driver_attrs); ippDelete(printer->attrs); cupsArrayDelete(printer->links); pthread_rwlock_destroy(&printer->rwlock); free(printer); } // // 'papplPrinterDelete()' - Delete a printer. // // This function deletes a printer from a system, freeing all memory and // canceling all jobs as needed. // void papplPrinterDelete( pappl_printer_t *printer) // I - Printer { pappl_system_t *system = printer->system; // System // Deliver delete event... papplSystemAddEvent(system, printer, NULL, PAPPL_EVENT_PRINTER_DELETED | PAPPL_EVENT_SYSTEM_CONFIG_CHANGED, NULL); // Remove the printer from the system object... _papplRWLockWrite(system); cupsArrayRemove(system->printers, printer); _papplRWUnlock(system); _papplPrinterDelete(printer); _papplSystemConfigChanged(system); } // // 'papplPrinterOpenFile()' - Create or open a file for a printer. // // This function creates, opens, or removes a file for a printer. The "fname" // and "fnamesize" arguments specify the location and size of a buffer to store // the printer filename, which incorporates the "directory", printer ID, // resource name, and "ext" values. The resource name is "sanitized" to only // contain alphanumeric characters. // // The "mode" argument is "r" to read an existing printer file, "w" to write a // new printer file, or "x" to remove an existing printer file. New files are // created with restricted permissions for security purposes. // // For the "r" and "w" modes, the return value is the file descriptor number on // success or `-1` on error. For the "x" mode, the return value is `0` on // success and `-1` on error. The `errno` variable is set appropriately on // error. // int // O - File descriptor or -1 on error papplPrinterOpenFile( pappl_printer_t *printer, // I - Printer char *fname, // I - Filename buffer size_t fnamesize, // I - Size of filename buffer const char *directory, // I - Directory to store in (`NULL` for default) const char *resname, // I - Resource name const char *ext, // I - Extension (`NULL` for none) const char *mode) // I - Open mode - "r" for reading or "w" for writing { char name[64], // "Safe" filename *nameptr; // Pointer into filename // Range check input... if (!printer || !fname || fnamesize < 256 || !resname || !mode) { if (fname) *fname = '\0'; return (-1); } // Make sure the spool directory exists... if (!directory) directory = printer->system->directory; if (mkdir(directory, 0777) && errno != EEXIST) { papplLogPrinter(printer, PAPPL_LOGLEVEL_FATAL, "Unable to create spool directory '%s': %s", directory, strerror(errno)); return (-1); } // Make a name from the resource name argument... for (nameptr = name; *resname && nameptr < (name + sizeof(name) - 1); resname ++) { if (isalnum(*resname & 255) || *resname == '-' || *resname == '.') { *nameptr++ = (char)tolower(*resname & 255); } else { *nameptr++ = '_'; while (resname[1] && !isalnum(resname[1] & 255) && resname[1] != '-' && resname[1] != '.') resname ++; } } *nameptr = '\0'; // Create a filename... if (ext) snprintf(fname, fnamesize, "%s/p%05d-%s.%s", directory, printer->printer_id, name, ext); else snprintf(fname, fnamesize, "%s/p%05d-%s", directory, printer->printer_id, name); if (!strcmp(mode, "r")) return (open(fname, O_RDONLY | O_NOFOLLOW | O_CLOEXEC | O_BINARY)); else if (!strcmp(mode, "w")) return (open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC | O_BINARY, 0600)); else if (!strcmp(mode, "x")) return (unlink(fname)); else return (-1); } // // 'compare_active_jobs()' - Compare two active jobs. // static int // O - Result of comparison compare_active_jobs(pappl_job_t *a, // I - First job pappl_job_t *b) // I - Second job { return (b->job_id - a->job_id); } // // 'compare_jobs()' - Compare two jobs. // static int // O - Result of comparison compare_all_jobs(pappl_job_t *a, // I - First job pappl_job_t *b) // I - Second job { return (b->job_id - a->job_id); } // // 'compare_completed_jobs()' - Compare two completed jobs. // static int // O - Result of comparison compare_completed_jobs(pappl_job_t *a, // I - First job pappl_job_t *b) // I - Second job { return (b->job_id - a->job_id); } pappl-1.4.9/pappl/printer.h000066400000000000000000000610011476704353100156210ustar00rootroot00000000000000// // Public printer header file for the Printer Application Framework // // Copyright © 2019-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_PRINTER_H_ # define _PAPPL_PRINTER_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Limits... // # define PAPPL_MAX_BIN 16 // Maximum number of output bins # define PAPPL_MAX_COLOR_MODE 8 // Maximum number of color modes # define PAPPL_MAX_MEDIA 256 // Maximum number of media sizes # define PAPPL_MAX_RASTER_TYPE 16 // Maximum number of raster types # define PAPPL_MAX_RESOLUTION 4 // Maximum number of printer resolutions # define PAPPL_MAX_SOURCE 16 // Maximum number of sources/rolls # define PAPPL_MAX_SUPPLY 32 // Maximum number of supplies # define PAPPL_MAX_TYPE 32 // Maximum number of media types # define PAPPL_MAX_VENDOR 32 // Maximum number of vendor extension attributes // // Constants... // enum pappl_color_mode_e // IPP "print-color-mode" bit values { PAPPL_COLOR_MODE_AUTO = 0x0001, // 'auto' - Automatic color/monochrome print mode PAPPL_COLOR_MODE_AUTO_MONOCHROME = 0x0002, // 'auto-monochrome' - Automatic monochrome/process monochrome print mode PAPPL_COLOR_MODE_BI_LEVEL = 0x0004, // 'bi-level' - B&W (threshold) print mode PAPPL_COLOR_MODE_COLOR = 0x0008, // 'color' - Full color print mode PAPPL_COLOR_MODE_MONOCHROME = 0x0010, // 'monochrome' - Grayscale print mode using 1 color PAPPL_COLOR_MODE_PROCESS_MONOCHROME = 0x0020 // 'process-monochrome' - Grayscale print mode using multiple colors }; typedef unsigned pappl_color_mode_t; // Bitfield for IPP "print-color-mode" values enum pappl_content_e // IPP "print-content-optimize" bit values { PAPPL_CONTENT_AUTO = 0x01, // 'auto': Automatically determine content PAPPL_CONTENT_GRAPHIC = 0x02, // 'graphic': Optimize for vector graphics PAPPL_CONTENT_PHOTO = 0x04, // 'photo': Optimize for photos/continuous tone images PAPPL_CONTENT_TEXT = 0x08, // 'text': Optimize for text PAPPL_CONTENT_TEXT_AND_GRAPHIC = 0x10 // 'text-and-graphic': Optimize for text and vector graphics }; typedef unsigned pappl_content_t; // Bitfield for IPP "print-content-optimize" values typedef enum pappl_duplex_e // Duplex printing support { PAPPL_DUPLEX_NONE, // No duplex printing support PAPPL_DUPLEX_NORMAL, // Duplex with normal back sides PAPPL_DUPLEX_FLIPPED, // Duplex with flipped back sides PAPPL_DUPLEX_ROTATED, // Duplex with back side rotated 180 degrees for long-edge duplex PAPPL_DUPLEX_MANUAL_TUMBLE // Duplex with back side rotated 180 degrees for short-edge duplex } pappl_duplex_t; enum pappl_finishings_e // IPP "finishings" bit values { PAPPL_FINISHINGS_NONE = 0x0000, // 'none' PAPPL_FINISHINGS_PUNCH = 0x0001, // 'punch' PAPPL_FINISHINGS_STAPLE = 0x0002, // 'staple' PAPPL_FINISHINGS_TRIM = 0x0004 // 'trim' }; typedef unsigned pappl_finishings_t; // Bitfield for IPP "finishings" values enum pappl_identify_actions_e // IPP "identify-actions" bit values { PAPPL_IDENTIFY_ACTIONS_NONE = 0x0000, // No actions PAPPL_IDENTIFY_ACTIONS_DISPLAY = 0x0001, // 'display': Display a message PAPPL_IDENTIFY_ACTIONS_FLASH = 0x0002, // 'flash': Flash the display or a light PAPPL_IDENTIFY_ACTIONS_SOUND = 0x0004, // 'sound': Make a sound PAPPL_IDENTIFY_ACTIONS_SPEAK = 0x0008 // 'speak': Speak a message }; typedef unsigned pappl_identify_actions_t; // Bitfield for IPP "identify-actions" values enum pappl_kind_e // IPP "printer-kind" bit values { PAPPL_KIND_DISC = 0x0001, // 'disc' PAPPL_KIND_DOCUMENT = 0x0002, // 'document' PAPPL_KIND_ENVELOPE = 0x0004, // 'envelope' PAPPL_KIND_LABEL = 0x0008, // 'label' PAPPL_KIND_LARGE_FORMAT = 0x0010, // 'large-format' PAPPL_KIND_PHOTO = 0x0020, // 'photo' PAPPL_KIND_POSTCARD = 0x0040, // 'postcard' PAPPL_KIND_RECEIPT = 0x0080, // 'receipt' PAPPL_KIND_ROLL = 0x0100 // 'roll' }; typedef unsigned pappl_kind_t; // Bitfield for IPP "printer-kind" values enum pappl_label_mode_e // IPP "label-mode-xxx" bit values { PAPPL_LABEL_MODE_APPLICATOR = 0x0001, // 'applicator' PAPPL_LABEL_MODE_CUTTER = 0x0002, // 'cutter' PAPPL_LABEL_MODE_CUTTER_DELAYED = 0x0004, // 'cutter-delayed' PAPPL_LABEL_MODE_KIOSK = 0x0008, // 'kiosk' PAPPL_LABEL_MODE_PEEL_OFF = 0x0010, // 'peel-off' PAPPL_LABEL_MODE_PEEL_OFF_PREPEEL = 0x0020, // 'peel-off-prepeel' PAPPL_LABEL_MODE_REWIND = 0x0040, // 'rewind' PAPPL_LABEL_MODE_RFID = 0x0080, // 'rfid' PAPPL_LABEL_MODE_TEAR_OFF = 0x0100 // 'tear-off' }; typedef unsigned short pappl_label_mode_t; // Bitfield for IPP "label-mode-xxx" values enum pappl_media_tracking_e // IPP "media-tracking" bit values { PAPPL_MEDIA_TRACKING_CONTINUOUS = 0x0001, // 'continuous' PAPPL_MEDIA_TRACKING_GAP = 0x0002, // 'gap' PAPPL_MEDIA_TRACKING_MARK = 0x0004, // 'mark' PAPPL_MEDIA_TRACKING_WEB = 0x0008 // 'web' }; typedef unsigned short pappl_media_tracking_t; // Bitfield for IPP "media-tracking" values enum pappl_preason_e // IPP "printer-state-reasons" bit values { PAPPL_PREASON_NONE = 0x0000, // 'none' PAPPL_PREASON_OTHER = 0x0001, // 'other' PAPPL_PREASON_COVER_OPEN = 0x0002, // 'cover-open' PAPPL_PREASON_INPUT_TRAY_MISSING = 0x0004, // 'input-tray-missing' PAPPL_PREASON_MARKER_SUPPLY_EMPTY = 0x0008, // 'marker-supply-empty' PAPPL_PREASON_MARKER_SUPPLY_LOW = 0x0010, // 'marker-supply-low' PAPPL_PREASON_MARKER_WASTE_ALMOST_FULL = 0x0020, // 'marker-waste-almost-full' PAPPL_PREASON_MARKER_WASTE_FULL = 0x0040, // 'marker-waste-full' PAPPL_PREASON_MEDIA_EMPTY = 0x0080, // 'media-empty' PAPPL_PREASON_MEDIA_JAM = 0x0100, // 'media-jam' PAPPL_PREASON_MEDIA_LOW = 0x0200, // 'media-low' PAPPL_PREASON_MEDIA_NEEDED = 0x0400, // 'media-needed' PAPPL_PREASON_OFFLINE = 0x0800, // 'offline' PAPPL_PREASON_SPOOL_AREA_FULL = 0x1000, // 'spool-area-full' PAPPL_PREASON_TONER_EMPTY = 0x2000, // 'toner-empty' PAPPL_PREASON_TONER_LOW = 0x4000, // 'toner-low' PAPPL_PREASON_DOOR_OPEN = 0x8000, // 'door-open' PAPPL_PREASON_IDENTIFY_PRINTER_REQUESTED = 0x10000, // 'identify-printer-requested' PAPPL_PREASON_DEVICE_STATUS = 0xefff // Supported @link papplDeviceGetStatus@ bits }; enum pappl_raster_type_e // IPP "pwg-raster-document-type-supported" bit values { PAPPL_PWG_RASTER_TYPE_NONE = 0x0000, // Do not force a particular raster type PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_8 = 0x0001, // 8-bit per component AdobeRGB PAPPL_PWG_RASTER_TYPE_ADOBE_RGB_16 = 0x0002, // 16-bit per component AdobeRGB PAPPL_PWG_RASTER_TYPE_BLACK_1 = 0x0004, // 1-bit (device) black PAPPL_PWG_RASTER_TYPE_BLACK_8 = 0x0008, // 8-bit (device) black PAPPL_PWG_RASTER_TYPE_BLACK_16 = 0x0010, // 16-bit (device) black PAPPL_PWG_RASTER_TYPE_CMYK_8 = 0x0020, // 8-bit per component (device) CMYK PAPPL_PWG_RASTER_TYPE_CMYK_16 = 0x0040, // 16-bit per component (device) CMYK PAPPL_PWG_RASTER_TYPE_RGB_8 = 0x0080, // 8-bit per component (device) RGB PAPPL_PWG_RASTER_TYPE_RGB_16 = 0x0100, // 16-bit per component (device) RGB PAPPL_PWG_RASTER_TYPE_SGRAY_8 = 0x0200, // 8-bit grayscale with 2.2 gamma PAPPL_PWG_RASTER_TYPE_SGRAY_16 = 0x0400, // 16-bit grayscale with 2.2 gamma PAPPL_PWG_RASTER_TYPE_SRGB_8 = 0x0800, // 8-bit per component sRGB PAPPL_PWG_RASTER_TYPE_SRGB_16 = 0x1000 // 16-bit per component sRGB }; typedef unsigned pappl_raster_type_t; // Bitfield for IPP "pwg-raster-document-type-supported" values enum pappl_scaling_e // IPP "print-scaling" bit values { PAPPL_SCALING_AUTO = 0x01, // 'auto': Scale to fit (non-borderless) or fill (borderless) if larger, otherwise center PAPPL_SCALING_AUTO_FIT = 0x02, // 'auto-fit': Scale to fit if larger, otherwise center PAPPL_SCALING_FILL = 0x04, // 'fill': Scale to fill the media PAPPL_SCALING_FIT = 0x08, // 'fit': Scale to fit within margins PAPPL_SCALING_NONE = 0x10 // 'none': No scaling (center/crop) }; typedef unsigned pappl_scaling_t; // Bitfield for IPP "print-scaling" values enum pappl_sides_e // IPP "sides" bit values { PAPPL_SIDES_ONE_SIDED = 0x01, // 'one-sided' PAPPL_SIDES_TWO_SIDED_LONG_EDGE = 0x02, // 'two-sided-long-edge' PAPPL_SIDES_TWO_SIDED_SHORT_EDGE = 0x04, // 'two-sided-short-edge' }; typedef unsigned pappl_sides_t; // Bitfield for IPP "sides" values enum pappl_uoptions_e // USB gadget options { PAPPL_UOPTIONS_NONE = 0, // No options (just USB printer) PAPPL_UOPTIONS_ETHERNET = 0x01, // Include USB ethernet gadget PAPPL_UOPTIONS_SERIAL = 0x02, // Include USB serial gadget PAPPL_UOPTIONS_STORAGE = 0x04, // Include USB mass storage gadget PAPPL_UOPTIONS_STORAGE_READONLY = 0x08, // USB mass storage gadget is read-only PAPPL_UOPTIONS_STORAGE_REMOVABLE = 0x10 // USB mass storage gadget is removable }; typedef unsigned pappl_uoptions_t; // USB gadget options bitfield // // Callback functions... // typedef void (*pappl_default_cb_t)(ipp_attribute_t *attr, void *data); // papplIterateDefaults callback typedef void (*pappl_job_cb_t)(pappl_job_t *job, void *data); // papplIterateXxxJobs callback function typedef void (*pappl_pr_delete_cb_t)(pappl_printer_t *printer, pappl_pr_driver_data_t *data); // Printer deletion callback typedef void (*pappl_pr_identify_cb_t)(pappl_printer_t *printer, pappl_identify_actions_t actions, const char *message); // Identify-Printer callback typedef bool (*pappl_pr_printfile_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); // Print a "raw" job callback typedef bool (*pappl_pr_rendjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); // End a raster job callback typedef bool (*pappl_pr_rendpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); // End a raster page callback typedef bool (*pappl_pr_rstartjob_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); // Start a raster job callback typedef bool (*pappl_pr_rstartpage_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); // Start a raster page callback typedef bool (*pappl_pr_rwriteline_cb_t)(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned y, const unsigned char *line); // Write a line of raster graphics callback typedef bool (*pappl_pr_status_cb_t)(pappl_printer_t *printer); // Update printer status callback typedef const char *(*pappl_pr_testpage_cb_t)(pappl_printer_t *printer, char *buffer, size_t bufsize); // Print a test page callback typedef ssize_t (*pappl_pr_usb_cb_t)(pappl_printer_t *printer, pappl_device_t *device, void *buffer, size_t bufsize, size_t bytes, void *data); // Raw USB IO callback // // Structures... // typedef struct pappl_icon_s // Printer PNG icon structure { char filename[256]; // External filename, if any const void *data; // PNG icon data, if any size_t datalen; // Size of PNG icon data } pappl_icon_t; typedef struct pappl_media_col_s // Media details structure { int bottom_margin; // Bottom margin in hundredths of millimeters int left_margin; // Left margin in hundredths of millimeters int left_offset; // Left offset in hundredths of millimeters int right_margin; // Right margin in hundredths of millimeters int size_width; // Width in hundredths of millimeters int size_length; // Height in hundredths of millimeters char size_name[64]; // PWG media size name char source[64]; // PWG media source name int top_margin; // Top margin in hundredths of millimeters int top_offset; // Top offset in hundredths of millimeters pappl_media_tracking_t tracking; // Media tracking char type[64]; // PWG media type name } pappl_media_col_t; struct pappl_pr_options_s // Combined print job options { # if CUPS_VERSION_MAJOR < 3 cups_page_header2_t header; // Raster header # else cups_page_header_t header; // Raster header # endif // CUPS_VERSION_MAJOR < 3 unsigned num_pages; // Number of pages in job unsigned first_page; // First page in page-ranges, starting at 1 unsigned last_page; // Last page in page-ranges, starting at 1 pappl_dither_t dither; // Dither array, if any int copies; // "copies" value pappl_finishings_t finishings; // "finishings" value(s) pappl_media_col_t media; // "media"/"media-col" value ipp_orient_t orientation_requested; // "orientation-requested" value char output_bin[64]; // "output-bin" value pappl_color_mode_t print_color_mode; // "print-color-mode" value pappl_content_t print_content_optimize; // "print-content-optimize" value int print_darkness; // "print-darkness" value int darkness_configured; // "printer-darkness-configured" value ipp_quality_t print_quality; // "print-quality" value pappl_scaling_t print_scaling; // "print-scaling" value int print_speed; // "print-speed" value int printer_resolution[2]; // "printer-resolution" value in dots per inch pappl_sides_t sides; // "sides" value int num_vendor; // Number of vendor options cups_option_t *vendor; // Vendor options }; struct pappl_pr_driver_data_s // Printer driver data { void *extension; // Extension data (managed by driver) pappl_pr_delete_cb_t delete_cb; // Printer deletion callback pappl_pr_identify_cb_t identify_cb; // Identify-Printer callback pappl_pr_printfile_cb_t printfile_cb; // Print (raw) file callback pappl_pr_rendjob_cb_t rendjob_cb; // End raster job callback pappl_pr_rendpage_cb_t rendpage_cb; // End raster page callback pappl_pr_rstartjob_cb_t rstartjob_cb; // Start raster job callback pappl_pr_rstartpage_cb_t rstartpage_cb; // Start raster page callback pappl_pr_rwriteline_cb_t rwriteline_cb; // Write raster line callback pappl_pr_status_cb_t status_cb; // Status callback pappl_pr_testpage_cb_t testpage_cb; // Test page callback pappl_dither_t gdither; // 'auto', 'text', and 'graphic' dither array pappl_dither_t pdither; // 'photo' dither array const char *format; // Printer-specific format char make_and_model[128]; // "printer-make-and-model" value int ppm; // "pages-per-minute" value int ppm_color; // "pages-per-minute-color" value, if any pappl_icon_t icons[3]; // "printer-icons" values pappl_kind_t kind; // "printer-kind" values bool has_supplies; // Printer has supplies to report bool input_face_up; // Does input media come in face-up? bool output_face_up; // Does output media come out face-up? ipp_orient_t orient_default; // "orientation-requested-default" value pappl_color_mode_t color_supported; // "print-color-mode" values pappl_color_mode_t color_default; // "print-color-mode-default" value pappl_content_t content_default; // "print-content-default" value ipp_quality_t quality_default; // "print-quality-default" value pappl_scaling_t scaling_default; // "print-scaling-default" value pappl_raster_type_t raster_types; // "pwg-raster-document-type-supported" values pappl_raster_type_t force_raster_type; // Force a particular raster type? pappl_duplex_t duplex; // Duplex printing modes supported pappl_sides_t sides_supported; // "sides-supported" values pappl_sides_t sides_default; // "sides-default" value pappl_finishings_t finishings; // "finishings-supported" values int num_resolution; // Number of printer resolutions int x_resolution[PAPPL_MAX_RESOLUTION]; // Horizontal printer resolutions int y_resolution[PAPPL_MAX_RESOLUTION]; // Vertical printer resolutions int x_default; // Default horizontal resolution int y_default; // Default vertical resolution bool borderless; // Borderless margins supported? int left_right; // Left and right margins in hundredths of millimeters int bottom_top; // Bottom and top margins in hundredths of millimeters int num_media; // Number of supported media const char *media[PAPPL_MAX_MEDIA];// Supported media pappl_media_col_t media_default; // Default media pappl_media_col_t media_ready[PAPPL_MAX_SOURCE]; // Ready media int num_source; // Number of media sources (trays/rolls) const char *source[PAPPL_MAX_SOURCE]; // Media sources int left_offset_supported[2]; // media-left-offset-supported (0,0 for none) int top_offset_supported[2]; // media-top-offset-supported (0,0 for none) pappl_media_tracking_t tracking_supported; // media-tracking-supported int num_type; // Number of media types const char *type[PAPPL_MAX_TYPE]; // Media types int num_bin; // Number of output bins const char *bin[PAPPL_MAX_BIN]; // Output bins int bin_default; // Default output bin pappl_label_mode_t mode_configured; // label-mode-configured pappl_label_mode_t mode_supported; // label-mode-supported int tear_offset_configured; // label-tear-offset-configured int tear_offset_supported[2]; // label-tear-offset-supported (0,0 for none) int speed_supported[2]; // print-speed-supported (0,0 for none) int speed_default; // print-speed-default int darkness_default; // print-darkness-default int darkness_configured; // printer-darkness-configured int darkness_supported; // printer/print-darkness-supported (0 for none) pappl_identify_actions_t identify_default; // "identify-actions-default" values pappl_identify_actions_t identify_supported; // "identify-actions-supported" values int num_features; // Number of "ipp-features-supported" values const char *features[PAPPL_MAX_VENDOR]; // "ipp-features-supported" values int num_vendor; // Number of vendor attributes const char *vendor[PAPPL_MAX_VENDOR]; // Vendor attribute names }; // // Functions... // extern void papplPrinterAddLink(pappl_printer_t *printer, const char *label, const char *path_or_url, pappl_loptions_t options) _PAPPL_PUBLIC; extern void papplPrinterCancelAllJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterCloseDevice(pappl_printer_t *printer) _PAPPL_PUBLIC; extern pappl_printer_t *papplPrinterCreate(pappl_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_id, const char *device_uri) _PAPPL_PUBLIC; extern void papplPrinterDelete(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterDisable(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterEnable(pappl_printer_t *printer) _PAPPL_PUBLIC; extern pappl_job_t *papplPrinterFindJob(pappl_printer_t *printer, int job_id) _PAPPL_PUBLIC; extern pappl_contact_t *papplPrinterGetContact(pappl_printer_t *printer, pappl_contact_t *contact) _PAPPL_PUBLIC; extern const char *papplPrinterGetDeviceID(pappl_printer_t *printer) _PAPPL_PUBLIC; extern const char *papplPrinterGetDeviceURI(pappl_printer_t *printer) _PAPPL_PUBLIC; extern char *papplPrinterGetDNSSDName(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern ipp_t *papplPrinterGetDriverAttributes(pappl_printer_t *printer) _PAPPL_PUBLIC; extern pappl_pr_driver_data_t *papplPrinterGetDriverData(pappl_printer_t *printer, pappl_pr_driver_data_t *data) _PAPPL_PUBLIC; extern const char *papplPrinterGetDriverName(pappl_printer_t *printer) _PAPPL_PUBLIC; extern char *papplPrinterGetGeoLocation(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplPrinterGetID(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetImpressionsCompleted(pappl_printer_t *printer) _PAPPL_PUBLIC; extern char *papplPrinterGetLocation(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplPrinterGetMaxActiveJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetMaxCompletedJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetMaxPreservedJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern const char *papplPrinterGetName(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetNextJobID(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetNumberOfActiveJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetNumberOfCompletedJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetNumberOfJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern char *papplPrinterGetOrganization(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplPrinterGetOrganizationalUnit(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplPrinterGetPath(pappl_printer_t *printer, const char *subpath, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplPrinterGetPrintGroup(pappl_printer_t *printer, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern pappl_preason_t papplPrinterGetReasons(pappl_printer_t *printer) _PAPPL_PUBLIC; extern ipp_pstate_t papplPrinterGetState(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterGetSupplies(pappl_printer_t *printer, int max_supplies, pappl_supply_t *supplies) _PAPPL_PUBLIC; extern pappl_system_t *papplPrinterGetSystem(pappl_printer_t *printer) _PAPPL_PUBLIC; extern bool papplPrinterHoldNewJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterHTMLFooter(pappl_client_t *client) _PAPPL_PUBLIC; extern void papplPrinterHTMLHeader(pappl_client_t *client, const char *title, int refresh) _PAPPL_PUBLIC; extern bool papplPrinterIsAcceptingJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern bool papplPrinterIsDeleted(pappl_printer_t *printer) _PAPPL_PUBLIC; extern bool papplPrinterIsHoldingNewJobs(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterIterateActiveJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit) _PAPPL_PUBLIC; extern void papplPrinterIterateAllJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit) _PAPPL_PUBLIC; extern void papplPrinterIterateCompletedJobs(pappl_printer_t *printer, pappl_job_cb_t cb, void *data, int first_index, int limit) _PAPPL_PUBLIC; extern pappl_device_t *papplPrinterOpenDevice(pappl_printer_t *printer) _PAPPL_PUBLIC; extern int papplPrinterOpenFile(pappl_printer_t *printer, char *fname, size_t fnamesize, const char *directory, const char *resname, const char *ext, const char *mode) _PAPPL_PUBLIC; extern void papplPrinterPause(pappl_printer_t *printer) _PAPPL_PUBLIC; extern bool papplPrinterReleaseHeldNewJobs(pappl_printer_t *printer, const char *username) _PAPPL_PUBLIC; extern void papplPrinterRemoveLink(pappl_printer_t *printer, const char *label) _PAPPL_PUBLIC; extern void papplPrinterResume(pappl_printer_t *printer) _PAPPL_PUBLIC; extern void papplPrinterSetContact(pappl_printer_t *printer, pappl_contact_t *contact) _PAPPL_PUBLIC; extern void papplPrinterSetDNSSDName(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern bool papplPrinterSetDriverData(pappl_printer_t *printer, pappl_pr_driver_data_t *data, ipp_t *attrs) _PAPPL_PUBLIC; extern bool papplPrinterSetDriverDefaults(pappl_printer_t *printer, pappl_pr_driver_data_t *data, int num_vendor, cups_option_t *vendor) _PAPPL_PUBLIC; extern void papplPrinterSetGeoLocation(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern void papplPrinterSetImpressionsCompleted(pappl_printer_t *printer, int add) _PAPPL_PUBLIC; extern void papplPrinterSetLocation(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern void papplPrinterSetMaxActiveJobs(pappl_printer_t *printer, int max_active_jobs) _PAPPL_PUBLIC; extern void papplPrinterSetMaxCompletedJobs(pappl_printer_t *printer, int max_completed_jobs) _PAPPL_PUBLIC; extern void papplPrinterSetMaxPreservedJobs(pappl_printer_t *printer, int max_preserved_jobs) _PAPPL_PUBLIC; extern void papplPrinterSetNextJobID(pappl_printer_t *printer, int next_job_id) _PAPPL_PUBLIC; extern void papplPrinterSetOrganization(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern void papplPrinterSetOrganizationalUnit(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern void papplPrinterSetPrintGroup(pappl_printer_t *printer, const char *value) _PAPPL_PUBLIC; extern bool papplPrinterSetReadyMedia(pappl_printer_t *printer, int num_ready, pappl_media_col_t *ready) _PAPPL_PUBLIC; extern void papplPrinterSetReasons(pappl_printer_t *printer, pappl_preason_t add, pappl_preason_t remove) _PAPPL_PUBLIC; extern void papplPrinterSetSupplies(pappl_printer_t *printer, int num_supplies, pappl_supply_t *supplies) _PAPPL_PUBLIC; extern void papplPrinterSetUSB(pappl_printer_t *printer, unsigned vendor_id, unsigned product_id, pappl_uoptions_t options, const char *storagefile, pappl_pr_usb_cb_t usb_cb, void *usb_data) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_PRINTER_H_ pappl-1.4.9/pappl/resource-private.h000066400000000000000000002465541476704353100174570ustar00rootroot00000000000000/* icon-sm.png */ static unsigned char icon_sm_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,0,48,0,0,0,48,8,3,0,0,0,96,220,9, 181,0,0,4,14,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,155,185,179,43, 36,206,131,212,166,166,146,14,254,53,148,180,108,82,209,132, 218,232,254,101,179,109,220,44,147,108,180,65,144,201,236,221, 157,105,38,51,227,252,164,105,41,62,20,65,16,193,168,224, 147,224,255,91,193,39,33,106,171,237,139,45,162,180,80,162, 4,131,40,248,208,250,71,161,210,23,9,235,185,51,179,187, 147,184,107,189,203,220,249,230,156,239,126,231,222,115,238,222, 11,144,184,44,91,150,222,37,2,44,26,174,45,229,211,226, 179,199,230,196,196,58,116,193,125,208,13,125,208,45,43,142, 149,42,149,38,1,27,227,194,191,218,237,239,32,198,222,215, 246,183,247,255,103,235,174,80,71,1,136,221,133,216,172,56, 202,34,226,101,0,254,21,197,178,93,128,4,65,251,200,9, 215,98,248,9,196,59,108,156,32,226,18,195,181,0,87,24, 158,15,240,178,207,153,145,50,136,95,69,44,40,170,140,254, 196,219,136,7,231,35,246,90,4,7,115,240,219,142,60,53, 168,173,41,34,203,69,201,54,171,154,78,35,211,189,131,251, 127,182,69,221,107,196,219,131,79,143,179,48,125,20,223,3, 184,246,151,42,114,150,225,135,16,159,85,228,220,116,136,175, 46,105,179,197,16,255,101,185,105,9,241,35,0,93,187,188, 133,114,10,241,62,196,99,85,123,188,28,232,116,169,170,55, 209,192,43,167,212,153,103,16,223,131,120,117,193,60,202,198, 238,68,252,181,49,95,156,10,117,126,82,156,12,230,15,30, 0,224,226,42,45,176,122,247,35,30,176,77,105,42,136,203, 141,87,104,54,199,242,136,248,184,230,22,102,2,125,238,45, 103,105,58,215,208,57,165,102,138,65,44,238,139,227,242,17, 86,167,62,196,87,169,158,151,66,253,95,45,183,20,198,37, 61,134,94,156,12,116,200,48,117,252,245,250,118,87,157,153, 8,226,146,57,23,11,26,140,37,47,86,181,241,66,200,127, 87,181,39,164,16,95,182,116,127,143,226,220,200,77,219,147, 202,1,159,191,159,26,229,80,147,31,147,237,92,62,196,21, 152,141,201,64,193,132,121,236,21,48,96,19,68,144,32,15, 105,124,91,96,163,167,10,26,232,104,161,232,165,104,161,248, 213,224,236,223,194,41,249,254,0,183,84,106,254,200,235,232, 209,48,66,166,255,35,240,208,170,194,239,104,85,35,188,12, 126,121,104,171,117,208,9,102,112,35,212,49,73,47,73,146, 131,248,28,34,147,228,48,25,33,163,32,146,39,201,83,100, 140,100,209,58,74,14,53,199,150,34,115,100,243,185,209,212, 121,1,35,82,159,55,139,188,139,232,119,65,198,254,103,100, 152,224,180,207,197,74,159,55,16,216,207,216,207,107,202,149, 215,110,94,58,125,110,87,139,187,70,86,159,187,214,115,233, 116,36,103,26,106,45,116,200,218,212,157,114,207,255,194,95, 231,215,176,95,231,55,90,12,254,7,126,3,127,235,219,86, 183,53,235,52,204,86,10,125,186,111,91,196,71,243,61,78, 100,62,165,45,85,108,97,179,163,162,89,53,86,250,2,31, 203,0,125,185,120,187,8,103,6,91,252,228,247,201,63,146, 107,201,247,146,31,38,127,227,222,228,62,225,206,115,159,114, 159,113,223,128,200,93,224,46,114,95,114,95,113,31,115,159, 71,106,212,121,239,52,107,238,175,163,177,10,230,105,151,81, 220,159,66,90,216,45,60,40,100,133,61,194,195,194,100,75, 79,232,21,134,132,9,97,47,122,118,55,171,19,141,23,93, 187,6,199,176,111,100,171,125,172,128,23,169,115,236,110,172, 179,214,225,63,84,70,150,6,39,124,166,227,239,51,3,78, 110,227,132,35,73,63,25,34,133,109,187,122,132,237,245,166, 118,126,75,61,218,175,129,198,115,241,108,60,5,98,124,95, 124,52,62,20,63,194,112,131,25,223,139,190,81,236,241,212, 114,233,178,203,14,226,140,105,157,180,181,154,234,138,195,201, 228,227,98,10,175,50,42,22,12,229,192,160,40,235,186,232, 187,28,209,166,14,181,151,104,229,0,176,123,50,56,194,111, 73,254,253,23,219,121,165,101,115,159,6,56,252,39,59,247, 90,182,57,15,224,172,3,208,251,104,203,54,128,103,227,189, 239,0,172,62,166,120,246,82,120,39,196,98,223,2,56,213, 131,195,193,87,79,26,207,171,31,235,245,91,120,110,37,222, 0,216,124,189,94,255,251,253,122,125,243,3,212,223,0,184, 160,255,3,255,37,120,11,197,99,214,203,0,0,0,56,101, 88,73,102,77,77,0,42,0,0,0,8,0,1,135,105,0, 4,0,0,0,1,0,0,0,26,0,0,0,0,0,2,160, 2,0,4,0,0,0,1,0,0,0,48,160,3,0,4,0, 0,0,1,0,0,0,48,0,0,0,0,248,255,78,54,0, 0,3,101,105,84,88,116,88,77,76,58,99,111,109,46,97, 100,111,98,101,46,120,109,112,0,0,0,0,0,60,120,58, 120,109,112,109,101,116,97,32,120,109,108,110,115,58,120,61, 34,97,100,111,98,101,58,110,115,58,109,101,116,97,47,34, 32,120,58,120,109,112,116,107,61,34,88,77,80,32,67,111, 114,101,32,54,46,48,46,48,34,62,10,32,32,32,60,114, 100,102,58,82,68,70,32,120,109,108,110,115,58,114,100,102, 61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46, 111,114,103,47,49,57,57,57,47,48,50,47,50,50,45,114, 100,102,45,115,121,110,116,97,120,45,110,115,35,34,62,10, 32,32,32,32,32,32,60,114,100,102,58,68,101,115,99,114, 105,112,116,105,111,110,32,114,100,102,58,97,98,111,117,116, 61,34,34,10,32,32,32,32,32,32,32,32,32,32,32,32, 120,109,108,110,115,58,112,104,111,116,111,115,104,111,112,61, 34,104,116,116,112,58,47,47,110,115,46,97,100,111,98,101, 46,99,111,109,47,112,104,111,116,111,115,104,111,112,47,49, 46,48,47,34,10,32,32,32,32,32,32,32,32,32,32,32, 32,120,109,108,110,115,58,100,99,61,34,104,116,116,112,58, 47,47,112,117,114,108,46,111,114,103,47,100,99,47,101,108, 101,109,101,110,116,115,47,49,46,49,47,34,10,32,32,32, 32,32,32,32,32,32,32,32,32,120,109,108,110,115,58,73, 112,116,99,52,120,109,112,69,120,116,61,34,104,116,116,112, 58,47,47,105,112,116,99,46,111,114,103,47,115,116,100,47, 73,112,116,99,52,120,109,112,69,120,116,47,50,48,48,56, 45,48,50,45,50,57,47,34,62,10,32,32,32,32,32,32, 32,32,32,60,112,104,111,116,111,115,104,111,112,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,112,104,111,116,111,115,104,111,112,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 100,99,58,114,105,103,104,116,115,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,32,120,109,108,58,108,97,110,103, 61,34,120,45,100,101,102,97,117,108,116,34,62,67,111,112, 121,114,105,103,104,116,32,50,48,50,48,32,77,105,99,104, 97,101,108,32,83,119,101,101,116,60,47,114,100,102,58,108, 105,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60, 47,114,100,102,58,65,108,116,62,10,32,32,32,32,32,32, 32,32,32,60,47,100,99,58,114,105,103,104,116,115,62,10, 32,32,32,32,32,32,32,32,32,60,100,99,58,99,114,101, 97,116,111,114,62,10,32,32,32,32,32,32,32,32,32,32, 32,32,60,114,100,102,58,83,101,113,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,114,100,102,58, 108,105,62,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,99, 114,101,97,116,111,114,62,10,32,32,32,32,32,32,32,32, 32,60,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,10,32,32,32,32,32,32,60,47, 114,100,102,58,68,101,115,99,114,105,112,116,105,111,110,62, 10,32,32,32,60,47,114,100,102,58,82,68,70,62,10,60, 47,120,58,120,109,112,109,101,116,97,62,10,252,83,118,101, 0,0,1,122,80,76,84,69,0,0,0,0,0,0,60,60, 60,64,64,64,65,65,65,67,62,62,67,67,67,68,62,62, 68,68,68,69,69,69,70,61,61,72,72,72,74,60,60,78, 78,78,79,58,59,84,83,83,84,84,84,85,83,83,86,86, 86,88,55,56,90,90,90,91,91,91,93,79,79,93,93,93, 94,54,54,94,78,79,94,94,94,95,53,54,99,99,99,100, 75,76,100,100,100,103,50,51,104,73,74,106,73,73,108,108, 108,110,110,110,112,47,49,113,47,49,113,113,113,114,47,48, 117,117,117,119,45,47,120,45,46,124,43,45,124,44,45,124, 64,65,128,42,44,128,128,128,129,42,44,129,129,129,130,61, 62,133,59,61,135,135,135,138,57,58,140,38,40,141,38,40, 142,55,57,143,37,39,145,37,39,148,36,38,149,149,149,152, 152,152,154,33,36,155,33,36,155,48,51,157,33,35,159,32, 34,160,32,34,162,31,34,163,31,33,166,29,32,169,169,169, 170,170,170,171,171,171,172,40,43,173,27,30,178,37,40,183, 35,38,186,23,26,186,186,186,189,32,35,193,20,24,193,30, 33,193,193,193,195,29,32,196,20,23,198,198,198,199,199,199, 200,18,22,204,204,204,210,21,25,210,210,210,212,14,18,215, 215,215,216,216,216,217,217,217,218,12,16,218,218,218,219,12, 16,222,15,19,222,222,222,223,11,15,224,10,15,225,10,14, 225,225,225,227,13,17,229,229,229,231,231,231,235,7,11,235, 235,235,236,9,13,239,7,12,239,239,239,240,240,240,242,4, 9,243,5,10,244,244,244,245,3,8,248,248,248,249,2,7, 249,249,249,250,250,250,251,2,7,251,251,251,254,254,254,255, 255,255,158,89,226,15,0,0,0,1,116,82,78,83,0,64, 230,216,102,0,0,1,171,73,68,65,84,72,199,213,150,103, 87,194,48,20,134,193,235,64,42,26,113,162,162,56,112,111, 112,79,144,162,184,181,46,20,247,222,91,104,53,255,221,40, 80,42,36,5,61,218,115,124,63,164,189,77,159,228,230,109, 70,117,186,4,233,191,74,151,84,127,0,232,191,35,205,0, 0,4,31,82,43,25,128,1,149,148,148,165,10,164,119,173, 93,134,174,207,206,94,146,2,40,172,245,253,225,90,51,185, 98,36,203,44,223,153,18,123,200,124,53,132,219,195,159,101, 101,227,200,194,209,147,89,37,165,194,139,72,2,184,194,57, 233,191,187,247,79,57,43,179,213,198,80,179,123,253,134,19, 37,10,38,6,80,31,218,223,137,190,181,229,19,162,109,115, 62,129,1,152,223,16,238,136,8,115,162,156,12,39,178,92, 194,10,0,41,179,98,184,4,152,163,246,64,92,99,124,56, 236,219,166,140,33,14,8,95,34,21,130,168,176,134,2,196, 166,170,178,34,113,82,252,2,32,187,68,151,236,146,134,41, 253,24,96,233,31,185,36,114,84,32,54,189,227,1,193,87, 68,1,20,11,40,30,48,197,38,31,125,137,198,3,73,119, 62,121,247,70,41,136,178,226,202,61,19,14,35,192,24,159, 7,13,30,183,61,159,196,77,70,139,167,128,185,205,180,72, 75,143,94,40,149,164,54,224,31,86,131,253,36,126,240,218, 164,58,21,32,103,57,0,238,189,141,57,224,79,224,120,145, 196,243,1,117,224,32,56,8,167,51,163,183,25,252,243,113, 176,251,51,86,7,250,170,161,74,34,106,230,175,58,115,17, 137,11,128,14,132,125,232,145,138,17,154,189,177,90,15,151, 167,207,163,177,77,218,92,25,103,184,84,234,202,66,208,219, 14,224,24,178,15,144,39,36,6,176,184,92,174,86,181,19, 40,197,35,75,175,79,75,161,212,244,216,85,249,87,208,28, 120,7,130,103,161,54,151,78,135,16,0,0,0,0,73,69, 78,68,174,66,96,130, }; /* icon-md.png */ static unsigned char icon_md_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,0,128,0,0,0,128,8,3,0,0,0,244,224,145, 249,0,0,4,14,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,155,185,179,43, 36,206,131,212,166,166,146,14,254,53,148,180,108,82,209,132, 218,232,254,101,179,109,220,44,147,108,180,65,144,201,236,221, 157,105,38,51,227,252,164,105,41,62,20,65,16,193,168,224, 147,224,255,91,193,39,33,106,171,237,139,45,162,180,80,162, 4,131,40,248,208,250,71,161,210,23,9,235,185,51,179,187, 147,184,107,189,203,220,249,230,156,239,126,231,222,115,238,222, 11,144,184,44,91,150,222,37,2,44,26,174,45,229,211,226, 179,199,230,196,196,58,116,193,125,208,13,125,208,45,43,142, 149,42,149,38,1,27,227,194,191,218,237,239,32,198,222,215, 246,183,247,255,103,235,174,80,71,1,136,221,133,216,172,56, 202,34,226,101,0,254,21,197,178,93,128,4,65,251,200,9, 215,98,248,9,196,59,108,156,32,226,18,195,181,0,87,24, 158,15,240,178,207,153,145,50,136,95,69,44,40,170,140,254, 196,219,136,7,231,35,246,90,4,7,115,240,219,142,60,53, 168,173,41,34,203,69,201,54,171,154,78,35,211,189,131,251, 127,182,69,221,107,196,219,131,79,143,179,48,125,20,223,3, 184,246,151,42,114,150,225,135,16,159,85,228,220,116,136,175, 46,105,179,197,16,255,101,185,105,9,241,35,0,93,187,188, 133,114,10,241,62,196,99,85,123,188,28,232,116,169,170,55, 209,192,43,167,212,153,103,16,223,131,120,117,193,60,202,198, 238,68,252,181,49,95,156,10,117,126,82,156,12,230,15,30, 0,224,226,42,45,176,122,247,35,30,176,77,105,42,136,203, 141,87,104,54,199,242,136,248,184,230,22,102,2,125,238,45, 103,105,58,215,208,57,165,102,138,65,44,238,139,227,242,17, 86,167,62,196,87,169,158,151,66,253,95,45,183,20,198,37, 61,134,94,156,12,116,200,48,117,252,245,250,118,87,157,153, 8,226,146,57,23,11,26,140,37,47,86,181,241,66,200,127, 87,181,39,164,16,95,182,116,127,143,226,220,200,77,219,147, 202,1,159,191,159,26,229,80,147,31,147,237,92,62,196,21, 152,141,201,64,193,132,121,236,21,48,96,19,68,144,32,15, 105,124,91,96,163,167,10,26,232,104,161,232,165,104,161,248, 213,224,236,223,194,41,249,254,0,183,84,106,254,200,235,232, 209,48,66,166,255,35,240,208,170,194,239,104,85,35,188,12, 126,121,104,171,117,208,9,102,112,35,212,49,73,47,73,146, 131,248,28,34,147,228,48,25,33,163,32,146,39,201,83,100, 140,100,209,58,74,14,53,199,150,34,115,100,243,185,209,212, 121,1,35,82,159,55,139,188,139,232,119,65,198,254,103,100, 152,224,180,207,197,74,159,55,16,216,207,216,207,107,202,149, 215,110,94,58,125,110,87,139,187,70,86,159,187,214,115,233, 116,36,103,26,106,45,116,200,218,212,157,114,207,255,194,95, 231,215,176,95,231,55,90,12,254,7,126,3,127,235,219,86, 183,53,235,52,204,86,10,125,186,111,91,196,71,243,61,78, 100,62,165,45,85,108,97,179,163,162,89,53,86,250,2,31, 203,0,125,185,120,187,8,103,6,91,252,228,247,201,63,146, 107,201,247,146,31,38,127,227,222,228,62,225,206,115,159,114, 159,113,223,128,200,93,224,46,114,95,114,95,113,31,115,159, 71,106,212,121,239,52,107,238,175,163,177,10,230,105,151,81, 220,159,66,90,216,45,60,40,100,133,61,194,195,194,100,75, 79,232,21,134,132,9,97,47,122,118,55,171,19,141,23,93, 187,6,199,176,111,100,171,125,172,128,23,169,115,236,110,172, 179,214,225,63,84,70,150,6,39,124,166,227,239,51,3,78, 110,227,132,35,73,63,25,34,133,109,187,122,132,237,245,166, 118,126,75,61,218,175,129,198,115,241,108,60,5,98,124,95, 124,52,62,20,63,194,112,131,25,223,139,190,81,236,241,212, 114,233,178,203,14,226,140,105,157,180,181,154,234,138,195,201, 228,227,98,10,175,50,42,22,12,229,192,160,40,235,186,232, 187,28,209,166,14,181,151,104,229,0,176,123,50,56,194,111, 73,254,253,23,219,121,165,101,115,159,6,56,252,39,59,247, 90,182,57,15,224,172,3,208,251,104,203,54,128,103,227,189, 239,0,172,62,166,120,246,82,120,39,196,98,223,2,56,213, 131,195,193,87,79,26,207,171,31,235,245,91,120,110,37,222, 0,216,124,189,94,255,251,253,122,125,243,3,212,223,0,184, 160,255,3,255,37,120,11,197,99,214,203,0,0,0,56,101, 88,73,102,77,77,0,42,0,0,0,8,0,1,135,105,0, 4,0,0,0,1,0,0,0,26,0,0,0,0,0,2,160, 2,0,4,0,0,0,1,0,0,0,128,160,3,0,4,0, 0,0,1,0,0,0,128,0,0,0,0,107,70,38,77,0, 0,3,101,105,84,88,116,88,77,76,58,99,111,109,46,97, 100,111,98,101,46,120,109,112,0,0,0,0,0,60,120,58, 120,109,112,109,101,116,97,32,120,109,108,110,115,58,120,61, 34,97,100,111,98,101,58,110,115,58,109,101,116,97,47,34, 32,120,58,120,109,112,116,107,61,34,88,77,80,32,67,111, 114,101,32,54,46,48,46,48,34,62,10,32,32,32,60,114, 100,102,58,82,68,70,32,120,109,108,110,115,58,114,100,102, 61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46, 111,114,103,47,49,57,57,57,47,48,50,47,50,50,45,114, 100,102,45,115,121,110,116,97,120,45,110,115,35,34,62,10, 32,32,32,32,32,32,60,114,100,102,58,68,101,115,99,114, 105,112,116,105,111,110,32,114,100,102,58,97,98,111,117,116, 61,34,34,10,32,32,32,32,32,32,32,32,32,32,32,32, 120,109,108,110,115,58,112,104,111,116,111,115,104,111,112,61, 34,104,116,116,112,58,47,47,110,115,46,97,100,111,98,101, 46,99,111,109,47,112,104,111,116,111,115,104,111,112,47,49, 46,48,47,34,10,32,32,32,32,32,32,32,32,32,32,32, 32,120,109,108,110,115,58,100,99,61,34,104,116,116,112,58, 47,47,112,117,114,108,46,111,114,103,47,100,99,47,101,108, 101,109,101,110,116,115,47,49,46,49,47,34,10,32,32,32, 32,32,32,32,32,32,32,32,32,120,109,108,110,115,58,73, 112,116,99,52,120,109,112,69,120,116,61,34,104,116,116,112, 58,47,47,105,112,116,99,46,111,114,103,47,115,116,100,47, 73,112,116,99,52,120,109,112,69,120,116,47,50,48,48,56, 45,48,50,45,50,57,47,34,62,10,32,32,32,32,32,32, 32,32,32,60,112,104,111,116,111,115,104,111,112,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,112,104,111,116,111,115,104,111,112,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 100,99,58,114,105,103,104,116,115,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,32,120,109,108,58,108,97,110,103, 61,34,120,45,100,101,102,97,117,108,116,34,62,67,111,112, 121,114,105,103,104,116,32,50,48,50,48,32,77,105,99,104, 97,101,108,32,83,119,101,101,116,60,47,114,100,102,58,108, 105,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60, 47,114,100,102,58,65,108,116,62,10,32,32,32,32,32,32, 32,32,32,60,47,100,99,58,114,105,103,104,116,115,62,10, 32,32,32,32,32,32,32,32,32,60,100,99,58,99,114,101, 97,116,111,114,62,10,32,32,32,32,32,32,32,32,32,32, 32,32,60,114,100,102,58,83,101,113,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,114,100,102,58, 108,105,62,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,99, 114,101,97,116,111,114,62,10,32,32,32,32,32,32,32,32, 32,60,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,10,32,32,32,32,32,32,60,47, 114,100,102,58,68,101,115,99,114,105,112,116,105,111,110,62, 10,32,32,32,60,47,114,100,102,58,82,68,70,62,10,60, 47,120,58,120,109,112,109,101,116,97,62,10,252,83,118,101, 0,0,2,109,80,76,84,69,0,0,0,0,0,0,21,21, 21,64,63,63,64,64,64,65,63,63,65,65,65,66,63,63, 66,66,66,67,62,62,67,67,67,68,62,62,68,68,68,69, 62,62,69,69,69,70,61,61,70,70,70,71,61,61,71,71, 71,72,61,61,72,72,72,73,73,73,74,60,60,74,74,74, 75,60,60,76,59,60,77,59,59,77,77,77,78,59,59,78, 78,78,79,58,59,79,79,79,80,58,58,80,58,59,81,58, 58,81,81,81,82,82,82,84,57,57,84,83,83,84,84,84, 85,56,57,85,85,85,87,87,87,88,55,56,88,88,88,89, 55,56,89,89,89,91,91,91,92,92,92,93,93,93,94,94, 94,95,95,95,96,96,96,98,98,98,99,52,53,100,51,52, 101,51,52,102,51,52,104,50,51,105,105,105,106,49,51,106, 72,73,108,108,108,109,109,109,111,48,49,111,111,111,112,112, 112,113,47,48,113,47,49,115,68,69,115,115,115,116,116,116, 117,67,68,117,117,117,118,67,68,118,118,118,123,123,123,124, 44,45,125,125,125,126,43,45,127,43,44,127,127,127,128,128, 128,130,42,43,131,131,131,132,132,132,133,40,42,133,133,133, 134,40,42,135,40,42,137,137,137,138,138,138,141,38,40,142, 55,56,143,143,143,144,37,39,144,144,144,145,145,145,147,36, 38,148,52,54,150,150,150,151,151,151,152,34,36,152,34,37, 152,152,152,154,33,36,154,34,36,154,154,154,155,33,36,155, 155,155,156,48,50,157,157,157,158,32,35,158,158,158,161,31, 34,164,164,164,165,43,46,165,165,165,166,29,32,166,166,166, 167,167,167,168,29,32,168,168,168,169,28,31,169,169,169,170, 28,31,171,171,171,173,40,42,174,174,174,177,38,41,177,177, 177,179,25,28,182,182,182,183,183,183,184,24,27,184,184,184, 185,34,37,185,185,185,186,186,186,187,23,26,189,189,189,190, 22,25,191,191,191,196,196,196,197,197,197,198,19,23,200,18, 22,200,200,200,202,18,21,203,17,21,203,203,203,204,204,204, 205,17,20,205,205,205,206,16,20,207,16,20,209,15,19,210, 15,19,210,210,210,211,15,19,211,211,211,216,216,216,217,13, 17,218,12,16,218,218,218,219,219,219,221,11,15,222,222,222, 223,11,15,224,14,19,224,224,224,225,10,14,225,225,225,227, 13,17,227,227,227,228,228,228,231,8,12,231,8,13,231,231, 231,232,232,232,233,7,12,234,7,11,234,7,12,235,235,235, 236,236,236,237,237,237,238,6,10,238,238,238,239,5,10,239, 239,239,240,5,10,240,240,240,241,241,241,243,243,243,244,4, 9,244,244,244,245,3,8,246,3,8,246,246,246,247,247,247, 248,2,7,249,249,249,251,2,7,251,251,251,253,253,253,254, 254,254,255,255,255,154,184,134,48,0,0,0,1,116,82,78, 83,0,64,230,216,102,0,0,4,21,73,68,65,84,120,218, 237,155,247,91,19,49,24,199,65,163,32,42,138,2,162,130, 117,71,197,189,21,247,86,176,90,183,226,94,184,247,22,183, 184,181,106,85,156,184,80,81,28,136,11,44,80,81,4,141, 208,191,201,92,174,150,227,218,203,93,73,142,234,99,222,31, 122,249,230,125,159,220,231,178,159,220,53,36,36,64,11,53, 104,33,102,153,0,16,0,2,192,52,128,208,32,153,0,16, 0,2,224,239,3,0,178,65,80,211,184,105,1,192,11,96, 106,176,1,46,4,3,160,121,255,73,243,87,239,59,105,207, 122,246,169,188,170,142,1,122,44,61,112,227,221,207,151,153, 231,14,172,91,148,50,106,32,140,118,215,37,192,160,244,215, 46,199,230,228,158,13,21,121,166,1,64,31,27,125,203,121, 116,178,79,174,27,214,206,34,3,174,129,36,231,154,72,63, 79,84,119,77,240,100,190,223,2,169,0,17,60,1,42,155, 4,4,16,62,40,245,248,195,210,8,126,0,17,191,128,97, 128,62,115,14,103,149,191,60,187,34,41,146,99,13,180,168, 48,4,0,83,119,102,150,230,95,90,55,46,134,119,31,104, 245,77,15,32,33,121,235,229,194,194,204,237,201,9,166,116, 194,182,95,40,0,49,99,215,92,202,47,205,220,109,237,110, 222,40,176,20,107,0,36,45,63,253,162,252,193,225,185,125, 77,30,134,157,10,1,216,91,92,233,174,133,185,28,86,46, 0,150,130,138,244,126,62,79,212,219,83,65,182,108,123,180, 198,19,123,125,76,0,157,11,10,222,224,153,32,165,216,223, 51,58,83,240,192,207,176,107,86,185,199,199,86,3,229,21, 210,76,228,220,56,203,143,109,116,74,119,201,182,106,182,185, 236,99,2,72,168,76,39,125,110,150,95,35,99,193,230,208, 238,116,196,199,4,16,89,53,64,15,192,226,210,6,32,62, 182,181,64,158,113,104,0,36,68,107,216,185,153,247,3,242, 194,175,5,160,187,55,112,51,239,7,244,107,128,62,27,252, 115,77,32,0,124,1,44,44,195,144,7,128,77,250,45,214, 158,9,169,19,17,15,128,236,112,64,91,11,168,83,177,17, 0,117,134,15,128,61,35,156,182,190,211,22,35,26,128,230, 201,136,15,64,180,61,219,102,209,156,106,41,203,49,47,0, 0,172,14,151,238,166,195,84,0,150,3,9,1,32,0,2, 6,224,118,16,160,183,31,16,77,32,0,4,128,0,16,0, 198,1,24,77,52,129,0,16,251,1,209,7,4,128,0,96, 6,112,89,88,0,180,79,74,13,3,56,108,44,0,218,103, 197,134,1,172,228,136,166,150,0,148,211,114,195,0,64,231, 136,134,166,105,239,11,140,3,80,143,104,104,154,254,198,196, 56,0,245,136,166,246,239,140,2,1,48,229,27,146,191,7, 64,247,251,1,190,22,248,251,130,32,127,198,83,191,141,100, 177,138,2,58,36,38,38,118,145,181,215,73,226,149,10,128, 174,56,221,152,3,192,80,68,236,243,157,85,97,30,71,46, 150,101,177,196,239,117,46,12,195,90,169,0,152,130,147,27, 56,0,12,67,127,236,154,76,48,156,136,121,196,175,116,66, 85,232,52,124,221,196,21,0,165,145,140,67,36,125,85,5, 128,210,160,42,148,39,192,182,168,9,167,240,229,174,164,195, 222,35,244,17,161,31,237,161,202,9,85,161,60,1,112,57, 177,95,17,42,146,244,120,172,103,252,64,104,25,84,57,161, 42,148,51,64,179,18,132,190,75,250,4,66,37,141,110,34, 116,31,170,156,80,21,202,23,32,106,61,190,60,194,178,41, 46,253,60,88,137,213,72,149,19,170,66,121,2,228,220,254, 46,245,172,29,88,78,199,215,217,160,23,254,221,165,114,66, 85,40,255,81,240,184,37,150,23,113,255,139,3,224,49,66, 207,85,78,168,10,229,13,80,118,44,30,171,184,50,156,204, 203,203,147,114,134,40,156,251,227,1,172,161,248,2,92,89, 60,115,88,28,209,11,170,135,58,218,163,112,146,120,165,226, 62,10,60,250,170,2,224,109,131,106,167,23,160,250,150,166, 0,116,196,19,64,206,4,201,174,224,236,49,186,0,7,187, 73,214,142,233,251,1,169,156,93,127,196,22,44,142,144,212, 18,156,58,83,211,233,71,201,246,138,105,63,80,163,6,238, 97,49,130,100,183,198,117,81,212,88,175,6,100,203,101,106, 130,193,184,132,181,30,29,143,211,31,26,200,249,215,165,54, 240,58,137,95,169,0,152,232,5,120,202,248,238,56,200,59, 34,1,240,63,2,120,172,158,201,90,252,197,67,0,8,128, 127,24,192,180,63,70,10,0,1,32,0,130,5,240,27,85, 126,181,220,185,1,241,173,0,0,0,0,73,69,78,68,174, 66,96,130, }; /* icon-lg.png */ static unsigned char icon_lg_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,2,0,0,0,2,0,8,6,0,0,0,244,120,212, 250,0,0,4,14,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,155,185,179,43, 36,206,131,212,166,166,146,14,254,53,148,180,108,82,209,132, 218,232,254,101,179,109,220,44,147,108,180,65,144,201,236,221, 157,105,38,51,227,252,164,105,41,62,20,65,16,193,168,224, 147,224,255,91,193,39,33,106,171,237,139,45,162,180,80,162, 4,131,40,248,208,250,71,161,210,23,9,235,185,51,179,187, 147,184,107,189,203,220,249,230,156,239,126,231,222,115,238,222, 11,144,184,44,91,150,222,37,2,44,26,174,45,229,211,226, 179,199,230,196,196,58,116,193,125,208,13,125,208,45,43,142, 149,42,149,38,1,27,227,194,191,218,237,239,32,198,222,215, 246,183,247,255,103,235,174,80,71,1,136,221,133,216,172,56, 202,34,226,101,0,254,21,197,178,93,128,4,65,251,200,9, 215,98,248,9,196,59,108,156,32,226,18,195,181,0,87,24, 158,15,240,178,207,153,145,50,136,95,69,44,40,170,140,254, 196,219,136,7,231,35,246,90,4,7,115,240,219,142,60,53, 168,173,41,34,203,69,201,54,171,154,78,35,211,189,131,251, 127,182,69,221,107,196,219,131,79,143,179,48,125,20,223,3, 184,246,151,42,114,150,225,135,16,159,85,228,220,116,136,175, 46,105,179,197,16,255,101,185,105,9,241,35,0,93,187,188, 133,114,10,241,62,196,99,85,123,188,28,232,116,169,170,55, 209,192,43,167,212,153,103,16,223,131,120,117,193,60,202,198, 238,68,252,181,49,95,156,10,117,126,82,156,12,230,15,30, 0,224,226,42,45,176,122,247,35,30,176,77,105,42,136,203, 141,87,104,54,199,242,136,248,184,230,22,102,2,125,238,45, 103,105,58,215,208,57,165,102,138,65,44,238,139,227,242,17, 86,167,62,196,87,169,158,151,66,253,95,45,183,20,198,37, 61,134,94,156,12,116,200,48,117,252,245,250,118,87,157,153, 8,226,146,57,23,11,26,140,37,47,86,181,241,66,200,127, 87,181,39,164,16,95,182,116,127,143,226,220,200,77,219,147, 202,1,159,191,159,26,229,80,147,31,147,237,92,62,196,21, 152,141,201,64,193,132,121,236,21,48,96,19,68,144,32,15, 105,124,91,96,163,167,10,26,232,104,161,232,165,104,161,248, 213,224,236,223,194,41,249,254,0,183,84,106,254,200,235,232, 209,48,66,166,255,35,240,208,170,194,239,104,85,35,188,12, 126,121,104,171,117,208,9,102,112,35,212,49,73,47,73,146, 131,248,28,34,147,228,48,25,33,163,32,146,39,201,83,100, 140,100,209,58,74,14,53,199,150,34,115,100,243,185,209,212, 121,1,35,82,159,55,139,188,139,232,119,65,198,254,103,100, 152,224,180,207,197,74,159,55,16,216,207,216,207,107,202,149, 215,110,94,58,125,110,87,139,187,70,86,159,187,214,115,233, 116,36,103,26,106,45,116,200,218,212,157,114,207,255,194,95, 231,215,176,95,231,55,90,12,254,7,126,3,127,235,219,86, 183,53,235,52,204,86,10,125,186,111,91,196,71,243,61,78, 100,62,165,45,85,108,97,179,163,162,89,53,86,250,2,31, 203,0,125,185,120,187,8,103,6,91,252,228,247,201,63,146, 107,201,247,146,31,38,127,227,222,228,62,225,206,115,159,114, 159,113,223,128,200,93,224,46,114,95,114,95,113,31,115,159, 71,106,212,121,239,52,107,238,175,163,177,10,230,105,151,81, 220,159,66,90,216,45,60,40,100,133,61,194,195,194,100,75, 79,232,21,134,132,9,97,47,122,118,55,171,19,141,23,93, 187,6,199,176,111,100,171,125,172,128,23,169,115,236,110,172, 179,214,225,63,84,70,150,6,39,124,166,227,239,51,3,78, 110,227,132,35,73,63,25,34,133,109,187,122,132,237,245,166, 118,126,75,61,218,175,129,198,115,241,108,60,5,98,124,95, 124,52,62,20,63,194,112,131,25,223,139,190,81,236,241,212, 114,233,178,203,14,226,140,105,157,180,181,154,234,138,195,201, 228,227,98,10,175,50,42,22,12,229,192,160,40,235,186,232, 187,28,209,166,14,181,151,104,229,0,176,123,50,56,194,111, 73,254,253,23,219,121,165,101,115,159,6,56,252,39,59,247, 90,182,57,15,224,172,3,208,251,104,203,54,128,103,227,189, 239,0,172,62,166,120,246,82,120,39,196,98,223,2,56,213, 131,195,193,87,79,26,207,171,31,235,245,91,120,110,37,222, 0,216,124,189,94,255,251,253,122,125,243,3,212,223,0,184, 160,255,3,255,37,120,11,197,99,214,203,0,0,0,56,101, 88,73,102,77,77,0,42,0,0,0,8,0,1,135,105,0, 4,0,0,0,1,0,0,0,26,0,0,0,0,0,2,160, 2,0,4,0,0,0,1,0,0,2,0,160,3,0,4,0, 0,0,1,0,0,2,0,0,0,0,0,40,48,151,191,0, 0,3,101,105,84,88,116,88,77,76,58,99,111,109,46,97, 100,111,98,101,46,120,109,112,0,0,0,0,0,60,120,58, 120,109,112,109,101,116,97,32,120,109,108,110,115,58,120,61, 34,97,100,111,98,101,58,110,115,58,109,101,116,97,47,34, 32,120,58,120,109,112,116,107,61,34,88,77,80,32,67,111, 114,101,32,54,46,48,46,48,34,62,10,32,32,32,60,114, 100,102,58,82,68,70,32,120,109,108,110,115,58,114,100,102, 61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46, 111,114,103,47,49,57,57,57,47,48,50,47,50,50,45,114, 100,102,45,115,121,110,116,97,120,45,110,115,35,34,62,10, 32,32,32,32,32,32,60,114,100,102,58,68,101,115,99,114, 105,112,116,105,111,110,32,114,100,102,58,97,98,111,117,116, 61,34,34,10,32,32,32,32,32,32,32,32,32,32,32,32, 120,109,108,110,115,58,112,104,111,116,111,115,104,111,112,61, 34,104,116,116,112,58,47,47,110,115,46,97,100,111,98,101, 46,99,111,109,47,112,104,111,116,111,115,104,111,112,47,49, 46,48,47,34,10,32,32,32,32,32,32,32,32,32,32,32, 32,120,109,108,110,115,58,100,99,61,34,104,116,116,112,58, 47,47,112,117,114,108,46,111,114,103,47,100,99,47,101,108, 101,109,101,110,116,115,47,49,46,49,47,34,10,32,32,32, 32,32,32,32,32,32,32,32,32,120,109,108,110,115,58,73, 112,116,99,52,120,109,112,69,120,116,61,34,104,116,116,112, 58,47,47,105,112,116,99,46,111,114,103,47,115,116,100,47, 73,112,116,99,52,120,109,112,69,120,116,47,50,48,48,56, 45,48,50,45,50,57,47,34,62,10,32,32,32,32,32,32, 32,32,32,60,112,104,111,116,111,115,104,111,112,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,112,104,111,116,111,115,104,111,112,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 100,99,58,114,105,103,104,116,115,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,32,120,109,108,58,108,97,110,103, 61,34,120,45,100,101,102,97,117,108,116,34,62,67,111,112, 121,114,105,103,104,116,32,50,48,50,48,32,77,105,99,104, 97,101,108,32,83,119,101,101,116,60,47,114,100,102,58,108, 105,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60, 47,114,100,102,58,65,108,116,62,10,32,32,32,32,32,32, 32,32,32,60,47,100,99,58,114,105,103,104,116,115,62,10, 32,32,32,32,32,32,32,32,32,60,100,99,58,99,114,101, 97,116,111,114,62,10,32,32,32,32,32,32,32,32,32,32, 32,32,60,114,100,102,58,83,101,113,62,10,32,32,32,32, 32,32,32,32,32,32,32,32,32,32,32,60,114,100,102,58, 108,105,62,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,99, 114,101,97,116,111,114,62,10,32,32,32,32,32,32,32,32, 32,60,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,78,101,119,32,73,109,97,103,101, 60,47,73,112,116,99,52,120,109,112,69,120,116,58,72,101, 97,100,108,105,110,101,62,10,32,32,32,32,32,32,60,47, 114,100,102,58,68,101,115,99,114,105,112,116,105,111,110,62, 10,32,32,32,60,47,114,100,102,58,82,68,70,62,10,60, 47,120,58,120,109,112,109,101,116,97,62,10,252,83,118,101, 0,0,42,218,73,68,65,84,120,218,237,221,11,144,28,245, 125,39,240,255,74,171,199,234,253,64,194,32,16,32,132,145, 99,30,54,38,16,99,3,43,201,56,166,202,198,212,69,185, 75,12,230,130,131,147,114,10,206,121,92,42,182,73,76,226, 34,54,118,168,96,135,68,201,149,109,72,25,56,238,184,114, 25,83,169,115,46,24,164,196,198,15,34,68,64,216,200,70, 32,16,8,131,132,30,160,149,86,90,73,236,245,175,157,85, 118,71,15,52,179,51,211,51,211,159,79,213,212,50,35,118, 102,127,253,239,158,255,183,187,255,253,239,174,4,229,54,104, 17,80,160,46,139,128,162,140,177,8,0,64,0,0,0,4, 0,0,64,0,0,0,4,0,0,64,0,0,0,4,0,0, 64,0,0,0,4,0,0,64,0,0,0,4,0,0,64,0, 0,0,4,0,0,64,0,0,0,4,0,0,64,0,0,0, 4,0,0,64,0,0,0,1,0,0,16,0,0,0,1,0, 0,16,0,0,0,1,0,0,16,0,0,0,1,0,0,16, 0,0,0,1,0,0,16,0,0,0,1,0,0,16,0,0, 0,1,0,0,168,94,87,11,252,13,131,154,1,0,28,1, 0,0,4,0,0,64,0,0,0,4,0,0,64,0,0,0, 4,0,0,64,0,0,0,4,0,0,16,0,0,0,1,0, 0,16,0,0,0,1,0,0,16,0,0,0,1,0,0,16, 0,0,0,1,0,0,16,0,0,0,1,0,0,16,0,0, 0,1,0,0,16,0,0,0,1,0,0,16,0,0,0,1, 0,0,16,0,0,64,0,0,0,4,0,0,64,0,0,0, 4,0,0,64,0,0,0,4,0,0,160,229,117,151,125,1, 244,246,246,22,246,217,199,28,115,76,122,229,149,87,74,187, 236,213,175,126,245,171,191,72,43,87,174,116,4,0,0,16, 0,0,0,1,0,0,16,0,168,155,50,159,255,83,191,250, 213,175,126,4,0,0,64,0,40,143,24,5,171,126,245,171, 95,253,234,71,0,0,0,4,0,0,64,0,0,0,4,128, 246,103,20,176,250,213,175,126,245,35,0,0,0,2,64,25, 24,5,172,126,245,171,95,253,8,0,0,128,0,0,0,8, 0,0,128,0,208,25,140,2,86,191,250,213,175,126,4,0, 0,64,0,40,3,163,128,213,175,126,245,171,31,1,0,0, 104,154,110,139,0,26,148,174,199,140,73,227,198,141,75,99, 199,142,77,93,93,93,249,107,175,191,254,122,26,24,24,72, 251,247,239,183,128,0,1,0,90,193,196,137,19,211,212,169, 83,211,180,105,211,210,148,41,83,242,199,228,201,147,243,159, 147,38,77,202,31,241,188,167,167,103,196,35,126,111,194,132, 9,7,126,142,31,63,62,239,248,135,58,253,67,217,186,117, 107,122,228,145,71,210,103,63,251,89,11,30,40,68,87,11, 252,13,131,69,126,120,111,111,175,181,160,19,87,236,172,243, 157,62,125,122,154,53,107,86,154,57,115,102,254,152,49,99, 70,254,51,94,143,71,116,244,67,29,126,60,162,211,110,182, 197,139,23,107,44,40,200,202,149,43,29,1,128,118,19,29, 251,113,199,29,151,230,206,157,155,142,61,246,216,252,231,156, 57,115,210,236,217,179,243,193,69,241,239,113,232,29,0,1, 160,229,68,71,85,230,107,97,223,168,254,248,247,249,243,231, 231,143,121,243,230,165,227,143,63,62,239,244,227,103,28,106, 111,55,113,254,63,198,5,96,253,87,191,250,5,0,200,196, 94,251,130,5,11,210,169,167,158,154,255,60,233,164,147,210, 137,39,158,152,159,95,111,150,193,193,193,180,115,231,206,212, 215,215,151,118,236,216,145,94,123,237,181,252,191,251,251,251, 243,199,174,93,187,70,252,28,122,236,217,179,231,192,35,6, 247,237,221,187,247,192,99,223,190,125,249,35,6,252,197,251, 135,21,43,86,104,112,64,0,160,156,169,127,209,162,69,249, 227,172,179,206,202,247,238,227,124,124,35,58,244,109,219,182, 229,143,237,219,183,231,131,238,226,231,208,107,67,175,71,103, 31,143,232,236,135,58,105,0,1,0,70,233,148,83,78,73, 103,159,125,118,254,56,227,140,51,234,54,249,71,116,216,47, 190,248,98,218,180,105,83,254,216,188,121,115,254,24,250,239, 56,180,24,123,223,0,8,0,45,167,19,207,127,69,7,127, 222,121,231,165,243,207,63,63,189,237,109,111,203,71,215,143, 166,147,127,254,249,231,211,134,13,27,242,159,27,55,110,204, 59,253,159,253,236,103,249,94,59,214,127,245,171,31,1,128, 130,247,242,227,114,182,11,46,184,32,63,143,95,173,56,127, 254,236,179,207,166,103,158,121,38,61,253,244,211,105,253,250, 245,249,35,14,211,3,32,0,116,228,222,114,187,166,224,184, 244,238,125,239,123,95,90,178,100,73,126,30,255,104,197,97, 249,232,228,215,174,93,155,239,209,175,90,181,42,61,247,220, 115,249,8,121,172,255,234,87,63,2,0,45,40,46,97,123, 215,187,222,149,222,255,254,247,167,115,207,61,247,168,46,105, 219,189,123,119,122,226,137,39,210,154,53,107,210,227,143,63, 158,158,124,242,201,124,143,223,23,0,128,0,80,152,101,203, 150,141,120,62,212,25,85,14,84,107,228,235,195,59,193,102, 126,110,53,175,119,119,119,231,135,248,63,240,129,15,228,215, 225,191,145,56,124,255,216,99,143,165,127,249,151,127,201,59, 255,225,163,252,99,230,189,161,0,80,249,217,173,190,28,234, 253,250,161,150,65,217,150,67,59,172,255,141,122,221,250,159, 10,95,254,101,103,42,224,2,167,2,110,245,61,224,152,78, 247,210,75,47,77,87,95,125,245,17,71,239,199,225,251,216, 187,255,238,119,191,155,63,94,126,249,229,142,168,191,17,42, 231,1,40,243,84,192,14,129,171,191,232,250,77,5,76,97, 90,121,227,127,203,91,222,146,62,254,241,143,167,211,79,63, 253,176,255,79,12,220,251,167,127,250,167,116,255,253,247,215, 84,139,36,110,253,87,191,250,17,0,104,17,113,94,255,195, 31,254,112,254,56,212,92,250,49,171,93,236,229,127,253,235, 95,207,207,235,3,32,0,80,165,86,59,4,24,183,189,189, 241,198,27,243,73,123,14,213,241,255,227,63,254,99,186,227, 142,59,142,250,16,127,187,213,79,185,215,127,245,171,95,0, 160,148,226,238,121,55,223,124,115,126,77,127,165,135,30,122, 40,45,95,190,60,159,132,7,0,1,128,14,17,55,221,249, 203,191,252,203,252,38,60,195,197,68,60,95,252,226,23,243, 209,252,0,8,0,116,152,79,125,234,83,7,117,254,63,254, 241,143,211,13,55,220,224,16,29,128,0,64,189,181,66,231, 26,151,161,189,251,221,239,30,241,218,35,143,60,146,62,249, 201,79,230,183,180,237,244,250,41,247,250,175,126,245,151,217, 24,139,160,196,233,47,155,224,231,163,31,253,232,136,215,126, 250,211,159,166,235,175,191,190,225,157,63,0,2,64,105,213, 235,214,184,181,138,105,125,135,207,236,55,48,48,144,62,251, 217,207,142,152,169,175,147,235,167,220,235,191,250,213,47,0, 80,90,17,0,134,251,246,183,191,157,223,152,7,56,122,199, 31,127,124,90,176,96,129,5,65,219,49,6,160,196,22,45, 90,52,226,121,204,234,7,28,185,179,63,237,180,211,242,25, 50,223,252,230,55,231,63,99,254,140,213,171,87,167,63,248, 131,63,176,128,16,0,104,15,115,231,206,29,241,60,110,226, 3,252,92,156,30,139,78,126,168,163,143,159,113,51,171,67, 137,127,3,1,128,163,86,244,40,216,113,227,198,141,120,190, 99,199,142,82,213,79,185,215,255,35,117,246,67,123,246,71, 43,254,223,56,58,80,205,100,89,174,2,176,253,11,0,20, 38,166,247,141,185,255,135,196,220,255,251,246,237,179,96,232, 248,61,251,232,224,135,14,229,87,219,217,87,234,235,235,203, 175,158,153,56,113,162,133,139,0,192,209,41,122,46,236,232, 236,135,31,5,136,203,2,155,25,0,204,5,110,253,111,116, 251,143,118,207,254,80,157,253,83,79,61,149,119,248,63,249, 201,79,242,159,27,55,110,180,254,171,95,0,160,253,142,0, 12,119,168,187,255,65,59,237,217,15,63,95,223,74,157,61, 8,0,8,0,160,179,7,1,128,98,85,30,238,143,83,0, 160,179,7,1,128,6,43,250,252,87,209,1,192,249,63,235, 255,161,58,251,161,142,190,17,157,125,60,90,229,182,214,174, 2,176,253,11,0,20,198,41,0,138,222,179,47,75,103,15, 2,0,35,180,194,85,0,69,30,1,48,10,88,103,95,230, 206,222,85,0,182,127,1,128,194,188,254,250,235,35,158,15, 159,19,0,106,21,19,226,12,117,244,58,123,16,0,104,65, 78,1,160,179,7,1,0,71,0,28,1,160,169,157,253,206, 157,59,243,142,94,103,15,2,64,233,20,125,254,171,50,0, 52,251,8,128,243,127,229,219,179,31,186,236,78,103,111,253, 183,253,11,0,20,168,242,20,128,35,0,58,123,157,61,8, 0,52,65,209,163,96,139,30,3,96,20,112,185,59,123,163, 224,213,111,251,23,0,40,105,0,160,253,58,251,161,115,246, 246,236,65,0,160,141,25,4,216,153,157,253,208,245,246,58, 123,64,0,64,0,208,217,235,236,1,1,160,85,180,218,85, 0,205,14,0,206,255,149,187,179,55,10,94,253,8,0,56, 2,192,176,206,126,248,148,185,246,236,1,1,160,3,21,61, 10,118,112,112,176,208,0,96,20,112,74,191,253,219,191,93, 218,206,222,40,120,245,59,10,32,0,208,230,71,0,78,57, 229,148,244,129,15,124,32,157,113,198,25,105,206,156,57,121, 71,22,239,213,213,213,149,63,56,188,95,251,181,95,171,203, 251,196,50,63,231,156,115,242,7,157,97,96,96,32,245,247, 247,231,225,110,227,198,141,105,195,134,13,105,237,218,181,105, 245,234,213,105,219,182,109,22,16,2,0,245,59,2,80,109, 167,127,205,53,215,164,119,188,227,29,105,194,132,9,22,38, 212,217,248,241,227,243,199,244,233,211,211,188,121,243,210,121, 231,157,119,224,223,214,173,91,151,238,191,255,254,252,33,12, 32,0,208,148,35,0,177,135,249,123,191,247,123,249,23,146, 189,123,40,198,194,133,11,243,199,71,63,250,209,60,4,220, 117,215,93,249,81,2,16,0,218,68,209,231,191,42,143,0, 28,169,67,159,61,123,118,186,233,166,155,210,169,167,158,170, 227,135,86,249,2,239,238,78,151,94,122,105,122,239,123,223, 155,238,189,247,222,116,219,109,183,165,93,187,118,249,254,67, 0,160,62,1,224,67,31,250,80,250,205,223,252,205,195,30, 33,136,247,137,115,149,79,63,253,116,250,209,143,126,148,158, 120,226,137,244,236,179,207,230,135,38,219,229,203,168,89,122, 123,123,243,65,122,141,26,160,55,110,220,184,212,211,211,147, 102,205,154,149,230,207,159,159,239,37,198,81,155,69,139,22, 29,118,166,199,45,91,182,228,225,110,213,170,85,26,168,133, 84,211,150,241,252,87,126,229,87,242,245,75,91,114,180,90, 97,87,110,176,200,15,143,13,166,40,69,143,130,253,147,63, 249,147,180,100,201,146,3,207,63,243,153,207,164,21,43,86, 28,120,30,29,254,23,191,248,197,124,112,223,161,194,193,222, 189,123,211,15,126,240,131,244,213,175,126,53,61,247,220,115, 109,87,127,209,154,89,255,140,25,51,210,210,165,75,211,101, 151,93,150,119,38,135,10,113,119,222,121,103,186,253,246,219, 71,53,54,68,251,55,190,254,86,108,203,118,109,255,149,43, 87,150,58,0,180,194,228,239,127,90,228,135,159,124,242,201, 133,125,246,164,73,147,10,221,67,190,248,226,139,243,193,124, 67,254,249,159,255,57,223,115,15,19,39,78,76,119,220,113, 71,90,176,96,193,65,157,255,190,125,251,210,215,191,254,245, 244,187,191,251,187,233,193,7,31,76,175,190,250,106,91,214, 95,180,102,214,191,123,247,238,244,228,147,79,166,111,126,243, 155,121,27,159,118,218,105,105,218,180,105,255,177,39,144,181, 241,217,103,159,157,78,60,241,196,244,189,239,125,239,160,241, 33,157,184,254,183,107,251,183,98,91,182,107,251,15,125,223, 149,149,153,95,74,236,112,167,0,162,243,191,251,238,187,211, 177,199,30,123,208,255,255,216,99,143,165,15,126,240,131,105, 249,242,229,45,251,197,194,145,219,60,246,122,174,190,250,234, 244,181,175,125,237,160,27,66,197,17,161,63,255,243,63,207, 207,45,163,45,17,0,40,211,10,145,29,246,255,251,191,255, 251,252,48,227,112,241,229,242,165,47,125,41,223,235,119,94, 191,253,197,233,155,56,68,28,87,116,84,30,134,141,203,205, 62,249,201,79,26,236,169,45,233,112,78,1,20,120,10,160, 232,142,244,194,11,47,204,15,241,15,249,206,119,190,147,119, 240,195,95,27,250,130,185,238,186,235,210,67,15,61,212,81, 245,23,173,21,234,223,180,105,83,126,234,231,252,243,207,207, 175,55,31,18,167,134,34,12,62,250,232,163,29,93,127,39, 181,127,145,109,217,174,237,239,20,0,252,187,11,46,184,32, 31,240,87,217,249,199,33,198,152,129,140,206,20,29,71,4, 188,152,105,110,184,43,175,188,50,157,123,238,185,22,144,182, 164,67,185,10,160,196,87,1,252,241,31,255,113,62,154,120, 72,156,211,31,126,169,95,28,246,191,246,218,107,235,214,249, 159,117,214,89,249,53,203,49,64,41,230,21,136,89,206,168, 93,76,21,27,151,240,197,184,140,111,125,235,91,233,241,199, 31,31,213,251,205,157,59,55,253,205,223,252,77,190,94,14, 137,247,191,234,170,171,26,178,183,230,42,128,198,213,223,236, 182,108,215,246,119,21,64,241,254,180,200,15,47,243,85,0, 23,93,116,209,136,195,253,195,207,19,198,0,163,191,250,171, 191,170,203,97,255,201,147,39,231,151,28,198,141,111,226,90, 230,169,83,167,30,246,154,116,170,216,120,179,101,24,203,50, 150,105,4,171,152,164,233,225,135,31,206,143,218,212,98,231, 206,157,121,216,139,73,101,134,130,96,172,163,49,40,52,222, 183,211,214,255,162,53,178,254,102,183,101,187,182,191,83,0, 148,214,145,6,6,197,222,100,92,102,84,143,206,255,214,91, 111,205,199,27,208,88,177,140,99,89,199,50,175,213,154,53, 107,242,105,101,135,187,252,242,203,243,169,159,105,47,218,18, 1,128,170,197,117,254,159,250,212,167,234,242,94,127,244,71, 127,52,98,174,1,26,43,150,117,44,243,209,136,73,100,134, 207,43,31,71,26,174,184,226,10,11,183,13,105,75,142,196, 5,162,5,42,250,252,215,225,142,0,124,227,27,223,168,203, 161,185,56,231,95,185,231,255,194,11,47,164,111,127,251,219, 249,207,202,235,150,169,78,124,153,159,112,194,9,233,61,239, 121,79,254,115,248,145,128,88,246,181,142,9,136,83,8,95, 249,202,87,210,13,55,220,112,224,181,75,46,185,36,125,249, 203,95,174,235,157,231,202,62,23,124,51,234,111,86,91,106, 127,71,0,104,183,198,63,196,220,254,241,133,241,119,127,247, 119,117,121,255,56,47,93,217,249,199,245,202,49,109,176,206, 127,244,98,25,198,178,140,101,26,203,246,72,203,190,90,113, 57,217,240,145,228,49,153,76,116,28,180,31,109,137,0,208, 130,134,143,208,109,149,0,16,115,251,215,107,134,191,24,237, 63,92,236,249,155,61,176,254,98,153,198,178,61,210,178,175, 86,12,2,189,239,190,251,70,188,86,239,78,163,232,245,191, 44,219,127,51,218,82,251,11,0,180,153,41,83,166,28,244, 69,17,55,246,169,151,184,212,175,242,8,0,141,81,185,108, 43,151,125,45,30,120,224,129,17,71,106,226,106,131,153,51, 103,90,216,109,72,91,34,0,48,194,113,199,29,55,226,121, 92,87,94,203,93,253,14,167,242,58,127,135,253,27,167,114, 217,214,99,142,133,237,219,183,31,52,7,68,220,142,150,246, 163,45,17,0,24,33,174,33,31,174,81,247,168,167,125,173, 94,189,122,196,243,184,23,61,218,18,1,128,81,42,122,20, 236,132,9,19,70,60,95,191,126,189,70,97,132,117,235,214, 141,120,126,168,251,207,183,235,250,95,182,237,191,145,109,169, 253,5,0,218,76,229,108,124,79,61,245,148,133,194,8,149, 115,202,155,68,70,91,34,0,80,7,69,142,130,61,212,84, 188,101,159,22,147,131,109,221,186,117,196,243,202,129,163,237, 186,254,151,113,251,111,100,91,106,127,1,128,54,18,151,142, 85,78,4,100,12,0,149,250,251,251,71,60,239,233,233,177, 80,180,37,2,0,237,44,46,249,171,228,50,61,42,85,222, 88,200,29,28,181,37,2,0,29,122,84,0,0,1,128,6, 51,10,22,235,191,250,213,143,0,0,0,52,77,169,239,6, 184,108,217,178,67,38,210,202,209,169,157,250,122,165,161,127, 111,212,251,83,140,86,95,79,188,222,220,215,43,219,178,200, 239,159,248,183,86,88,14,101,213,213,2,127,195,96,145,31, 222,219,219,91,232,23,115,145,43,227,138,21,43,70,60,95, 188,120,113,67,223,255,207,254,236,207,108,113,13,52,252,150, 175,245,108,207,70,173,39,69,175,255,173,16,204,154,93,127, 163,183,249,118,107,255,149,43,87,150,250,59,195,41,0,0, 16,0,0,0,1,128,134,114,46,10,235,191,250,213,143,0, 0,0,52,77,183,69,80,156,178,15,130,162,61,85,14,36, 163,189,219,178,168,129,128,190,255,28,1,0,0,4,0,0, 64,0,0,0,26,194,24,128,2,57,255,69,59,42,114,242, 24,70,167,149,38,2,242,253,231,8,0,0,32,0,148,139, 185,243,177,254,171,95,253,8,0,0,128,0,0,0,8,0, 0,128,0,208,25,140,130,197,250,175,126,245,35,0,0,0, 2,64,25,24,5,139,245,95,253,234,71,0,160,112,227,198, 141,179,16,56,226,58,49,48,48,96,161,128,0,64,167,233, 233,233,177,16,56,226,58,209,223,223,111,161,128,0,64,167, 153,53,107,150,133,192,17,215,137,190,190,62,11,5,4,0, 70,171,213,70,193,206,159,63,95,163,112,196,117,98,227,198, 141,29,187,254,151,125,251,87,191,0,64,137,45,92,184,208, 66,224,136,235,196,134,13,27,44,20,16,0,24,173,86,27, 5,123,206,57,231,212,245,253,42,7,140,141,29,59,86,163, 55,72,229,178,173,215,96,189,202,117,98,237,218,181,29,187, 254,151,125,251,87,191,0,64,137,45,90,180,40,205,152,49, 163,110,239,183,101,203,150,17,207,79,56,225,4,11,185,65, 42,151,109,229,178,175,69,172,11,177,78,12,183,122,245,106, 11,27,4,0,58,113,47,114,233,210,165,117,123,191,199,30, 123,108,196,243,247,188,231,61,105,204,24,171,92,221,55,226, 108,153,198,178,61,210,178,175,69,172,11,195,143,44,172,91, 183,46,109,219,182,205,2,7,1,128,78,116,217,101,151,165, 174,174,174,186,188,215,183,190,245,173,131,246,82,175,190,250, 234,116,210,73,39,57,29,80,167,192,22,203,50,150,105,229, 17,128,202,101,95,173,88,7,98,93,24,238,254,251,239,183, 208,161,131,116,91,4,197,105,197,81,176,49,234,251,226,139, 47,78,43,87,174,28,245,123,61,254,248,227,233,59,223,249, 78,186,240,194,11,71,132,128,223,248,141,223,208,248,13,20, 203,60,150,253,104,196,58,48,252,10,128,125,251,246,213,61, 0,24,5,175,126,28,1,160,197,92,115,205,53,117,155,21, 240,243,159,255,124,90,191,126,189,133,218,36,177,172,99,153, 143,70,180,125,172,3,149,123,255,14,255,131,0,64,157,180, 234,40,216,121,243,230,165,43,175,188,178,46,239,181,115,231, 206,116,221,117,215,229,123,165,52,126,207,63,150,117,44,243, 209,136,182,143,117,96,200,254,253,251,211,93,119,221,85,154, 245,191,236,219,191,250,203,195,41,0,14,233,138,43,174,72, 171,86,173,74,107,214,172,169,75,8,248,244,167,63,157,206, 58,235,172,116,233,165,151,166,179,207,62,59,205,158,61,59, 141,31,63,222,130,30,133,184,212,47,70,251,199,128,191,56, 231,63,218,195,254,225,204,51,207,204,219,126,184,123,239,189, 183,174,19,0,1,173,19,0,6,45,6,66,116,38,209,49, 135,24,96,22,157,246,239,252,206,239,164,205,155,55,215,229, 253,163,131,26,222,73,197,30,64,153,207,3,182,90,253,115, 230,204,201,219,124,248,0,205,88,39,110,187,237,54,27,7, 52,70,87,145,31,238,20,0,7,220,116,211,77,105,112,112, 112,68,7,117,243,205,55,167,105,211,166,89,56,29,46,218, 56,218,122,248,97,217,88,23,98,157,216,181,107,151,5,4, 29,72,0,40,80,171,237,253,198,33,255,59,239,188,115,196, 107,49,18,252,214,91,111,205,247,14,59,189,254,178,182,127, 180,109,180,113,229,188,255,177,46,196,58,81,150,245,191,236, 219,191,250,5,0,74,238,246,219,111,79,15,62,248,224,65, 33,96,249,242,229,249,249,97,58,75,180,105,180,109,101,231, 31,235,64,172,11,128,0,64,3,180,226,40,216,56,236,251, 185,207,125,46,61,252,240,195,7,253,173,183,220,114,75,62, 233,76,189,46,17,52,10,186,184,250,163,13,163,45,163,77, 43,255,142,104,251,88,7,134,159,14,42,203,250,95,246,237, 95,253,2,0,37,23,147,190,92,127,253,245,7,29,9,136, 193,97,87,93,117,85,190,103,216,219,219,91,183,25,3,105, 158,104,179,104,187,104,195,104,203,202,25,25,163,205,163,237, 99,29,0,58,155,203,0,57,108,8,184,241,198,27,243,203, 191,226,186,240,225,157,125,92,35,126,195,13,55,228,183,134, 189,239,190,251,210,3,15,60,144,182,111,223,110,161,181,176, 184,177,79,204,237,31,211,251,86,30,238,15,177,183,31,231, 252,35,24,52,122,207,31,16,0,104,113,209,17,196,37,96, 113,233,222,39,62,241,137,3,151,8,14,137,142,228,218,107, 175,77,31,251,216,199,242,219,196,198,157,226,226,134,49,17, 12,182,110,221,154,250,251,251,211,222,189,123,45,200,38,138, 67,251,61,61,61,105,214,172,89,121,251,44,92,184,48,191, 165,111,220,213,239,112,247,95,136,75,253,98,180,127,35,7, 252,1,2,0,195,180,203,40,216,232,24,226,112,241,71,62, 242,145,116,249,229,151,31,212,145,196,243,183,190,245,173,249, 131,246,17,51,252,197,36,63,17,242,138,184,212,207,40,120, 245,35,0,208,6,162,131,248,235,191,254,235,244,141,111,124, 35,159,41,238,146,75,46,73,221,221,86,159,118,52,116,99, 159,152,222,215,12,127,32,0,80,128,118,156,9,47,58,140, 47,124,225,11,233,203,95,254,114,30,2,226,17,135,153,105, 125,113,122,38,58,254,86,185,177,143,153,32,213,239,40,128, 0,64,27,138,14,228,158,123,238,201,31,51,103,206,60,112, 158,57,206,59,199,32,193,41,83,166,228,231,162,205,247,223, 92,113,127,128,24,123,209,215,215,151,135,181,24,143,49,52, 62,195,221,252,0,1,128,186,135,129,184,18,32,30,246,0, 212,15,180,7,243,0,0,128,0,64,51,25,5,172,126,245, 171,95,253,8,0,0,128,0,80,6,230,2,87,191,250,213, 175,126,4,0,0,64,0,0,0,4,0,0,64,0,232,12, 70,1,171,95,253,234,87,63,2,0,0,32,0,148,129,81, 192,234,87,191,250,213,143,0,0,0,8,0,0,128,0,0, 0,8,0,157,193,40,96,245,171,95,253,234,71,0,0,0, 4,128,50,48,10,88,253,234,87,191,250,17,0,0,0,1, 0,0,16,0,0,128,58,234,46,115,241,203,150,45,27,241, 124,104,84,106,229,185,169,70,190,30,255,93,196,231,30,202, 208,191,55,235,239,169,252,183,162,150,131,215,203,185,254,23, 253,122,81,235,127,229,54,95,230,229,95,118,93,217,99,176, 204,11,160,183,183,183,180,181,175,88,177,98,196,243,197,139, 23,219,34,192,54,95,26,43,87,174,108,133,62,184,48,78, 1,20,200,40,96,245,171,95,253,234,71,0,0,0,4,0, 0,64,0,0,0,4,128,206,96,46,112,245,171,95,253,234, 71,0,0,0,4,128,50,48,10,88,253,234,87,191,250,17, 0,0,0,1,0,0,16,0,0,0,1,160,51,24,5,172, 126,245,171,95,253,8,0,0,128,0,80,6,70,1,171,95, 253,234,87,63,2,0,0,32,0,0,0,2,0,0,32,0, 116,6,163,128,213,175,126,245,171,31,1,0,0,16,0,202, 192,40,96,245,171,95,253,234,71,0,0,0,4,0,0,64, 0,0,0,4,128,206,96,20,176,250,213,175,126,245,35,0, 0,0,2,64,25,24,5,172,126,245,171,95,253,8,0,0, 128,0,0,0,8,0,0,128,0,208,25,140,2,86,191,250, 213,175,126,4,0,0,64,0,40,3,163,128,213,175,126,245, 171,31,1,0,0,16,0,0,0,1,0,0,16,0,58,131, 81,192,234,87,191,250,213,143,0,0,0,8,0,101,96,20, 176,250,213,175,126,245,35,0,0,0,2,0,0,32,0,0, 0,2,64,103,48,10,88,253,234,87,191,250,17,0,0,0, 1,160,12,140,2,86,191,250,213,175,126,138,210,109,17,48, 100,197,138,21,22,2,148,108,155,95,188,120,177,5,225,8, 0,0,32,0,0,0,2,0,245,103,20,44,224,251,143,162, 24,3,192,1,206,5,66,103,171,28,231,99,155,119,4,128, 130,24,5,172,126,245,171,95,253,8,0,0,128,0,0,0, 8,0,0,128,0,208,25,204,5,174,126,245,171,95,253,8, 0,0,128,0,80,6,70,1,171,95,253,234,87,63,2,0, 0,32,0,0,0,2,0,0,32,0,116,6,163,128,213,175, 126,245,171,31,1,0,0,16,0,202,192,40,96,245,171,95, 253,234,71,0,0,0,154,166,212,183,3,94,182,108,217,136, 231,67,231,164,42,147,105,35,95,143,255,46,226,115,143,148, 200,155,245,247,84,254,91,81,203,161,232,229,95,150,122,91, 109,253,47,250,245,162,214,255,202,117,175,172,235,63,41,117, 101,143,193,50,47,128,222,222,222,194,62,123,248,198,87,132, 162,239,13,94,116,253,69,83,191,250,155,93,127,209,219,124, 171,181,255,202,149,43,91,161,15,46,140,83,0,5,50,10, 88,253,234,87,191,250,17,0,0,0,1,160,12,140,2,86, 191,250,213,175,126,4,0,0,64,0,0,0,4,0,0,64, 0,232,12,70,1,171,95,253,234,87,63,2,0,0,32,0, 148,129,81,192,234,87,191,250,213,143,0,0,0,8,0,0, 128,0,0,0,8,0,157,193,40,96,245,171,95,253,234,71, 0,0,0,4,128,50,48,10,88,253,234,87,191,250,17,0, 0,0,1,0,0,16,0,0,0,1,160,51,24,5,172,126, 245,171,95,253,8,0,0,128,0,80,6,70,1,171,95,253, 234,87,63,2,0,0,32,0,0,0,2,0,0,32,0,116, 6,163,128,213,175,126,245,171,31,1,0,0,16,0,202,192, 40,96,245,171,95,253,234,71,0,160,233,6,6,6,70,60, 31,55,110,156,133,2,29,170,114,251,174,220,254,17,0,40, 145,254,254,254,17,207,123,122,122,44,20,232,80,149,219,119, 229,246,143,0,64,137,244,245,245,141,120,62,107,214,44,11, 5,58,84,229,246,93,185,253,35,0,208,68,69,143,130,221, 184,113,227,136,231,243,231,207,47,85,253,101,111,127,245,151, 171,254,202,237,187,114,251,215,254,2,0,37,178,97,195,134, 17,207,23,46,92,104,161,64,135,170,220,190,43,183,127,4, 0,154,168,232,81,176,107,215,174,29,241,252,156,115,206,41, 85,253,101,111,127,245,151,171,254,202,237,187,114,251,215,254, 2,0,37,178,122,245,234,17,207,23,45,90,148,102,204,152, 97,193,64,135,137,237,58,182,239,35,109,255,8,0,148,200, 182,109,219,210,186,117,235,14,60,31,59,118,108,90,186,116, 169,5,3,29,38,182,235,216,190,135,196,118,31,219,63,2, 0,37,118,255,253,247,143,120,126,217,101,151,165,174,174,46, 11,6,58,68,108,207,177,93,31,105,187,71,0,160,201,90, 97,20,108,124,17,236,219,183,239,192,243,24,41,124,241,197, 23,151,166,254,178,183,191,250,59,191,254,216,158,135,95,1, 16,219,123,43,4,0,87,1,8,0,20,44,14,3,86,126, 25,92,115,205,53,102,5,132,14,16,219,113,108,207,149,161, 223,225,127,4,128,130,181,202,40,216,187,238,186,43,237,223, 191,255,192,243,121,243,230,165,43,175,188,178,52,245,151,189, 253,213,223,185,245,199,118,28,219,243,144,216,206,99,123,215, 254,8,0,228,98,66,144,123,239,189,119,196,107,87,92,113, 69,58,243,204,51,45,28,104,83,177,253,198,118,60,92,108, 231,69,79,0,132,0,64,139,185,237,182,219,210,150,45,91, 14,60,143,17,195,159,254,244,167,211,156,57,115,44,28,104, 51,115,231,206,205,183,223,225,35,255,99,251,142,237,28,4, 0,70,216,181,107,87,186,233,166,155,210,224,224,224,129,215, 226,16,221,205,55,223,156,166,77,155,102,1,65,155,136,237, 245,47,254,226,47,70,28,98,143,237,58,182,239,216,206,65, 0,104,1,173,54,10,118,213,170,85,233,206,59,239,28,241, 90,140,30,190,245,214,91,27,114,36,192,40,112,245,171,191, 190,98,59,141,237,181,114,222,255,216,174,99,251,214,254,8, 0,28,214,237,183,223,158,30,124,240,193,131,66,192,242,229, 203,141,9,128,22,22,219,103,108,167,149,157,127,108,207,177, 93,131,0,208,66,90,113,20,108,28,42,252,220,231,62,151, 30,126,248,225,131,254,214,91,110,185,37,93,125,245,213,117, 187,68,208,40,112,245,171,127,244,98,123,140,237,50,182,207, 202,247,140,237,56,182,231,225,167,246,180,63,2,0,135,21, 19,133,92,127,253,245,7,29,9,136,1,69,87,93,117,85, 190,55,209,219,219,107,198,64,40,80,108,127,177,29,198,246, 24,219,229,240,1,127,67,123,254,177,29,15,159,232,11,134, 235,182,8,56,92,8,184,241,198,27,243,75,134,226,90,226, 225,157,125,92,87,124,195,13,55,228,183,19,189,239,190,251, 210,3,15,60,144,182,111,223,110,161,65,19,196,141,125,98, 110,255,152,222,183,242,112,127,136,189,253,56,231,31,193,160, 21,247,252,17,0,104,3,241,229,17,151,13,61,254,248,227, 233,19,159,248,68,154,61,123,246,136,127,143,47,159,107,175, 189,54,125,236,99,31,203,111,45,26,119,23,139,155,140,68, 48,216,186,117,107,234,239,239,79,123,247,238,181,32,161,6, 113,104,191,167,167,39,205,154,53,43,223,214,22,46,92,152, 223,210,55,238,234,87,185,183,63,36,46,245,139,209,254,173, 54,224,143,214,20,187,117,165,142,136,113,8,141,55,54,105, 210,164,244,145,143,124,36,93,126,249,229,135,253,242,1,138, 17,51,252,197,36,63,17,216,93,234,119,244,86,174,92,217, 10,125,176,0,32,0,180,135,56,252,31,179,139,93,114,201, 37,169,187,219,1,36,40,210,208,141,125,98,122,95,51,252, 9,0,2,64,27,5,128,24,5,219,174,215,194,206,156,57, 51,15,1,241,136,67,147,64,243,196,169,182,232,248,219,249, 198,62,173,240,253,87,246,0,96,23,142,154,196,151,206,61, 247,220,147,63,34,12,12,157,155,140,115,149,113,148,96,202, 148,41,249,249,203,241,227,199,91,88,80,131,129,129,129,124, 28,77,95,95,95,190,119,31,99,107,134,198,218,184,155,31, 2,0,45,19,6,226,74,128,120,180,219,30,64,217,247,128, 212,175,126,202,203,60,0,0,32,0,208,76,230,66,87,191, 250,213,175,126,4,0,0,64,0,40,3,115,161,171,95,253, 234,87,63,2,0,0,32,0,0,0,2,0,0,32,0,116, 6,163,128,213,175,126,245,171,31,1,0,0,104,154,152,9, 176,171,224,191,161,176,123,17,44,91,182,236,144,137,180,114, 116,170,215,189,222,136,215,135,254,205,242,241,186,245,191,249, 127,79,139,40,244,94,60,93,101,95,0,110,6,148,212,175, 126,245,171,191,148,245,183,192,205,128,10,229,20,0,0,8, 0,0,128,0,64,67,25,5,172,126,245,171,95,253,8,0, 0,128,0,80,6,230,2,87,191,250,213,175,126,4,0,0, 64,0,0,0,4,0,0,64,0,232,12,70,1,171,95,253, 234,87,63,2,0,0,208,52,221,22,65,113,138,152,10,115, 238,238,61,233,151,182,108,171,235,123,14,102,19,74,239,235, 234,74,3,99,198,164,109,227,199,165,45,227,199,231,143,190, 113,221,45,87,255,225,156,180,115,87,250,175,207,62,63,170, 247,120,53,171,253,75,167,45,104,106,251,183,82,123,54,98, 253,111,231,250,222,200,233,147,38,165,211,159,122,166,234,223, 91,51,99,106,90,63,121,178,239,63,4,0,170,243,142,109, 219,211,117,79,175,111,202,103,237,201,190,96,159,239,153,152, 158,152,62,45,173,201,31,83,179,47,220,241,45,185,92,126, 249,165,77,233,194,45,91,71,253,62,223,60,254,77,233,217, 201,147,180,167,250,222,208,89,47,111,78,191,85,67,109,119, 159,56,47,173,63,165,253,3,0,2,0,29,108,194,235,175, 167,133,217,158,117,60,46,127,241,165,252,181,159,78,153,156, 238,203,58,201,21,115,102,183,204,223,217,53,56,152,22,111, 222,82,151,247,90,186,105,115,250,234,41,39,149,178,61,7, 198,142,85,31,180,17,99,0,104,170,55,247,237,76,255,253, 167,79,167,187,127,184,58,253,250,154,31,167,158,125,251,11, 255,155,206,124,245,181,116,204,192,64,93,222,171,119,83,22, 36,6,7,75,217,158,215,60,243,92,75,180,167,250,64,0, 104,121,101,62,255,53,109,223,190,116,217,83,79,167,175,60, 242,111,233,156,236,48,111,145,150,108,170,95,59,188,105,207, 158,244,214,215,118,148,174,253,163,61,255,203,11,47,86,213, 158,237,84,127,45,245,189,145,190,190,62,223,127,8,0,148, 215,220,61,3,233,243,107,158,76,215,174,123,38,63,20,223, 108,221,217,97,223,11,95,217,90,215,247,92,186,233,21,237, 89,80,123,170,15,4,128,182,96,46,236,255,240,193,23,95, 78,255,109,221,250,166,127,238,185,217,222,92,236,221,213,211, 69,217,120,130,49,71,209,57,116,114,251,31,77,123,182,115, 253,245,88,95,167,76,153,226,251,15,1,0,194,251,127,246, 114,126,158,181,153,150,52,96,111,125,122,22,40,206,45,248, 180,70,89,219,83,125,32,0,208,166,226,60,235,123,179,75, 242,154,97,226,254,253,233,157,117,190,198,124,200,210,151,157, 223,108,118,123,170,15,4,0,218,220,213,207,110,72,19,246, 55,126,180,245,5,217,185,255,137,217,24,128,70,120,103,54, 167,64,51,106,208,158,234,3,1,160,13,25,5,123,104,199, 12,236,77,191,154,237,89,53,218,146,6,14,214,235,201,130, 197,5,111,112,116,161,44,237,127,184,246,236,148,250,107,93, 95,93,5,224,251,79,0,128,67,248,207,207,191,152,166,238, 221,219,176,247,159,158,125,105,55,250,60,125,76,10,68,115, 218,83,125,80,61,51,1,22,185,231,208,70,115,97,255,195, 113,199,166,175,157,116,194,65,175,79,206,38,70,153,155,93, 251,126,108,54,103,123,252,60,46,251,249,174,58,28,90,143, 61,232,243,182,110,79,15,28,59,167,33,245,92,244,202,150, 84,237,188,110,15,206,57,38,45,217,124,244,237,245,142,109, 175,230,157,194,142,113,227,90,174,253,91,161,61,27,89,127, 59,172,175,174,2,112,47,0,1,128,182,176,163,187,251,144, 243,162,111,203,94,122,97,82,207,136,215,102,100,179,234,253, 250,134,141,249,40,233,241,163,184,86,250,23,183,53,46,0, 84,123,248,127,75,118,211,152,255,117,226,241,85,5,128,238, 172,246,139,179,75,2,255,33,155,74,86,123,54,182,61,203, 86,31,212,131,83,0,212,221,246,236,139,247,111,23,158,146, 174,58,239,237,233,133,236,230,42,181,138,27,193,52,98,90, 221,184,195,220,209,206,214,55,100,213,204,25,105,125,54,47, 252,43,85,222,28,102,73,7,76,10,212,234,237,169,62,16, 0,104,49,91,38,76,72,95,56,125,97,170,245,224,234,140, 189,251,210,169,217,141,89,234,109,113,182,23,223,85,229,239, 252,112,214,204,252,231,15,102,207,172,234,247,206,200,130,70, 4,14,237,217,184,246,84,31,8,0,109,167,12,231,191,158, 156,54,53,253,159,19,142,175,125,111,125,79,253,59,207,106, 247,202,227,2,175,213,51,167,231,255,253,253,42,3,64,215, 191,7,142,78,105,255,122,182,103,43,214,223,204,245,213,85, 0,206,255,11,0,116,188,59,179,193,88,181,30,24,141,209, 250,245,116,114,182,135,182,160,202,189,180,184,63,252,206,238, 159,15,151,121,116,198,244,212,63,166,186,205,102,73,135,221, 27,160,149,218,83,125,32,0,180,165,178,204,133,189,59,187, 143,250,166,9,227,107,250,221,233,117,158,167,127,113,13,157, 241,240,195,254,123,179,206,63,198,3,84,35,2,199,201,135, 8,29,237,218,254,245,106,207,86,173,191,89,235,171,171,0, 220,11,64,0,160,20,54,84,140,188,46,100,143,42,27,160, 181,120,115,13,1,96,214,200,195,254,223,59,102,102,213,239, 209,105,71,1,90,162,61,213,7,2,0,173,111,99,79,109, 95,168,3,99,235,183,138,190,101,71,95,126,221,119,85,127, 247,196,137,7,93,54,22,3,2,171,157,248,53,63,242,208, 65,35,196,91,161,61,213,7,2,0,109,96,66,141,19,173, 76,218,87,191,57,214,151,140,242,240,255,144,152,216,39,198, 5,84,227,77,123,170,191,244,80,123,170,15,4,128,14,85, 166,81,176,11,250,118,214,244,123,187,198,142,173,207,138,158, 79,202,83,253,242,62,220,168,255,239,205,30,253,105,128,118, 110,255,122,180,103,43,215,223,140,245,213,85,0,174,2,16, 0,232,252,149,44,235,124,79,222,213,95,211,239,246,119,215, 39,0,188,61,155,150,119,230,222,234,6,20,246,101,95,230, 107,14,179,167,255,189,217,179,170,254,27,98,250,225,49,29, 112,26,160,21,218,83,125,32,0,180,181,178,140,130,141,17, 240,181,30,82,221,56,138,153,217,70,236,125,215,176,247,255, 175,179,102,164,215,187,14,61,101,208,75,217,223,181,126,210, 164,170,222,47,38,138,25,126,3,162,118,109,255,122,181,103, 171,214,223,172,245,213,85,0,174,2,16,0,232,104,99,179, 47,210,143,63,245,76,205,191,191,110,242,228,81,255,13,227, 179,123,181,199,13,95,170,245,253,55,216,203,47,227,213,0, 173,208,158,234,3,1,128,54,240,91,207,60,151,126,97,71, 109,231,58,119,101,35,170,95,154,56,97,212,127,195,249,217, 93,218,38,239,175,110,112,86,252,223,15,207,58,242,245,254, 15,213,112,26,224,130,44,136,76,216,191,95,123,170,15,4, 0,58,215,47,191,180,41,253,167,23,95,170,249,247,159,138, 67,164,93,93,163,254,59,106,217,235,94,51,108,246,191,195, 255,125,147,211,230,42,111,14,20,183,141,189,96,203,54,237, 169,62,40,156,219,1,23,168,19,71,193,118,101,3,168,222, 157,237,229,126,104,195,11,105,225,40,111,140,242,224,220,209, 159,35,156,156,205,204,118,222,214,234,59,220,163,154,243,63, 251,178,143,255,239,178,236,54,178,213,5,146,205,105,197,220, 246,184,23,122,35,219,179,21,234,47,114,125,117,21,128,171, 0,4,0,218,186,179,159,149,221,75,125,206,158,159,63,142, 219,189,59,189,47,219,139,58,177,127,247,168,223,123,79,54, 229,238,202,57,179,71,253,62,241,229,94,203,61,222,143,118, 148,255,67,199,204,170,58,0,156,155,93,145,48,117,239,222, 124,62,1,237,169,62,16,0,74,40,70,193,182,75,10,254, 213,23,94,76,23,109,222,114,224,249,184,193,215,211,236,236, 75,180,81,23,61,125,55,235,88,119,117,143,126,245,140,189, 237,106,173,207,102,254,123,233,40,71,115,63,22,167,10,178, 203,5,171,25,99,208,157,117,68,177,44,127,120,214,25,133, 181,127,43,180,103,35,215,255,118,88,95,93,5,112,140,163, 0,2,0,109,177,162,100,157,214,188,221,187,155,242,89,3, 217,161,245,175,101,119,100,27,173,248,194,127,219,246,215,170, 254,189,239,87,49,184,111,127,182,231,247,195,108,176,224,146, 97,157,205,209,88,154,141,75,248,161,246,84,31,20,200,32, 64,90,206,93,217,151,233,139,53,206,197,62,92,204,252,87, 203,10,94,237,44,127,181,76,10,116,70,54,45,240,236,93, 187,180,167,250,64,0,128,16,147,235,252,239,19,142,175,203, 123,213,50,250,127,203,248,113,233,39,83,171,59,52,27,19, 6,237,173,114,244,119,252,223,23,100,135,169,181,167,250,64, 0,40,33,231,191,70,122,105,194,132,116,253,25,139,242,195, 234,163,53,175,191,63,157,94,195,124,238,249,225,255,42,59, 243,56,247,251,111,51,166,85,253,89,191,180,254,185,82,183, 103,187,175,255,163,93,95,93,5,224,251,79,0,128,248,50, 200,174,167,255,195,179,126,33,109,174,211,68,42,139,107,156, 113,239,251,53,220,228,39,212,114,26,96,65,118,217,217,73, 59,119,105,79,245,129,0,80,54,230,194,254,185,181,217,33, 247,223,63,251,173,71,61,242,190,81,1,160,63,219,147,123, 116,198,244,26,131,195,172,84,203,109,126,218,125,106,224,209, 180,103,187,174,255,245,90,95,93,5,224,251,175,104,174,2, 160,48,123,179,14,247,107,243,79,72,247,156,120,252,97,111, 186,83,139,133,217,84,174,243,107,184,182,59,102,233,251,204, 143,214,214,252,185,181,84,176,56,27,168,120,251,41,243,59, 162,61,99,52,252,29,39,157,88,247,246,84,31,8,0,116, 136,216,83,142,61,237,187,207,125,123,250,183,129,61,117,127, 255,197,155,107,223,171,142,73,122,154,233,184,221,123,210,47, 188,186,35,253,120,250,212,182,111,207,229,167,158,156,158,155, 60,169,99,215,215,78,173,15,1,0,26,238,213,108,176,220, 255,123,211,156,244,127,143,59,54,187,109,106,79,58,102,90, 214,233,189,82,223,0,16,179,189,45,222,180,165,173,150,203, 146,205,155,219,50,0,84,182,103,167,175,175,32,0,80,55, 157,62,10,54,238,142,22,55,72,137,203,234,126,148,117,246, 249,229,114,195,70,76,55,162,254,51,95,125,45,205,201,166, 123,109,39,23,103,147,8,45,63,245,148,150,63,172,252,70, 237,217,238,235,127,189,235,123,35,174,2,112,21,128,0,64, 91,216,52,97,124,254,165,88,105,127,214,105,237,236,30,155, 250,198,118,231,63,227,14,122,125,217,227,217,108,58,221,231, 179,199,96,147,59,181,118,28,84,55,99,239,190,244,142,109, 219,179,14,103,166,246,84,31,8,0,101,208,78,115,97,63, 48,119,78,186,173,206,131,213,234,93,127,119,54,136,239,194, 236,230,63,237,40,130,75,51,3,64,35,218,179,149,214,255, 86,168,239,141,184,10,192,189,0,138,230,50,64,58,198,185, 217,94,244,180,236,246,191,237,232,93,89,112,153,80,197,13, 133,0,4,0,24,182,23,221,174,226,18,196,119,110,217,166, 17,1,1,0,170,49,49,219,123,110,247,14,180,19,39,5, 2,4,0,14,161,236,231,191,234,89,255,5,217,33,244,137, 217,94,116,59,251,197,236,20,198,212,189,123,181,127,73,184, 10,64,224,21,0,192,222,115,46,238,97,127,209,230,45,26, 19,16,0,58,93,217,231,194,174,87,253,211,7,246,230,3, 0,59,34,200,108,126,69,251,151,132,171,0,220,11,160,240, 157,14,139,128,118,119,209,43,91,210,216,26,126,47,198,220, 127,248,188,115,210,142,113,245,223,12,98,79,254,15,127,250, 116,213,191,119,102,54,45,240,156,108,122,96,119,153,3,4, 0,120,163,189,230,26,15,255,63,153,77,20,211,168,142,54, 110,15,188,63,61,93,117,48,137,105,104,226,94,6,247,156, 56,79,195,2,13,229,20,0,109,109,110,182,183,252,214,215, 118,212,216,73,55,110,226,157,190,236,168,194,154,233,211,154, 26,104,0,28,1,56,74,203,150,45,27,241,124,104,84,106, 229,185,169,70,190,62,124,54,172,102,124,238,148,29,59,107, 90,86,61,195,110,134,82,175,191,167,242,223,106,121,159,216, 91,174,117,242,214,181,11,79,77,199,100,243,190,55,106,249, 63,62,255,196,244,182,53,63,170,250,239,58,117,231,174,52, 63,123,236,58,105,254,27,126,110,173,237,217,236,245,124,52, 235,127,173,235,235,208,251,21,81,215,209,174,255,181,88,188, 117,91,154,59,118,108,218,189,251,231,183,188,158,56,113,226, 136,127,175,199,235,123,178,233,145,111,57,254,216,150,92,110, 69,47,255,78,210,10,19,95,15,22,249,225,189,189,189,165, 106,240,75,127,246,114,250,253,167,158,169,250,247,238,206,14, 73,183,226,212,170,255,227,145,199,210,130,172,179,172,214,11, 61,19,211,213,191,248,246,134,254,109,111,234,223,157,238,248, 215,71,107,250,221,255,153,45,239,219,143,98,121,119,90,123, 150,169,190,90,107,107,150,75,46,252,165,172,135,232,236,123, 35,172,92,185,178,212,1,192,41,128,2,185,10,96,116,245, 159,156,117,252,181,116,254,161,145,135,255,135,188,148,133,140, 184,201,76,77,123,121,37,184,26,192,85,0,174,2,64,0, 128,154,244,142,226,92,249,247,179,65,122,205,80,235,231,28, 151,141,109,120,75,141,99,27,0,4,0,58,87,54,105,78, 173,215,204,191,150,157,223,252,241,33,110,21,219,152,0,80, 251,145,134,165,155,54,107,103,64,0,128,225,222,178,163,47, 223,75,174,197,15,179,219,238,190,222,164,115,155,107,179,65, 134,219,198,141,171,233,119,99,46,129,49,131,131,26,27,16, 0,58,141,123,1,212,94,255,104,46,149,107,198,249,255,33, 131,89,208,248,65,141,159,55,115,239,190,116,78,135,204,112, 104,253,63,152,123,1,24,141,47,0,64,181,43,109,182,87, 124,113,141,115,230,15,100,29,242,170,89,51,154,250,247,142, 238,52,128,47,73,64,0,232,56,174,2,168,173,254,183,111, 123,53,219,59,174,237,174,121,143,205,152,158,118,143,29,219, 212,58,87,103,159,185,103,76,109,155,218,187,178,187,28,142, 223,191,95,251,119,32,87,1,184,10,64,0,128,42,141,230, 134,57,223,111,226,225,255,33,123,178,192,241,232,140,218,102, 5,236,201,110,113,252,206,45,219,52,58,32,0,80,110,177, 55,28,123,197,237,20,0,126,254,185,181,95,118,104,106,96, 64,0,96,212,106,61,252,189,123,108,107,172,42,243,178,217, 245,38,215,120,72,124,221,228,73,233,149,9,197,220,101,239, 7,217,149,7,181,142,231,127,243,17,6,139,181,123,123,118, 250,250,122,36,49,221,110,203,46,247,49,186,134,50,48,21, 112,201,166,2,6,224,231,76,5,12,0,8,0,52,143,171, 0,212,175,126,245,171,31,1,0,0,16,0,0,0,1,0, 0,16,0,58,131,123,1,168,95,253,234,87,63,2,0,0, 32,0,148,129,81,192,234,87,191,250,213,143,0,0,0,8, 0,0,128,0,0,0,8,0,157,193,40,96,245,171,95,253, 234,71,0,0,0,4,128,50,48,10,88,253,234,87,191,250, 17,0,0,0,1,0,0,16,0,0,0,1,160,51,24,5, 172,126,245,171,95,253,8,0,0,64,211,116,181,192,223,48, 168,25,0,192,17,0,0,64,0,0,0,4,0,0,64,0, 0,0,4,0,0,64,0,0,0,4,0,0,64,0,0,0, 1,0,0,16,0,0,0,1,0,0,16,0,0,0,1,0, 0,16,0,0,0,1,0,0,16,0,0,0,1,0,0,16, 0,0,0,1,0,0,16,0,0,0,1,0,0,16,0,0, 0,1,0,0,16,0,0,0,1,0,0,4,0,0,64,0, 0,0,4,0,0,64,0,0,0,4,0,0,64,0,0,0, 90,94,183,69,64,201,117,89,4,20,104,208,34,192,17,0, 0,64,0,0,0,4,0,0,64,0,0,0,4,0,0,64, 0,0,0,4,0,0,64,0,0,0,4,0,0,16,0,0, 0,1,0,0,16,0,0,0,1,0,0,16,0,0,0,1, 0,0,16,0,0,0,1,0,0,16,0,0,0,1,0,0, 16,0,0,0,1,0,0,16,0,0,0,1,0,0,16,0, 0,0,1,0,0,16,0,0,64,0,0,0,4,0,0,64, 0,0,0,4,0,0,64,0,0,0,218,200,255,7,248,149, 225,60,216,132,110,116,0,0,0,0,73,69,78,68,174,66, 96,130, }; /* style.css */ static const char * const style_css = "/* Base styles */\n" "@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Source+Code+Pro&display=swap');\n" "\n" "body {\n" " background: white;\n" " color: black;\n" " font-family: 'Open Sans', sans-serif;\n" " font-size: 16px;\n" " margin: 0;\n" "}\n" "code, kbd, pre, tt, input[type=email], input[type=number], input[type=password], input[type=tel], input[type=text], textarea {\n" " font-family: 'Source Code Pro', monospace;\n" "}\n" "pre {\n" " white-space: pre-wrap;\n" "}\n" "\n" "/* Header */\n" ".header {\n" " background: black;\n" " color: white;\n" " width: 100%;\n" "}\n" ".header2 {\n" " background: #333;\n" " color: white;\n" " width: 100%;\n" "}\n" "\n" "/* Navigation */\n" "div.nav {\n" " color: #ccc;\n" " vertical-align: middle;\n" "}\n" ".header div.nav {\n" " font-size: 24px;\n" " line-height: 40px;\n" "}\n" ".header2 div.nav {\n" " font-size: 20px;\n" " line-height: 35px;\n" "}\n" ".header a.btn, .header a.btn:visited, .header2 a.btn, .header2 a.btn:visited {\n" " color: #ccc;\n" " text-decoration: none;\n" " white-space: nowrap;\n" "}\n" ".header a.btn:hover, .header2 a.btn:hover {\n" " color: #eee;\n" "}\n" ".header a.btn:active, .header2 a.btn:active {\n" " color: #fff;\n" "}\n" ".header span.active, .header2 span.active {\n" " color: #fff;\n" " white-space: nowrap;\n" "}\n" ".header a.btn, .header span.active, .header span.spacer {\n" " padding: 0 30px 0 0;\n" "}\n" ".header2 a.btn, .header2 span.active {\n" " padding: 0 20px 0 0;\n" "}\n" "div.nav img {\n" " height: 24px;\n" " margin-right: 10px;\n" " vertical-align: middle;\n" "}\n" "span.spacer {\n" " color: #ccc;\n" "}\n" "span.spacer:after {\n" " content: \"⋮\";\n" "}\n" "\n" "/* Interior Content */\n" ".content {\n" " margin: 20px 0 44px;\n" "}\n" "\n" "form {\n" " display: inline-block;\n" "}\n" "\n" "div.btn {\n" " display: inline-block;\n" " line-height: 32px;\n" "}\n" ".content a.btn, .content a.btn:visited, button, input[type=submit], select {\n" " border: none;\n" " border-radius: 5px;\n" " cursor: pointer;\n" " font-family: inherit;\n" " font-size: 14px;\n" " font-weight: normal;\n" " padding: 4px 8px;\n" " text-decoration: none;\n" " white-space: nowrap;\n" " -moz-appearance: none;\n" " -webkit-appearance: none;\n" "}\n" ".content a.btn, .content a.btn:visited, button, input[type=submit] {\n" " background: #333;\n" " color: #ccc;\n" "}\n" ".content a.btn:hover, button:hover, input[type=submit]:hover {\n" " background: #333;\n" " color: #eee;\n" "}\n" ".content a.btn:active, button:active, input[type=submit]:active {\n" " background: #444;\n" " color: #fff;\n" "}\n" "input[type=email], input[type=password], input[type=tel], input[type=text] {\n" " padding: 4px 8px;\n" "}\n" "input[type=number] {\n" " appearance: textfield;\n" " padding: 4px 0 4px 8px;\n" "}\n" "input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button {\n" " -webkit-appearance: none;\n" " margin: 0;\n" "}\n" "input[type=email]:disabled, input[type=number]:disabled, input[type=password]:disabled, input[type=tel]:disabled, input[type=text]:disabled {\n" " border: none;\n" " color: black;\n" " font-size: 16px;\n" " padding: 0;\n" "}\n" "select {\n" " background: #ccc url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23000000' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n" " color: black;\n" " padding: 4px 32px 4px 8px;\n" "}\n" "select:hover {\n" " background: #ddd url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23000000' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n" "}\n" "textarea {\n" " width: 100%;\n" "}\n" "label.image input[type=radio] {\n" " position: absolute;\n" " opacity: 0;\n" " width: 0;\n" " height: 0;\n" "}\n" "label.image input[type=radio] + img {\n" " border-radius: 5px;\n" " cursor: pointer;\n" " padding: 2px;\n" "}\n" "label.image input[type=radio]:checked + img {\n" " background: rgba(127,127,127,.5);\n" "}\n" "\n" "div.switch {\n" " display: inline-flex;\n" "}\n" "div.switch input {\n" " border: 0;\n" " clip: rect(0,0,0,0);\n" " height: 1px;\n" " overflow: hidden;\n" " position: absolute !important;\n" " width: 1px;\n" "}\n" "div.switch label {\n" " background-color: #ddd;\n" " border: 1px solid rgba(0,0,0,0.2);\n" " color: black;\n" " font-family: monospace;\n" " font-size: 11px;\n" " line-height: 1;\n" " margin-right: -1px;\n" " padding: 6px 8px;\n" " text-align: center;\n" " transition: all 0.2s ease-in-out;\n" "}\n" "div.switch label:first-of-type {\n" " border-radius: 5px 0 0 5px;\n" "}\n" "div.switch label:last-of-type {\n" " border-radius: 0 5px 5px 0;\n" "}\n" "div.switch input:checked + label {\n" " background-color: #333;\n" " color: #ddd;\n" "}\n" "\n" "label.switch {\n" " position: relative;\n" " display: inline-block;\n" " width: 30px;\n" " height: 17px;\n" " margin-bottom: 5px;\n" " margin-left: 2px;\n" " vertical-align: middle;\n" "}\n" "label.switch input {\n" " opacity: 0;\n" " width: 0;\n" " height: 0;\n" "}\n" "\n" "img.password-show, img.password-hide {\n" " cursor: pointer;\n" " margin-left: -25px;\n" " padding-bottom: 5px;\n" " vertical-align: bottom;\n" "}\n" "img.password-hide {\n" " content: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZXllLXNsYXNoIiB2aWV3Qm94PSIwIDAgMTYgMTYiPg0KICA8cGF0aCBkPSJNMTMuMzU5IDExLjIzOEMxNS4wNiA5LjcyIDE2IDggMTYgOHMtMy01LjUtOC01LjVhNy4wMjggNy4wMjggMCAwIDAtMi43OS41ODhsLjc3Ljc3MUE1Ljk0NCA1Ljk0NCAwIDAgMSA4IDMuNWMyLjEyIDAgMy44NzkgMS4xNjggNS4xNjggMi40NTdBMTMuMTM0IDEzLjEzNCAwIDAgMSAxNC44MjggOGMtLjA1OC4wODctLjEyMi4xODMtLjE5NS4yODgtLjMzNS40OC0uODMgMS4xMi0xLjQ2NSAxLjc1NS0uMTY1LjE2NS0uMzM3LjMyOC0uNTE3LjQ4NmwuNzA4LjcwOXoiLz4NCiAgPHBhdGggZD0iTTExLjI5NyA5LjE3NmEzLjUgMy41IDAgMCAwLTQuNDc0LTQuNDc0bC44MjMuODIzYTIuNSAyLjUgMCAwIDEgMi44MjkgMi44MjlsLjgyMi44MjJ6bS0yLjk0MyAxLjI5OS44MjIuODIyYTMuNSAzLjUgMCAwIDEtNC40NzQtNC40NzRsLjgyMy44MjNhMi41IDIuNSAwIDAgMCAyLjgyOSAyLjgyOXoiLz4NCiAgPHBhdGggZD0iTTMuMzUgNS40N2MtLjE4LjE2LS4zNTMuMzIyLS41MTguNDg3QTEzLjEzNCAxMy4xMzQgMCAwIDAgMS4xNzIgOGwuMTk1LjI4OGMuMzM1LjQ4LjgzIDEuMTIgMS40NjUgMS43NTVDNC4xMjEgMTEuMzMyIDUuODgxIDEyLjUgOCAxMi41Yy43MTYgMCAxLjM5LS4xMzMgMi4wMi0uMzZsLjc3Ljc3MkE3LjAyOSA3LjAyOSAwIDAgMSA4IDEzLjVDMyAxMy41IDAgOCAwIDhzLjkzOS0xLjcyMSAyLjY0MS0zLjIzOGwuNzA4LjcwOXptMTAuMjk2IDguODg0LTEyLTEyIC43MDgtLjcwOCAxMiAxMi0uNzA4LjcwOHoiLz4NCjwvc3ZnPg==);\n" "}\n" "img.password-show {\n" " content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZXllIiB2aWV3Qm94PSIwIDAgMTYgMTYiPg0KICA8cGF0aCBkPSJNMTYgOHMtMy01LjUtOC01LjVTMCA4IDAgOHMzIDUuNSA4IDUuNVMxNiA4IDE2IDh6TTEuMTczIDhhMTMuMTMzIDEzLjEzMyAwIDAgMSAxLjY2LTIuMDQzQzQuMTIgNC42NjggNS44OCAzLjUgOCAzLjVjMi4xMiAwIDMuODc5IDEuMTY4IDUuMTY4IDIuNDU3QTEzLjEzMyAxMy4xMzMgMCAwIDEgMTQuODI4IDhjLS4wNTguMDg3LS4xMjIuMTgzLS4xOTUuMjg4LS4zMzUuNDgtLjgzIDEuMTItMS40NjUgMS43NTVDMTEuODc5IDExLjMzMiAxMC4xMTkgMTIuNSA4IDEyLjVjLTIuMTIgMC0zLjg3OS0xLjE2OC01LjE2OC0yLjQ1N0ExMy4xMzQgMTMuMTM0IDAgMCAxIDEuMTcyIDh6Ii8+DQogIDxwYXRoIGQ9Ik04IDUuNWEyLjUgMi41IDAgMSAwIDAgNSAyLjUgMi41IDAgMCAwIDAtNXpNNC41IDhhMy41IDMuNSAwIDEgMSA3IDAgMy41IDMuNSAwIDAgMS03IDB6Ii8+DQo8L3N2Zz4=);\n" "}\n" "\n" "div.pager {\n" " padding: 10px 0;\n" " text-align: center;\n" "}\n" "\n" "div.log {\n" " background: #333;\n" " border: solid thin rgba(127,127,127,.5);\n" " color: #ccc;\n" " height: 30em;\n" " margin-top: 20px;\n" " overflow: scroll;\n" " width: 100%;\n" "}\n" "\n" "div.log pre {\n" " padding: 10px;\n" "}\n" "\n" "/* Footer */\n" ".footer {\n" " background: rgba(224,224,224,.9);\n" " bottom: 0;\n" " color: #777;\n" " font-size: 12px;\n" " height: 24px;\n" " left: 0;\n" " position: fixed;\n" " right: 0;\n" " width: 100%;\n" "}\n" ".footer a {\n" " color: #c66;\n" "}\n" "\n" "/* Grid System - Rows and Columns */\n" ".row {\n" " position: relative;\n" " width: 100%;\n" "}\n" ".row::after {\n" " clear: both;\n" " content: \"\";\n" " display: table;\n" " width: 0;\n" "}\n" ".row [class^=\"col-\"] {\n" " float: left;\n" " margin: 20px 0 0 2%;\n" " min-height: 1px;\n" " padding: 5px 0;\n" "}\n" ".row:first-child [class^=\"col-\"] {\n" " margin: 0 0 0 2%;\n" "}\n" "h1:first-child, h2:first-child, h3:first-child, .row p:first-child {\n" " margin-top: 0;\n" "}\n" ".row p:last-child, .rounded p:last-child {\n" " margin-bottom: 0;\n" "}\n" ".col-1 {\n" " width: 6.1666%;\n" "}\n" ".col-2 {\n" " width: 14.3333%;\n" "}\n" ".col-3 {\n" " width: 22.5%;\n" "}\n" ".col-4 {\n" " width: 30.6666%;\n" "}\n" ".col-5 {\n" " width: 38.8333%;\n" "}\n" ".col-6 {\n" " width: 47%;\n" "}\n" ".col-7 {\n" " width: 55.1666%;\n" "}\n" ".col-8 {\n" " width: 63.3333%;\n" "}\n" ".col-9 {\n" " width: 71.5%;\n" "}\n" ".col-10 {\n" " width: 79.6666%;\n" "}\n" ".col-11 {\n" " width: 87.8333%;\n" "}\n" ".col-12 {\n" " width: 96%;\n" "}\n" "\n" "/* Inline Styles */\n" "span.badge {\n" " background: #c00;\n" " border-radius: 8px;\n" " color: #fff;\n" " font-size: 14px;\n" " font-weight: bold;\n" " padding: 1px 6px;\n" "}\n" "\n" "span.bar {\n" " box-shadow: 1px 1px 2px rgba(51,51,51,0.25);\n" " font-size: 20px;\n" " line-height: 20px;\n" "}\n" "\n" "img.idle, img.processing, img.stopped {\n" " border-radius: 10px;\n" " float: left;\n" " height: 64px;\n" " margin-right: 10px;\n" " padding: 5px;\n" " width: 64px;\n" "}\n" "\n" "img.idle {\n" " background-color: rgba(0,192,0,0.5);\n" "}\n" "\n" "img.processing {\n" " background-color: rgba(224,224,0,0.5);\n" "}\n" "\n" "img.stopped {\n" " background-color: rgba(192,0,0,0.5);\n" "}\n" "\n" ".shaded {\n" " background-color: rgba(127,127,127,.25);\n" "}\n" "\n" "h1.title {\n" " border-bottom: solid 2px black;\n" " clear: both;\n" "}\n" "\n" "h2.title {\n" " border-bottom: solid 1px #555;\n" " clear: both;\n" " color: #555;\n" "}\n" "\n" ".title a:link, .title a:visited {\n" " color: inherit;\n" " text-decoration: none;\n" "}\n" "\n" ".title a.btn, .title a.btn:visited {\n" " color: #ccc;\n" " vertical-align: 25%;\n" "}\n" "\n" ".title a.btn:hover, .title a.btn:active {\n" " color: #fff;\n" "}\n" "\n" "/* Animations */\n" ".banner {\n" " animation: banner 3s 1s 1 forwards;\n" " background: rgba(160,160,224,0.5);\n" " border-radius: 5px;\n" " margin: 10px 0;\n" " padding: 10px;\n" "}\n" "\n" "@keyframes banner {\n" " 0% { background: rgba(160,160,224,0.5); }\n" " 100% { background: rgba(160,160,160,0.5); }\n" "}\n" "\n" ".spinner > div {\n" " width: 18px;\n" " height: 18px;\n" "\n" " border-radius: 100%;\n" " display: inline-block;\n" " animation: spinner 1.4s infinite ease-in-out both;\n" "}\n" "\n" ".spinner .bounce1 {\n" " animation-delay: -0.32s;\n" "}\n" "\n" ".spinner .bounce2 {\n" " animation-delay: -0.16s;\n" "}\n" "\n" "@keyframes spinner {\n" " 0%, 80%, 100% {\n" " transform: scale(0);\n" " background: rgba(160,160,160,0.5);\n" " } 40% {\n" " transform: scale(1.0);\n" " background: rgba(160,160,224,0.5);\n" " }\n" "}\n" "\n" "/* Form Tables */\n" "table.form {\n" " border-collapse: collapse;\n" " margin-top: 10px;\n" " min-width: 50%;\n" "}\n" "table.form td, table.form th {\n" " line-height: 30px;\n" " padding: 5px 2px;\n" " vertical-align: top;\n" "}\n" "table.form th {\n" " text-align: right;\n" "}\n" "\n" "iframe#map {\n" " width: 300px;\n" " height: 200px;\n" "}\n" "\n" "/* List Tables */\n" "table.list {\n" " border-bottom: solid thin black;\n" " border-collapse: collapse;\n" " clear: both;\n" " width: 100%;\n" "}\n" "table.list tr:nth-child(even) {\n" " background: #fcfcfc;\n" "}\n" "table.list tr:nth-child(odd) {\n" " background: #f0f0f0;\n" "}\n" "table.list th {\n" " background: white;\n" " border-bottom: solid thin black;\n" " text-align: left;\n" " vertical-align: bottom;\n" "}\n" "table.list td {\n" " margin: 0;\n" " padding: 5px;\n" " vertical-align: top;\n" "}\n" "\n" "/* Meter Tables for Supply Levels */\n" "table.meter {\n" " border-collapse: collapse;\n" " margin-top: 10px;\n" " min-width: 50%;\n" " max-width: 600px;\n" "}\n" "table.meter thead td {\n" " border-bottom: 1px solid black;\n" " border-left: 1px solid black;\n" " border-right: 1px solid black;\n" " height: 4px;\n" " line-height: 4px;\n" " padding: 0;\n" " width: 20%;\n" "}\n" "table.meter tfoot td {\n" " border-left: 1px solid black;\n" " border-right: 1px solid black;\n" " border-top: 1px solid black;\n" " height: 4px;\n" " line-height: 4px;\n" " padding: 0;\n" " width: 20%;\n" "}\n" "table.meter td {\n" " padding: 5px 0;\n" "}\n" "table.meter th {\n" " border-right: 1px solid black;\n" " padding: 5px;\n" " text-align: right;\n" "}\n" "\n" "/* Small Device Overrides */\n" "@media only screen and (min-device-width: 320px) and (max-device-width: 480px), only screen and (min-device-width: 320px) and (max-device-width: 568px) {\n" " .content {\n" " margin: 20px 0 20px;\n" " }\n" " .footer {\n" " height: auto;\n" " position: relative;\n" " }\n" " .row [class^=\"col-\"] {\n" " width: 96%;\n" " }\n" " iframe#map {\n" " width: 200px;\n" " height: 200px;\n" " }\n" "}\n" "\n" "/* Dark Mode Overrides */\n" "@media (prefers-color-scheme: dark) {\n" " body {\n" " background: black;\n" " color: #ccc;\n" " }\n" " span.bar {\n" " box-shadow: 1px 1px 5px rgba(255,255,255,0.5);\n" " }\n" "\n" " h1.title {\n" " border-bottom: solid 2px #ccc;\n" " }\n" " h2.title {\n" " border-bottom: solid 1px #999;\n" " color: #999;\n" " }\n" "\n" " input[type=email], input[type=text], input[type=password], input[type=number] {\n" " background: #333;\n" " color: #ccc;\n" " }\n" " select {\n" " background: #333 url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23CCCCCC' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n" " color: #ccc;\n" " padding: 4px 32px 4px 8px;\n" " }\n" " select:hover {\n" " background: #444 url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23DDDDDD' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n" " }\n" "\n" " div.switch label {\n" " background-color: #333;\n" " border: 1px solid rgba(191,191,191,0.2);\n" " color: #ccc;\n" " }\n" " div.switch input:checked + label {\n" " background-color: #ddd;\n" " color: #333;\n" " }\n" "\n" " table.list {\n" " border-bottom: solid thin #ccc;\n" " }\n" " table.list tr:nth-child(even) {\n" " background: #222;\n" " color: #ccc;\n" " }\n" " table.list tr:nth-child(odd) {\n" " background: #333;\n" " }\n" " table.list th {\n" " background: black;\n" " border-bottom: solid thin #ccc;\n" " }\n" " table.meter thead td {\n" " border-bottom: 1px solid #ccc;\n" " border-left: 1px solid #ccc;\n" " border-right: 1px solid #ccc;\n" " }\n" " table.meter tfoot td {\n" " border-left: 1px solid #ccc;\n" " border-right: 1px solid #ccc;\n" " border-top: 1px solid #ccc;\n" " }\n" " table.meter th {\n" " border-right: 1px solid #ccc;\n" " }\n" "}\n" ; pappl-1.4.9/pappl/resource.c000066400000000000000000000347241476704353100157740ustar00rootroot00000000000000// // System resource implementation for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" #include // // Local functions... // static void add_resource(pappl_system_t *system, _pappl_resource_t *r); static int compare_resources(_pappl_resource_t *a, _pappl_resource_t *b); static _pappl_resource_t *copy_resource(_pappl_resource_t *r); static void free_resource(_pappl_resource_t *r); // // 'papplSystemAddResourceCallback()' - Add a dynamic resource that uses a // callback function. // // This function adds a dynamic resource at the specified path. When a client // GET or POST request is received at the specified path, the "cb" function // will be called with the client pointer and "data" pointer to respond to it. // // Resource callbacks are most often used to implement custom web pages. // // > Note: Any custom web page that is added prior to calling the // > @link papplSystemRun@ function will replace the corresponding standard web // > page at the same path. // void papplSystemAddResourceCallback( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *format, // I - MIME media type for content such as "text/html" pappl_resource_cb_t cb, // I - Callback function void *data) // I - Callback data { _pappl_resource_t r; // New resource if (!system || !path || path[0] != '/' || !format || !cb) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)format; r.cb = cb; r.cbdata = data; add_resource(system, &r); } // // 'papplSystemAddResourceData()' - Add a static data resource. // // This function adds a static resource at the specified path. The provided // data is not copied to the resource and must remain stable for as long as the // resource is added to the system. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddResourceData( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *format, // I - MIME media type such as "image/png" const void *data, // I - Resource data size_t datalen) // I - Size of resource data { _pappl_resource_t r; // New resource if (!system || !path || path[0] != '/' || !format || !data || datalen == 0) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)format; r.last_modified = time(NULL); r.data = data; r.length = datalen; add_resource(system, &r); } // // 'papplSystemAddResourceDirectory()' - Add external files in a directory as // resources. // // This function adds static resources from the specified directory under the // specified path. The directory is scanned and only those files present at the // time of the call are available, and those files must remain stable for as // long as the resources are added to the system.. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddResourceDirectory( pappl_system_t *system, // I - System object const char *basepath, // I - Base resource path const char *directory) // I - Directory containing resource files { cups_dir_t *dir; // Directory pointer cups_dentry_t *dent; // Current directory entry char filename[1024], // External filename path[1024], // Resource path *ext; // Extension on filename const char *format; // MIME media type _pappl_resource_t r; // New resource if (!system || !basepath || !directory) return; // Read all files in the directory... if ((dir = cupsDirOpen(directory)) == NULL) return; while ((dent = cupsDirRead(dir)) != NULL) { // Skip dot files, directories, and files without an extension... if (dent->filename[0] == '.' || !S_ISREG(dent->fileinfo.st_mode) || (ext = strrchr(dent->filename, '.')) == NULL) continue; // See if this is an extension we recognize... if (!strcmp(ext, ".css")) format = "text/css"; else if (!strcmp(ext, ".html")) format = "text/html"; else if (!strcmp(ext, ".icc")) format = "application/vnd.iccprofile"; else if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg")) format = "image/jpeg"; else if (!strcmp(ext, ".pdf")) format = "application/pdf"; else if (!strcmp(ext, ".png")) format = "image/png"; else if (!strcmp(ext, ".strings")) format = "text/strings"; else if (!strcmp(ext, ".txt")) format = "text/plain"; else continue; // Add the file... snprintf(filename, sizeof(filename), "%s/%s", directory, dent->filename); snprintf(path, sizeof(path), "%s/%s", basepath, dent->filename); memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)format; r.filename = (char *)filename; r.last_modified = dent->fileinfo.st_mtime; r.length = (size_t)dent->fileinfo.st_size; add_resource(system, &r); } cupsDirClose(dir); } // // 'papplSystemAddResourceFile()' - Add an external file as a resource. // // This function adds a static resource at the specified path. The provided // file is not copied to the resource and must remain stable for as long as the // resource is added to the system. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddResourceFile( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *format, // I - MIME media type such as "image/png" const char *filename) // I - Filename { _pappl_resource_t r; // New resource struct stat fileinfo; // File information if (!system || !path || path[0] != '/' || !format || !filename || stat(filename, &fileinfo)) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)format; r.filename = (char *)filename; r.last_modified = fileinfo.st_mtime; r.length = (size_t)fileinfo.st_size; add_resource(system, &r); } // // 'papplSystemAddResourceString()' - Add a static data resource as a C string. // // This function adds a static resource at the specified path. The provided // data is not copied to the resource and must remain stable for as long as the // resource is added to the system. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddResourceString( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *format, // I - MIME media type such as "image/png" const char *data) // I - Resource data { _pappl_resource_t r; // New resource if (!system || !path || path[0] != '/' || !format || !data) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)format; r.last_modified = time(NULL); r.data = data; r.length = strlen(data); add_resource(system, &r); } // // 'papplSystemAddStringsData()' - Add a static localization file resource. // // This function adds a static localization resource at the specified path. // Localization files use the NeXTStep strings ("text/strings") format defined // in PWG Candidate Standard 5100.13-2013. The provided data is not copied to // the resource and must remain stable for as long as the resource is added to // the system. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddStringsData( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *language, // I - ISO language tag such as "en-US", "fr-CA", etc. const char *data) // I - Nul-terminated string containing strings file data { _pappl_resource_t r; // New resource if (!system || !path || path[0] != '/' || !language || !data || !*data) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)"text/strings"; r.language = (char *)language; r.last_modified = time(NULL); r.data = data; r.length = strlen(data); add_resource(system, &r); // Load the localization... _papplLocCreate(system, _papplSystemFindResourceForPath(system, path)); } // // 'papplSystemAddStringsFile()' - Add an external localization file resource. // // This function adds a static localization resource at the specified path. // Localization files use the NeXTStep strings ("text/strings") format defined // in PWG Candidate Standard 5100.13-2013. The provided file is not copied to // the resource and must remain stable for as long as the resource is added to // the system. // // > Note: Any resource that is added prior to calling the @link papplSystemRun@ // > function will replace the corresponding standard resource at the same path. // void papplSystemAddStringsFile( pappl_system_t *system, // I - System object const char *path, // I - Resource path const char *language, // I - ISO language tag such as "en-US", "fr-CA", etc. const char *filename) // I - Filename { _pappl_resource_t r; // New resource struct stat fileinfo; // File information if (!system || !path || path[0] != '/' || !language || !filename || stat(filename, &fileinfo)) return; memset(&r, 0, sizeof(r)); r.path = (char *)path; r.format = (char *)"text/strings"; r.filename = (char *)filename; r.language = (char *)language; r.last_modified = fileinfo.st_mtime; r.length = (size_t)fileinfo.st_size; add_resource(system, &r); // Load the localization... _papplLocCreate(system, _papplSystemFindResourceForPath(system, path)); } // // '_papplSystemFindResourceForLanguage()' - Find a resource for a language. // _pappl_resource_t * // O - Resource object _papplSystemFindResourceForLanguage( pappl_system_t *system, // I - System object const char *language) // I - Language { _pappl_resource_t *r; // Resource if (!system || !system->resources || !language) return (NULL); _papplRWLockRead(system); for (r = (_pappl_resource_t *)cupsArrayGetFirst(system->resources); r; r = (_pappl_resource_t *)cupsArrayGetNext(system->resources)) { if (r->format && !strcmp(r->format, "text/strings") && r->language && !strcmp(r->language, language)) break; } _papplRWUnlock(system); return (r); } // // '_papplSystemFindResourceForPath()' - Find a resource at a path. // _pappl_resource_t * // O - Resource object _papplSystemFindResourceForPath( pappl_system_t *system, // I - System object const char *path) // I - Resource path { _pappl_resource_t key, // Search key *match; // Matching resource, if any char altpath[1024]; // Alternate path if (!system || !system->resources || !path) return (NULL); key.path = (char *)path; _papplRWLockRead(system); if ((match = (_pappl_resource_t *)cupsArrayFind(system->resources, &key)) == NULL) { snprintf(altpath, sizeof(altpath), "%s/", path); key.path = altpath; match = (_pappl_resource_t *)cupsArrayFind(system->resources, &key); } _papplRWUnlock(system); return (match); } // // 'papplSystemRemoveResource()' - Remove a resource at the specified path. // // This function removes a resource at the specified path. // void papplSystemRemoveResource( pappl_system_t *system, // I - System object const char *path) // I - Resource path { _pappl_resource_t key, // Search key *match; // Matching resource, if any if (!system || !system->resources || !path) return; key.path = (char *)path; _papplRWLockWrite(system); if ((match = (_pappl_resource_t *)cupsArrayFind(system->resources, &key)) != NULL) { papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Removing resource for '%s'.", path); cupsArrayRemove(system->resources, match); } _papplRWUnlock(system); } // // 'add_resource()' - Add a resource object to a system object. // static void add_resource(pappl_system_t *system, // I - System object _pappl_resource_t *r) // I - Resource { _papplRWLockWrite(system); if (!cupsArrayFind(system->resources, r)) { if (!system->resources) system->resources = cupsArrayNew((cups_array_cb_t)compare_resources, NULL, NULL, 0, (cups_acopy_cb_t)copy_resource, (cups_afree_cb_t)free_resource); cupsArrayAdd(system->resources, r); } _papplRWUnlock(system); } // // 'compare_resources()' - Compare the path of two resources. // static int // O - Result of comparison compare_resources(_pappl_resource_t *a, // I - First resource _pappl_resource_t *b) // I - Second resource { return (strcmp(a->path, b->path)); } // // 'copy_resource()' - Make a copy of some resource data. // static _pappl_resource_t * // O - New resource copy_resource(_pappl_resource_t *r) // I - Resource to copy { _pappl_resource_t *newr; // New resource if ((newr = (_pappl_resource_t *)calloc(1, sizeof(_pappl_resource_t))) != NULL) { newr->path = strdup(r->path); newr->format = strdup(r->format); newr->last_modified = r->last_modified; newr->data = r->data; newr->length = r->length; newr->cb = r->cb; newr->cbdata = r->cbdata; if (r->filename) newr->filename = strdup(r->filename); if (r->language) newr->language = strdup(r->language); if (!newr->path || !newr->format || (r->filename && !newr->filename) || (r->language && !newr->language)) { free_resource(newr); return (NULL); } } return (newr); } // // 'free_resource()' - Free the memory used for a resource. // static void free_resource(_pappl_resource_t *r) // I - Resource { free(r->path); free(r->format); free(r->filename); free(r->language); free(r); } pappl-1.4.9/pappl/snmp-private.h000066400000000000000000000077641476704353100166030ustar00rootroot00000000000000// // Private SNMP definitions for the Printer Application Framework. // // Copyright © 2020-2022 by Michael R Sweet // Copyright © 2007-2014 by Apple Inc. // Copyright © 2006-2007 by Easy Software Products, all rights reserved. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_SNMP_PRIVATE_H_ # define _PAPPL_SNMP_PRIVATE_H_ # include "base-private.h" // // Constants... // #define _PAPPL_SNMP_COMMUNITY "public"// SNMP default community name #define _PAPPL_SNMP_PORT 161 // SNMP well-known port #define _PAPPL_SNMP_MAX_COMMUNITY 512 // Maximum size of community name #define _PAPPL_SNMP_MAX_OID 128 // Maximum number of OID numbers #define _PAPPL_SNMP_MAX_PACKET 1472 // Maximum size of SNMP packet #define _PAPPL_SNMP_MAX_STRING 1024 // Maximum size of string #define _PAPPL_SNMP_VERSION_1 0 // SNMPv1 // // Types... // enum _pappl_asn1_e // ASN1 request/object types { _PAPPL_ASN1_END_OF_CONTENTS = 0x00, // End-of-contents _PAPPL_ASN1_BOOLEAN = 0x01, // BOOLEAN _PAPPL_ASN1_INTEGER = 0x02, // INTEGER or ENUMERATION _PAPPL_ASN1_BIT_STRING = 0x03, // BIT STRING _PAPPL_ASN1_OCTET_STRING = 0x04, // OCTET STRING _PAPPL_ASN1_NULL_VALUE = 0x05, // NULL VALUE _PAPPL_ASN1_OID = 0x06, // OBJECT IDENTIFIER _PAPPL_ASN1_SEQUENCE = 0x30, // SEQUENCE _PAPPL_ASN1_HEX_STRING = 0x40, // Binary string aka Hex-STRING _PAPPL_ASN1_COUNTER = 0x41, // 32-bit unsigned aka Counter32 _PAPPL_ASN1_GAUGE = 0x42, // 32-bit unsigned aka Gauge32 _PAPPL_ASN1_TIMETICKS = 0x43, // 32-bit unsigned aka Timeticks32 _PAPPL_ASN1_GET_REQUEST = 0xa0, // GetRequest-PDU _PAPPL_ASN1_GET_NEXT_REQUEST = 0xa1, // GetNextRequest-PDU _PAPPL_ASN1_GET_RESPONSE = 0xa2 // GetResponse-PDU }; typedef enum _pappl_asn1_e _pappl_asn1_t;// ASN1 request/object types typedef struct _pappl_snmp_string_s // String value { unsigned char bytes[_PAPPL_SNMP_MAX_STRING]; // Bytes in string unsigned num_bytes; // Number of bytes } _pappl_snmp_string_t; union _pappl_snmp_value_u // Object value { int boolean; // Boolean value int integer; // Integer value int counter; // Counter value unsigned gauge; // Gauge value unsigned timeticks; // Timeticks value int oid[_PAPPL_SNMP_MAX_OID]; // OID value _pappl_snmp_string_t string; // String value }; typedef struct _pappl_snmp_s // SNMP data packet { const char *error; // Encode/decode error http_addr_t address; // Source address int version; // Version number char community[_PAPPL_SNMP_MAX_COMMUNITY]; // Community name _pappl_asn1_t request_type; // Request type unsigned request_id; // request-id value int error_status; // error-status value int error_index; // error-index value int object_name[_PAPPL_SNMP_MAX_OID]; // object-name value _pappl_asn1_t object_type; // object-value type union _pappl_snmp_value_u object_value; // object-value value } _pappl_snmp_t; typedef void (*_pappl_snmp_cb_t)(_pappl_snmp_t *packet, void *data); // SNMP callback // // Prototypes... // extern void _papplSNMPClose(int fd) _PAPPL_PRIVATE; extern int *_papplSNMPCopyOID(int *dst, const int *src, int dstsize) _PAPPL_PRIVATE; extern int _papplSNMPIsOID(_pappl_snmp_t *packet, const int *oid) _PAPPL_PRIVATE; extern int _papplSNMPIsOIDPrefixed(_pappl_snmp_t *packet, const int *prefix) _PAPPL_PRIVATE; extern char *_papplSNMPOIDToString(const int *src, char *dst, size_t dstsize) _PAPPL_PRIVATE; extern int _papplSNMPOpen(int family) _PAPPL_PRIVATE; extern _pappl_snmp_t *_papplSNMPRead(int fd, _pappl_snmp_t *packet, double timeout) _PAPPL_PRIVATE; extern int _papplSNMPWalk(int fd, http_addr_t *address, int version, const char *community, const int *prefix, double timeout, _pappl_snmp_cb_t cb, void *data) _PAPPL_PRIVATE; extern int _papplSNMPWrite(int fd, http_addr_t *address, int version, const char *community, _pappl_asn1_t request_type, const unsigned request_id, const int *oid) _PAPPL_PRIVATE; #endif // !_PAPPL_SNMP_PRIVATE_H_ pappl-1.4.9/pappl/snmp.c000066400000000000000000000720071476704353100151160ustar00rootroot00000000000000// // SNMP functions for the Printer Application Framework. // // Copyright © 2020-2022 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // Copyright © 2006-2007 by Easy Software Products, all rights reserved. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers. // #include "snmp-private.h" // // Macros... // #define _(x) x #define snmp_set_error(p,m) p->error = m // // Local functions... // static int asn1_decode_snmp(unsigned char *buffer, size_t len, _pappl_snmp_t *packet); static int asn1_encode_snmp(unsigned char *buffer, size_t len, _pappl_snmp_t *packet); static int asn1_get_integer(unsigned char **buffer, unsigned char *bufend, unsigned length); static int asn1_get_oid(unsigned char **buffer, unsigned char *bufend, unsigned length, int *oid, int oidsize); static int asn1_get_packed(unsigned char **buffer, unsigned char *bufend); static char *asn1_get_string(unsigned char **buffer, unsigned char *bufend, unsigned length, char *string, size_t strsize); static unsigned asn1_get_length(unsigned char **buffer, unsigned char *bufend); static int asn1_get_type(unsigned char **buffer, unsigned char *bufend); static void asn1_set_integer(unsigned char **buffer, int integer); static void asn1_set_length(unsigned char **buffer, unsigned length); static void asn1_set_oid(unsigned char **buffer, const int *oid); static void asn1_set_packed(unsigned char **buffer, int integer); static unsigned asn1_size_integer(int integer); static unsigned asn1_size_length(unsigned length); static unsigned asn1_size_oid(const int *oid); static unsigned asn1_size_packed(int integer); // // '_papplSNMPClose()' - Close a SNMP socket. // void _papplSNMPClose(int fd) // I - SNMP socket file descriptor { httpAddrClose(NULL, fd); } // // '_papplSNMPCopyOID()' - Copy an OID. // // The array pointed to by "src" is terminated by the value -1. // int * // O - New OID _papplSNMPCopyOID(int *dst, // I - Destination OID const int *src, // I - Source OID int dstsize) // I - Number of integers in dst { int i; // Looping var for (i = 0, dstsize --; i < dstsize && src[i] >= 0; i ++) dst[i] = src[i]; dst[i] = -1; return (dst); } // // '_papplSNMPIsOID()' - Test whether a SNMP response contains the specified OID. // // The array pointed to by "oid" is terminated by the value -1. // int // O - 1 if equal, 0 if not equal _papplSNMPIsOID(_pappl_snmp_t *packet, // I - Response packet const int *oid) // I - OID { int i; // Looping var // Range check input... if (!packet || !oid) return (0); // Compare OIDs... for (i = 0; i < _PAPPL_SNMP_MAX_OID && oid[i] >= 0 && packet->object_name[i] >= 0; i ++) { if (oid[i] != packet->object_name[i]) return (0); } return (i < _PAPPL_SNMP_MAX_OID && oid[i] == packet->object_name[i]); } // // '_papplSNMPIsOIDPrefixed()' - Test whether a SNMP response uses the specified // OID prefix. // // The array pointed to by "prefix" is terminated by the value -1. // int // O - 1 if prefixed, 0 if not prefixed _papplSNMPIsOIDPrefixed( _pappl_snmp_t *packet, // I - Response packet const int *prefix) // I - OID prefix { int i; // Looping var // Range check input... if (!packet || !prefix) return (0); // Compare OIDs... for (i = 0; i < _PAPPL_SNMP_MAX_OID && prefix[i] >= 0 && packet->object_name[i] >= 0; i ++) { if (prefix[i] != packet->object_name[i]) return (0); } return (i < _PAPPL_SNMP_MAX_OID); } // // '_papplSNMPOIDToString()' - Convert an OID to a string. // char * // O - New string or @code NULL@ on error _papplSNMPOIDToString(const int *src, // I - OID char *dst, // I - String buffer size_t dstsize) // I - Size of string buffer { char *dstptr, // Pointer into string buffer *dstend; // End of string buffer // Range check input... if (!src || !dst || dstsize < 4) return (NULL); // Loop through the OID array and build a string... for (dstptr = dst, dstend = dstptr + dstsize - 1; *src >= 0 && dstptr < dstend; src ++, dstptr += strlen(dstptr)) snprintf(dstptr, (size_t)(dstend - dstptr + 1), ".%d", *src); if (*src >= 0) return (NULL); else return (dst); } // // '_papplSNMPOpen()' - Open a SNMP socket. // int // O - SNMP socket file descriptor _papplSNMPOpen(int family) // I - Address family - @code AF_INET@ or @code AF_INET6@ { int fd; // SNMP socket file descriptor int val; // Socket option value // Create the SNMP socket... if ((fd = (int)socket(family, SOCK_DGRAM, 0)) < 0) return (-1); // Set the "broadcast" flag... val = 1; if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char *)&val, sizeof(val))) { close(fd); return (-1); } return (fd); } // // '_papplSNMPRead()' - Read and parse a SNMP response. // // If "timeout" is negative, @code _papplSNMPRead@ will wait for a response // indefinitely. // _pappl_snmp_t * // O - SNMP packet or @code NULL@ if none _papplSNMPRead(int fd, // I - SNMP socket file descriptor _pappl_snmp_t *packet, // I - SNMP packet buffer double timeout) // I - Timeout in seconds { unsigned char buffer[_PAPPL_SNMP_MAX_PACKET]; // Data packet ssize_t bytes; // Number of bytes received socklen_t addrlen; // Source address length http_addr_t address; // Source address // Range check input... if (fd < 0 || !packet) return (NULL); // Optionally wait for a response... if (timeout >= 0.0) { int ready; // Data ready on socket? struct pollfd pfd; // Polled file descriptor pfd.fd = fd; pfd.events = POLLIN; while ((ready = poll(&pfd, 1, (int)(timeout * 1000.0))) < 0 && (errno == EINTR || errno == EAGAIN)) ; // Wait for poll to complete... // If we don't have any data ready, return right away... if (ready <= 0) return (NULL); } // Read the response data... addrlen = sizeof(address); if ((bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (void *)&address, &addrlen)) < 0) return (NULL); // Look for the response status code in the SNMP message header... asn1_decode_snmp(buffer, (size_t)bytes, packet); memcpy(&(packet->address), &address, sizeof(packet->address)); // Return decoded data packet... return (packet); } // // '_papplSNMPWalk()' - Enumerate a group of OIDs. // // This function queries all of the OIDs with the specified OID prefix, // calling the "cb" function for every response that is received. // // The array pointed to by "prefix" is terminated by the value -1. // // If "timeout" is negative, @code _papplSNMPWalk@ will wait for a response // indefinitely. // int // O - Number of OIDs found or -1 on error _papplSNMPWalk( int fd, // I - SNMP socket http_addr_t *address, // I - Address to query int version, // I - SNMP version const char *community, // I - Community name const int *prefix, // I - OID prefix double timeout, // I - Timeout for each response in seconds _pappl_snmp_cb_t cb, // I - Function to call for each response void *data) // I - User data pointer that is passed to the callback function { int count = 0; // Number of OIDs found unsigned request_id = 0; // Current request ID _pappl_snmp_t packet; // Current response packet int lastoid[_PAPPL_SNMP_MAX_OID]; // Last OID we got #ifdef DEBUG char temp[1024]; // OID returned #endif // DEBUG // Range check input... _PAPPL_DEBUG("_papplSNMPWalk(fd=%d, address=%p, version=%d, community=\"%s\", prefix=%s, timeout=%g, cb=%p, data=%p)\n", fd, address, version, community ? community : "(null)", _papplSNMPOIDToString(prefix, temp, sizeof(temp)), timeout, cb, data); if (fd < 0 || !address || version != _PAPPL_SNMP_VERSION_1 || !community || !prefix || !cb) return (-1); // Copy the OID prefix and then loop until we have no more OIDs... _papplSNMPCopyOID(packet.object_name, prefix, _PAPPL_SNMP_MAX_OID); lastoid[0] = -1; for (;;) { request_id ++; if (!_papplSNMPWrite(fd, address, version, community, _PAPPL_ASN1_GET_NEXT_REQUEST, request_id, packet.object_name)) { _PAPPL_DEBUG("_papplSNMPWalk: Unable to send Get-Next-Request.\n"); return (-1); } if (!_papplSNMPRead(fd, &packet, timeout)) { _PAPPL_DEBUG("_papplSNMPWalk: Unable to read response.\n"); return (-1); } _PAPPL_DEBUG("_papplSNMPWalk: OID %s.\n", _papplSNMPOIDToString(packet.object_name, temp, sizeof(temp))); if (!_papplSNMPIsOIDPrefixed(&packet, prefix) || _papplSNMPIsOID(&packet, lastoid)) { _PAPPL_DEBUG("_papplSNMPWalk: Different prefix or same OID as last, returning %d.\n", count); return (count); } if (packet.error || packet.error_status) { _PAPPL_DEBUG("_papplSNMPWalk: error=\"%s\", error_status=%d, returning %d.\n", packet.error, packet.error_status, count > 0 ? count : -1); return (count > 0 ? count : -1); } _papplSNMPCopyOID(lastoid, packet.object_name, _PAPPL_SNMP_MAX_OID); count ++; (*cb)(&packet, data); } } // // '_papplSNMPWrite()' - Send an SNMP query packet. // // The array pointed to by "oid" is terminated by the value -1. // int // O - 1 on success, 0 on error _papplSNMPWrite( int fd, // I - SNMP socket http_addr_t *address, // I - Address to send to int version, // I - SNMP version const char *community, // I - Community name _pappl_asn1_t request_type, // I - Request type const unsigned request_id, // I - Request ID const int *oid) // I - OID { int i; // Looping var _pappl_snmp_t packet; // SNMP message packet unsigned char buffer[_PAPPL_SNMP_MAX_PACKET]; // SNMP message buffer ssize_t bytes; // Size of message http_addr_t temp; // Copy of address // Range check input... if (fd < 0 || !address || version != _PAPPL_SNMP_VERSION_1 || !community || (request_type != _PAPPL_ASN1_GET_REQUEST && request_type != _PAPPL_ASN1_GET_NEXT_REQUEST) || request_id < 1 || !oid) return (0); // Create the SNMP message... memset(&packet, 0, sizeof(packet)); packet.version = version; packet.request_type = request_type; packet.request_id = request_id; packet.object_type = _PAPPL_ASN1_NULL_VALUE; papplCopyString(packet.community, community, sizeof(packet.community)); for (i = 0; i < (_PAPPL_SNMP_MAX_OID - 1) && oid[i] >= 0; i ++) packet.object_name[i] = oid[i]; packet.object_name[i] = -1; if (oid[i] >= 0) { errno = E2BIG; return (0); } bytes = asn1_encode_snmp(buffer, sizeof(buffer), &packet); if (bytes < 0) { errno = E2BIG; return (0); } // Send the message... temp = *address; temp.ipv4.sin_port = htons(_PAPPL_SNMP_PORT); #if _WIN32 return (sendto(fd, buffer, (int)bytes, 0, (void *)&temp, (socklen_t)httpAddrGetLength(&temp)) == bytes); #else return (sendto(fd, buffer, (size_t)bytes, 0, (void *)&temp, (socklen_t)httpAddrGetLength(&temp)) == bytes); #endif // _WIN32 } // // 'asn1_decode_snmp()' - Decode a SNMP packet. // static int // O - 0 on success, -1 on error asn1_decode_snmp( unsigned char *buffer, // I - Buffer size_t len, // I - Size of buffer _pappl_snmp_t *packet) // I - SNMP packet { unsigned char *bufptr, // Pointer into the data *bufend; // End of data unsigned length; // Length of value // Initialize the decoding... memset(packet, 0, sizeof(_pappl_snmp_t)); packet->object_name[0] = -1; bufptr = buffer; bufend = buffer + len; if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_SEQUENCE) { snmp_set_error(packet, _("Packet does not start with SEQUENCE")); } else if (asn1_get_length(&bufptr, bufend) == 0) { snmp_set_error(packet, _("SEQUENCE uses indefinite length")); } else if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_INTEGER) { snmp_set_error(packet, _("No version number")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("Version uses indefinite length")); } else if ((packet->version = asn1_get_integer(&bufptr, bufend, length)) != _PAPPL_SNMP_VERSION_1) { snmp_set_error(packet, _("Bad SNMP version number")); } else if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_OCTET_STRING) { snmp_set_error(packet, _("No community name")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("Community name uses indefinite length")); } else { asn1_get_string(&bufptr, bufend, length, packet->community, sizeof(packet->community)); if ((packet->request_type = (_pappl_asn1_t)asn1_get_type(&bufptr, bufend)) != _PAPPL_ASN1_GET_RESPONSE) { snmp_set_error(packet, _("Packet does not contain a Get-Response-PDU")); } else if (asn1_get_length(&bufptr, bufend) == 0) { snmp_set_error(packet, _("Get-Response-PDU uses indefinite length")); } else if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_INTEGER) { snmp_set_error(packet, _("No request-id")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("request-id uses indefinite length")); } else { packet->request_id = (unsigned)asn1_get_integer(&bufptr, bufend, length); if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_INTEGER) { snmp_set_error(packet, _("No error-status")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("error-status uses indefinite length")); } else { packet->error_status = asn1_get_integer(&bufptr, bufend, length); if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_INTEGER) { snmp_set_error(packet, _("No error-index")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("error-index uses indefinite length")); } else { packet->error_index = asn1_get_integer(&bufptr, bufend, length); if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_SEQUENCE) { snmp_set_error(packet, _("No variable-bindings SEQUENCE")); } else if (asn1_get_length(&bufptr, bufend) == 0) { snmp_set_error(packet, _("variable-bindings uses indefinite length")); } else if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_SEQUENCE) { snmp_set_error(packet, _("No VarBind SEQUENCE")); } else if (asn1_get_length(&bufptr, bufend) == 0) { snmp_set_error(packet, _("VarBind uses indefinite length")); } else if (asn1_get_type(&bufptr, bufend) != _PAPPL_ASN1_OID) { snmp_set_error(packet, _("No name OID")); } else if ((length = asn1_get_length(&bufptr, bufend)) == 0) { snmp_set_error(packet, _("Name OID uses indefinite length")); } else { asn1_get_oid(&bufptr, bufend, length, packet->object_name, _PAPPL_SNMP_MAX_OID); packet->object_type = (_pappl_asn1_t)asn1_get_type(&bufptr, bufend); if ((length = asn1_get_length(&bufptr, bufend)) == 0 && packet->object_type != _PAPPL_ASN1_NULL_VALUE && packet->object_type != _PAPPL_ASN1_OCTET_STRING) { snmp_set_error(packet, _("Value uses indefinite length")); } else { switch (packet->object_type) { case _PAPPL_ASN1_BOOLEAN : packet->object_value.boolean = asn1_get_integer(&bufptr, bufend, length); break; case _PAPPL_ASN1_INTEGER : packet->object_value.integer = asn1_get_integer(&bufptr, bufend, length); break; case _PAPPL_ASN1_NULL_VALUE : break; case _PAPPL_ASN1_OCTET_STRING : case _PAPPL_ASN1_BIT_STRING : case _PAPPL_ASN1_HEX_STRING : packet->object_value.string.num_bytes = length; asn1_get_string(&bufptr, bufend, length, (char *)packet->object_value.string.bytes, sizeof(packet->object_value.string.bytes)); break; case _PAPPL_ASN1_OID : asn1_get_oid(&bufptr, bufend, length, packet->object_value.oid, _PAPPL_SNMP_MAX_OID); break; case _PAPPL_ASN1_COUNTER : packet->object_value.counter = asn1_get_integer(&bufptr, bufend, length); break; case _PAPPL_ASN1_GAUGE : packet->object_value.gauge = (unsigned)asn1_get_integer(&bufptr, bufend, length); break; case _PAPPL_ASN1_TIMETICKS : packet->object_value.timeticks = (unsigned)asn1_get_integer(&bufptr, bufend, length); break; default : snmp_set_error(packet, _("Unsupported value type")); break; } } } } } } } return (packet->error ? -1 : 0); } // // 'asn1_encode_snmp()' - Encode a SNMP packet. // static int // O - Length on success, -1 on error asn1_encode_snmp( unsigned char *buffer, // I - Buffer size_t bufsize, // I - Size of buffer _pappl_snmp_t *packet) // I - SNMP packet { unsigned char *bufptr; // Pointer into buffer unsigned total, // Total length msglen, // Length of entire message commlen, // Length of community string reqlen, // Length of request listlen, // Length of variable list varlen, // Length of variable namelen, // Length of object name OID valuelen; // Length of object value // Get the lengths of the community string, OID, and message... namelen = asn1_size_oid(packet->object_name); switch (packet->object_type) { case _PAPPL_ASN1_NULL_VALUE : valuelen = 0; break; case _PAPPL_ASN1_BOOLEAN : valuelen = asn1_size_integer(packet->object_value.boolean); break; case _PAPPL_ASN1_INTEGER : valuelen = asn1_size_integer(packet->object_value.integer); break; case _PAPPL_ASN1_OCTET_STRING : valuelen = packet->object_value.string.num_bytes; break; case _PAPPL_ASN1_OID : valuelen = asn1_size_oid(packet->object_value.oid); break; default : packet->error = "Unknown object type"; return (-1); } varlen = 1 + asn1_size_length(namelen) + namelen + 1 + asn1_size_length(valuelen) + valuelen; listlen = 1 + asn1_size_length(varlen) + varlen; reqlen = 2 + asn1_size_integer((int)packet->request_id) + 2 + asn1_size_integer(packet->error_status) + 2 + asn1_size_integer(packet->error_index) + 1 + asn1_size_length(listlen) + listlen; commlen = (unsigned)strlen(packet->community); msglen = 2 + asn1_size_integer(packet->version) + 1 + asn1_size_length(commlen) + commlen + 1 + asn1_size_length(reqlen) + reqlen; total = 1 + asn1_size_length(msglen) + msglen; if (total > bufsize) { packet->error = "Message too large for buffer"; return (-1); } // Then format the message... bufptr = buffer; *bufptr++ = _PAPPL_ASN1_SEQUENCE; // SNMPv1 message header asn1_set_length(&bufptr, msglen); asn1_set_integer(&bufptr, packet->version); // version *bufptr++ = _PAPPL_ASN1_OCTET_STRING; // community asn1_set_length(&bufptr, commlen); memcpy(bufptr, packet->community, commlen); bufptr += commlen; *bufptr++ = (unsigned char)packet->request_type; // Get-Request-PDU/Get-Next-Request-PDU asn1_set_length(&bufptr, reqlen); asn1_set_integer(&bufptr, (int)packet->request_id); asn1_set_integer(&bufptr, packet->error_status); asn1_set_integer(&bufptr, packet->error_index); *bufptr++ = _PAPPL_ASN1_SEQUENCE; // variable-bindings asn1_set_length(&bufptr, listlen); *bufptr++ = _PAPPL_ASN1_SEQUENCE; // variable asn1_set_length(&bufptr, varlen); asn1_set_oid(&bufptr, packet->object_name); // ObjectName switch (packet->object_type) { case _PAPPL_ASN1_NULL_VALUE : *bufptr++ = _PAPPL_ASN1_NULL_VALUE; // ObjectValue *bufptr++ = 0; // Length break; case _PAPPL_ASN1_BOOLEAN : asn1_set_integer(&bufptr, packet->object_value.boolean); break; case _PAPPL_ASN1_INTEGER : asn1_set_integer(&bufptr, packet->object_value.integer); break; case _PAPPL_ASN1_OCTET_STRING : *bufptr++ = _PAPPL_ASN1_OCTET_STRING; asn1_set_length(&bufptr, valuelen); memcpy(bufptr, packet->object_value.string.bytes, valuelen); bufptr += valuelen; break; case _PAPPL_ASN1_OID : asn1_set_oid(&bufptr, packet->object_value.oid); break; default : break; } return ((int)(bufptr - buffer)); } // // 'asn1_get_integer()' - Get an integer value. // static int // O - Integer value asn1_get_integer( unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend, // I - End of buffer unsigned length) // I - Length of value { int value; // Integer value if (*buffer >= bufend) return (0); if (length > sizeof(int)) { if (length > (unsigned)(bufend - *buffer)) *buffer = bufend; else (*buffer) += length; return (0); } for (value = (**buffer & 0x80) ? ~0 : 0; length > 0 && *buffer < bufend; length --, (*buffer) ++) value = ((value & 0xffffff) << 8) | **buffer; return (value); } // // 'asn1_get_length()' - Get a value length. // static unsigned // O - Length asn1_get_length(unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend) // I - End of buffer { unsigned length; // Length if (*buffer >= bufend) return (0); length = **buffer; (*buffer) ++; if (length & 128) { int count; // Number of bytes for length if ((count = length & 127) > sizeof(unsigned)) { if (count > (bufend - *buffer)) *buffer = bufend; else (*buffer) += count; return (0); } for (length = 0; count > 0 && *buffer < bufend; count --, (*buffer) ++) length = (length << 8) | **buffer; } return (length); } // // 'asn1_get_oid()' - Get an OID value. // static int // O - Number of OIDs asn1_get_oid( unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend, // I - End of buffer unsigned length, // I - Length of value int *oid, // I - OID buffer int oidsize) // I - Size of OID buffer { unsigned char *valend; // End of value int *oidptr, // Current OID *oidend; // End of OID buffer int number; // OID number if (*buffer >= bufend) { return (0); } else if (length > (unsigned)(bufend - *buffer)) { *buffer = bufend; return (0); } valend = *buffer + length; oidptr = oid; oidend = oid + oidsize - 1; if (valend > bufend) valend = bufend; number = asn1_get_packed(buffer, valend); if (number < 80) { *oidptr++ = number / 40; number = number % 40; *oidptr++ = number; } else { *oidptr++ = 2; number -= 80; *oidptr++ = number; } while (*buffer < valend) { number = asn1_get_packed(buffer, valend); if (oidptr < oidend) *oidptr++ = number; } *oidptr = -1; return ((int)(oidptr - oid)); } // // 'asn1_get_packed()' - Get a packed integer value. // static int // O - Value asn1_get_packed( unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend) // I - End of buffer { int value; // Value if (*buffer >= bufend) return (0); value = 0; while (*buffer < bufend && (**buffer & 128)) { value = (value << 7) | (**buffer & 127); (*buffer) ++; } if (*buffer < bufend) { value = (value << 7) | **buffer; (*buffer) ++; } return (value); } // // 'asn1_get_string()' - Get a string value. // static char * // O - String asn1_get_string( unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend, // I - End of buffer unsigned length, // I - Value length char *string, // I - String buffer size_t strsize) // I - String buffer size { if (*buffer >= bufend) return (NULL); if (length > (unsigned)(bufend - *buffer)) length = (unsigned)(bufend - *buffer); if (length < strsize) { // String is smaller than the buffer... if (length > 0) memcpy(string, *buffer, length); string[length] = '\0'; } else { // String is larger than the buffer... memcpy(string, *buffer, strsize - 1); string[strsize - 1] = '\0'; } if (length > 0) (*buffer) += length; return (string); } // // 'asn1_get_type()' - Get a value type. // static int // O - Type asn1_get_type(unsigned char **buffer, // IO - Pointer in buffer unsigned char *bufend) // I - End of buffer { int type; // Type if (*buffer >= bufend) return (0); type = **buffer; (*buffer) ++; if ((type & 31) == 31) type = asn1_get_packed(buffer, bufend); return (type); } // // 'asn1_set_integer()' - Set an integer value. // static void asn1_set_integer(unsigned char **buffer,// IO - Pointer in buffer int integer) // I - Integer value { **buffer = _PAPPL_ASN1_INTEGER; (*buffer) ++; if (integer > 0x7fffff || integer < -0x800000) { **buffer = 4; (*buffer) ++; **buffer = (unsigned char)(integer >> 24); (*buffer) ++; **buffer = (unsigned char)(integer >> 16); (*buffer) ++; **buffer = (unsigned char)(integer >> 8); (*buffer) ++; **buffer = (unsigned char)integer; (*buffer) ++; } else if (integer > 0x7fff || integer < -0x8000) { **buffer = 3; (*buffer) ++; **buffer = (unsigned char)(integer >> 16); (*buffer) ++; **buffer = (unsigned char)(integer >> 8); (*buffer) ++; **buffer = (unsigned char)integer; (*buffer) ++; } else if (integer > 0x7f || integer < -0x80) { **buffer = 2; (*buffer) ++; **buffer = (unsigned char)(integer >> 8); (*buffer) ++; **buffer = (unsigned char)integer; (*buffer) ++; } else { **buffer = 1; (*buffer) ++; **buffer = (unsigned char)integer; (*buffer) ++; } } // // 'asn1_set_length()' - Set a value length. // static void asn1_set_length(unsigned char **buffer, // IO - Pointer in buffer unsigned length) // I - Length value { if (length > 255) { **buffer = 0x82; // 2-byte length (*buffer) ++; **buffer = (unsigned char)(length >> 8); (*buffer) ++; **buffer = (unsigned char)length; (*buffer) ++; } else if (length > 127) { **buffer = 0x81; // 1-byte length (*buffer) ++; **buffer = (unsigned char)length; (*buffer) ++; } else { **buffer = (unsigned char)length; // Length (*buffer) ++; } } // // 'asn1_set_oid()' - Set an OID value. // static void asn1_set_oid(unsigned char **buffer, // IO - Pointer in buffer const int *oid) // I - OID value { **buffer = _PAPPL_ASN1_OID; (*buffer) ++; asn1_set_length(buffer, asn1_size_oid(oid)); if (oid[1] < 0) { asn1_set_packed(buffer, oid[0] * 40); return; } asn1_set_packed(buffer, oid[0] * 40 + oid[1]); for (oid += 2; *oid >= 0; oid ++) asn1_set_packed(buffer, *oid); } // // 'asn1_set_packed()' - Set a packed integer value. // static void asn1_set_packed(unsigned char **buffer, // IO - Pointer in buffer int integer) // I - Integer value { if (integer > 0xfffffff) { **buffer = ((integer >> 28) & 0x7f) | 0x80; (*buffer) ++; } if (integer > 0x1fffff) { **buffer = ((integer >> 21) & 0x7f) | 0x80; (*buffer) ++; } if (integer > 0x3fff) { **buffer = ((integer >> 14) & 0x7f) | 0x80; (*buffer) ++; } if (integer > 0x7f) { **buffer = ((integer >> 7) & 0x7f) | 0x80; (*buffer) ++; } **buffer = integer & 0x7f; (*buffer) ++; } // // 'asn1_size_integer()' - Figure out the number of bytes needed for an // integer value. // static unsigned // O - Size in bytes asn1_size_integer(int integer) // I - Integer value { if (integer > 0x7fffff || integer < -0x800000) return (4); else if (integer > 0x7fff || integer < -0x8000) return (3); else if (integer > 0x7f || integer < -0x80) return (2); else return (1); } // // 'asn1_size_length()' - Figure out the number of bytes needed for a // length value. // static unsigned // O - Size in bytes asn1_size_length(unsigned length) // I - Length value { if (length > 0xff) return (3); else if (length > 0x7f) return (2); else return (1); } // // 'asn1_size_oid()' - Figure out the number of bytes needed for an // OID value. // static unsigned // O - Size in bytes asn1_size_oid(const int *oid) // I - OID value { unsigned length; // Length of value if (oid[1] < 0) return (asn1_size_packed(oid[0] * 40)); for (length = asn1_size_packed(oid[0] * 40 + oid[1]), oid += 2; *oid >= 0; oid ++) length += asn1_size_packed(*oid); return (length); } // // 'asn1_size_packed()' - Figure out the number of bytes needed for a // packed integer value. // static unsigned // O - Size in bytes asn1_size_packed(int integer) // I - Integer value { if (integer > 0xfffffff) return (5); else if (integer > 0x1fffff) return (4); else if (integer > 0x3fff) return (3); else if (integer > 0x7f) return (2); else return (1); } pappl-1.4.9/pappl/strings/000077500000000000000000000000001476704353100154605ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/de.strings000066400000000000000000001401371476704353100174710ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Alle Jobs abbrechen (cancel)."; " -c COPIES" = " -c KOPIEN"; " -d PRINTER Specify printer." = " -d PRINTER Drucker angeben."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Druckjob ID angeben (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Geben Sie den Treiber an (Hinzufügen/Ändern)."; " -n COPIES Specify number of copies (submit)." = " -n COPIES Geben Sie die Anzahl der Exemplare an."; " -o %s=%s (default)" = " -o %s=%s (Standard)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=WERT Option angeben (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 bis 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 bis 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE"; " -o printer-location='LOCATION'" = " -o printer-location='ORT'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organizationn='ORGANISATION'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='Abteilung'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Spezifizieren Sie ipp: oder ipps: Drucker/Server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Schnittstelle / Socket angeben: oder USB: Gerät (add/modify)."; " add PRINTER Add a printer." = " add PRINTER Einen Drucker hinzufügen."; " autoadd Automatically add supported printers." = " autoadd Unterstützte Drucker automatisch hinzufügen."; " cancel Cancel one or more jobs." = " cancel Stornierung einer oder mehrerer Druckaufträge."; " default Set the default printer." = " default Setzen Sie den Standarddrucker."; " delete Delete a printer." = " delete Löschen eines Druckers."; " devices List devices." = " devices Geräte auflisten."; " drivers List drivers." = " drivers Treiber auflisten."; " jobs List jobs." = " jobs Aufträge auflisten."; " modify Modify a printer." = " modify Drucker ändern."; " options List printer options." = " options Liste der Druckeroptionen."; " pause Pause printing for a printer." = " pause Druck pausieren."; " printers List printers." = " printers Drucker auflisten."; " resume Resume printing for a printer." = " resume Druck fortsetzen."; " server Run a server." = " server Server ausführen."; " shutdown Shutdown a running server." = " shutdown Abschalten eines laufenden Servers."; " status Show server/printer/job status." = " status Server/Drucker/Auftragsstatus anzeigen."; " submit Submit a file for printing." = " submit Senden Sie eine Datei zum Drucken."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d zoll/s"; "%d job" = "%d Job"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%d dpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g \""; /* size (type+borderless) */ "%s (%s%s)" = "%s ( %s %s )"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) aus %s"; /* Source/Tray Media */ "%s Media" = "%s Medien"; "%s: Bad 'server-port' value." = "%s: Unpassender Server-Port."; "%s: Bad job ID." = "%s: Unpassende Job-ID."; "%s: Bad printer URI '%s'." = "%s: Unpassender Drucker URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Kann nicht mehr als einen Unterbefehl angeben."; "%s: Empty print file received on the standard input." = "%s: Leere Druckdatei, die auf der Standardeingabe empfangen wurde."; "%s: Failed to create a system." = "%s: Erstellung eines Systems fehlgeschlagen."; "%s: Missing '-d PRINTER'." = "%s: Fehlende Option '-d PRINTER'."; "%s: Missing '-m DRIVER-NAME'." = "%s: Fehlende Option '-m DRIVER-NAME'."; "%s: Missing '-v DEVICE-URI'." = "%s: Fehlende Option '-v DEVICE-URI'."; "%s: Missing copy count after '-n'." = "%s: Fehlende Kopien-Anzahl nach -n."; "%s: Missing device URI after '-v'." = "%s: Fehlender Gerät URI nach -v."; "%s: Missing driver name after '-m'." = "%s: Fehlender Treibername nach -m."; "%s: Missing filename after '--'." = "%s: Fehlender Dateiname nach '--'."; "%s: Missing hostname after '-h'." = "%s: Fehlender Rechnername nach '-h'."; "%s: Missing job ID after '-j'." = "%s: Fehlende Auftrags-ID nach '-j'."; "%s: Missing option(s) after '-o'." = "%s: Fehlende Option(en) nach '-o'."; "%s: Missing printer URI after '-u'." = "%s: Fehlender Drucker URI nach '-u'."; "%s: Missing printer name after '-d'." = "%s: Fehlender Druckername nach '-d'."; "%s: Missing space after '-o'." = "%s: Fehlendes Leerzeichen nach '-o'."; "%s: Missing title after '-t'." = "%s: Fehlender Titel nach '-t'."; "%s: No default printer available." = "%s: Kein Standarddrucker verfügbar."; "%s: No files to print." = "%s: Keine Dateien zum Drucken."; "%s: Server is not running." = "%s: Server läuft nicht."; "%s: Sub-command '%s' does not accept files." = "%s: Unterbefehl '%s' akzeptiert keine Dateien."; "%s: Sub-command 'autoadd' is not supported." = "%s: Unterbefehl 'autoadd' wird nicht unterstützt."; "%s: Too many files." = "%s: Zu viele Dateien."; "%s: Unable to access '%s': %s" = "%s: Zugriff auf '%s': %s nicht möglich"; "%s: Unable to add printer: %s" = "%s: Hinzufügen des Druckers nicht möglich: %s"; "%s: Unable to cancel job: %s" = "%s: Job %s konnte nicht storniert werden"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Drucker konnte nicht verbunden werden: '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Verbindung zu Server nicht möglich: %s"; "%s: Unable to create temporary file: %s" = "%s: Temporäre Datei konnte nicht erstellt werden: %s"; "%s: Unable to delete printer: %s" = "%s: Drucker konnte nicht gelöscht werden: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Information nicht verfügbar '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Drucker-Information nicht verfügbar: %s"; "%s: Unable to get printer options: %s" = "%s: Druckeroptionen konnten nicht abgerufen werden: %s"; "%s: Unable to modify printer: %s" = "%s: Drucker konnte nicht geändert werden: %s"; "%s: Unable to pause printer: %s" = "%s: Drucker konnte nicht pausiert werden: %s"; "%s: Unable to print '%s': %s" = "%s: Konnte nicht gedruckt werden: %s ': %s"; "%s: Unable to resume printer: %s" = "%s: Drucker konnte nicht wieder gestartet werden: %s"; "%s: Unable to set default printer: %s" = "%s: Standard-Drucker konnte nicht festgelegt werden: %s"; "%s: Unable to shutdown server: %s" = "%s: Server konnte nicht heruntergefahren werden: %s"; "%s: Unable to start server: %s" = "%s: Server konnte nicht gestartet werden: %s"; "%s: Unable to write to temporary file: %s" = "%s: Konnte nicht in temporäre Datei schreiben: %s"; "%s: Unknown option '%s'." = "%s: Unbekannte Option '%s'."; "%s: Unknown option '-%c'." = "%s: Unbekannte Option '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Unbekannter Unterbefehl '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Nicht unterstütztes URI-System '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Warnung - Persönliche Benutzerinformationen werden nicht in URIs unterstützt."; ", Borderless" = ", Randlos"; "A printer with that name already exists." = "Ein Drucker mit diesem Namen existiert bereits."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Drucker hinzufügen"; "Admin Group" = "Admin Gruppe"; "Afghanistan" = "Afghanistan"; "Albania" = "Albanien"; "Algeria" = "Algerien"; "American Samoa" = "Amerikanisch-Samoa"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarktis"; "Antigua and Barbuda" = "Antigua und Barbuda"; "Argentina" = "Argentinien"; "Armenia" = "Armenien"; "Aruba" = "Aruba"; "Australia" = "Australien"; "Austria" = "Österreich"; "Auto" = "Auto"; "Auto-Detect Driver" = "Treiber automatisch erkennen"; "Azerbaijan" = "Aserbaidschan"; "Bad administration group." = "Unpassende Verwaltungsgruppe."; "Bad port number." = "Unpassende Port-Nummer."; "Bad print group." = "Unpassende Druckgruppe."; "Bad printer defaults." = "Unpassende Standard-Druckereinstellungen."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrain"; "Bangladesh" = "Bangladesch"; "Barbados" = "Barbados"; "Belarus" = "Weißrussland"; "Belgium" = "Belgien"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivien"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius und Saba"; "Borderless" = "Randlos"; "Bosnia and Herzegovina" = "Bosnien und Herzegowina"; "Botswana" = "Botsuana"; "Bouvet Island" = "Bouvetinsel"; "Brazil" = "Brasilien"; "British Indian Ocean Territory" = "Britisches Territorium im Indischen Ozean"; "Brunei Darussalam" = "Brunei"; "Bulgaria" = "Bulgarien"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cap Verde"; "Cambodia" = "Kambodscha"; "Cameroon" = "Kamerun"; "Canada" = "Kanada"; "Cancel All Jobs" = "Alle Druckaufträge löschen"; "Cancel Job" = "Druckauftrag abbrechen"; "Canceled %s" = "Canceled %s"; "Canceling" = "Abbrechend"; "Cayman Islands" = "Cayman Inseln"; "Central African Republic" = "Zentralafrikanische Republik"; "Certificate created." = "Zertifikat erstellt."; "Certificate installed." = "Zertifikat installiert."; "Certificate request created." = "Zertifikatsanfrage erstellt."; "Chad" = "Tschad"; "Change Access Password" = "Zugangspasswort ändern"; "Change Log Level" = "Log Level ändern"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "WLAN-Netzwerk ändern"; "Changes Saved." = "Änderungen gespeichert."; "Changes saved." = "Änderungen gespeichert."; "Chile" = "Chile"; "China" = "China"; "Christmas Island" = "Weihnachtsinsel"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Kakao (Keeling) Inseln"; "Colombia" = "Kolumbien"; "Comoros" = "Komoren"; "Completed %s" = "Completed %s"; "Configuration" = "Konfiguration"; "Configure Media" = "Medien konfigurieren"; "Confirm Cancel All" = "Abbruch bestätigen: Alle"; "Confirm Delete Printer" = "Löschung des Druckers bestätigen"; "Congo" = "Kongo"; "Congo, Democratic Republic of the" = "Kongo, Demokratische Republik"; "Contact" = "Kontakt"; "Cook Islands" = "Cookinseln"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Signatur-Anfrage für Zertifikat erzeugen"; "Create New Certificate" = "Neues Zertifikat erstellen"; "Create New TLS Certificate" = "Neues TLS-Zertifikat erstellen"; "Create TLS Certificate Request" = "TLS Zertifikat Anfrage erzeugen"; "Croatia" = "Kroatien"; "Cuba" = "Kuba"; "Curaçao" = "Curaçao"; "Current Password" = "Aktuelles Passwort"; "Custom Size" = "Benutzerdefinierte Größe"; "Cyprus" = "Zypern"; "Czechia" = "Tschechien"; "Côte d'Ivoire" = "Côte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SD Service Name"; "Debugging" = "Fehleranalyse"; "Default printer set." = "Standarddruckersatz."; "Delete" = "Löschen"; "Delete Printer" = "Drucker löschen"; "Denmark" = "Dänemark"; "Djibouti" = "Dschibuti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominica"; "Dominican Republic" = "Dominikanische Republik"; "Download Certificate Request File" = "Certificate Request File herunterladen"; "Ecuador" = "Ecuador"; "Egypt" = "Ägypten"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Äquatorialguinea"; "Eritrea" = "Eritrea"; "Errors" = "Fehler"; "Estonia" = "Estland"; "Eswatini" = "Swasiland"; "Ethiopia" = "Äthiopien"; "Falkland Islands (Malvinas)" = "Falklandinseln (Malvinas)"; "Faroe Islands" = "Färöer"; "Fatal Errors/Conditions" = "Gravierende Fehler/Zustände"; "Fiji" = "Fidschi"; "Finland" = "Finnland"; "France" = "Frankreich"; "French Guiana" = "Französisch-Guayana"; "French Polynesia" = "Französisch-Polynesien"; "French Southern Territories" = "Französische südliche Gebiete"; "Gabon" = "Gabun"; "Gambia" = "Gambia"; "Georgia" = "Georgien"; "Germany" = "Deutschland"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Griechenland"; "Greenland" = "Grönland"; "Grenada" = "Grenada"; "Group changes saved." = "Gruppenänderungen gespeichert."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Island und McDonald Inseln"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Heiliger Stuhl"; "Honduras" = "Honduras"; "Hong Kong" = "Hongkong"; "Hostname" = "Rechnername (Hostname)"; "Human-Readable Location" = "Ortsbezeichnung"; "Hungary" = "Ungarn"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Island"; "Identify Printer" = "Drucker identifizieren"; "India" = "Indien"; "Indonesia" = "Indonesien"; "Informational" = "Informativ"; "Install TLS Certificate" = "TLS Zertifikat installieren"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Ungültige Auftragsnummer (Job-ID)."; "Invalid certificate or private key." = "Zertifikat oder privater Schlüssel ungültig."; "Invalid form data." = "Formulardaten ungültig."; "Invalid form submission." = "Formulardaten ungültig."; "Invalid job ID." = "Auftragsnummer ungültig."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (Islamische Republik)"; "Iraq" = "Irak"; "Ireland" = "Irland"; "Isle of Man" = "Isle of Man"; "Israel" = "Israel"; "Italy" = "Italien"; "Jamaica" = "Jamaika"; "Japan" = "Japan"; "Jersey" = "Jersey"; "Job #" = "Auftrag #"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Aufträge"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Jordanien"; "Kazakhstan" = "Kasachstan"; "Kenya" = "Kenia"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Korea (Demokratische Volksrepublik)"; "Korea, Republic of" = "Korea, Republik"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kirgisistan"; "Landscape" = "Querformat"; "Lao People's Democratic Republic" = "Laos"; "Latvia" = "Lettland"; "Lebanon" = "Libanon"; "Lesotho" = "Lesotho"; "Level" = "Ebene"; "Liberia" = "Liberia"; "Libya" = "Libyen"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Litauen"; "Location" = "Standort"; "Log Level" = "Protokollierungsstufe"; "Logging" = "Protokollierung"; "Logs" = "Protokolle"; "Luxembourg" = "Luxemburg"; "Macao" = "Macao"; "Madagascar" = "Madagaskar"; "Malawi" = "Malawi"; "Malaysia" = "Malaysia"; "Maldives" = "Malediven"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Marshallinseln"; "Martinique" = "Martinique"; "Mauritania" = "Mauretanien"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Medien"; "Mexico" = "Mexiko"; "Micronesia (Federated States of)" = "Mikronesien (Bundesstaaten)"; "Missing action." = "Fehlende Aktivität."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "Der private Schlüssel fehlt."; "Moldova, Republic of" = "Republik Moldau"; "Monaco" = "Monaco"; "Mongolia" = "Mongolei"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Marokko"; "Mozambique" = "Mosambik"; "Myanmar" = "Myanmar"; "Name" = "Name"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Niederlande"; "Network" = "Netzwerk"; "Network Printer" = "Netzwerkdrucker"; "Networking" = "Vernetzung"; "New Caledonia" = "Neukaledonien"; "New Zealand" = "Neuseeland"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "Kein Standard-Drucker gesetzt."; "No jobs in history." = "Keine Aufträge in der Historie."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "Nordmakedonien"; "Northern Mariana Islands" = "Nördliche Marianen"; "Norway" = "Norwegen"; "Not set" = "Nicht gesetzt"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Optionen:"; "Organization" = "Organisation"; "Organization Name" = "Name der Organisation"; "Other Settings" = "Weitere Einstellungen"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palästina"; "Panama" = "Panama"; "Papua New Guinea" = "Papua-Neuguinea"; "Paraguay" = "Paraguay"; "Password" = "Passwort"; "Password changed." = "Passwort geändert."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Das Passwort muss mindestens acht Zeichen lang sein und mindestens einen Großbuchstaben, einen Kleinbuchstaben und eine Ziffer enthalten."; "Passwords do not match." = "Passwörter passen nicht."; "Pause Printing" = "Drucken pausieren"; "Peru" = "Peru"; "Philippines" = "Philippinen"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Bitte geben Sie einen Hostnamen oder eine IP-Adresse für den Drucker ein."; "Please enter a printer name." = "Bitte geben Sie einen Druckernamen ein."; "Please select a device." = "Bitte wählen Sie ein Gerät aus."; "Please select a driver." = "Bitte wählen Sie einen Treiber aus."; "Please select a valid log level." = "Bitte wählen Sie einen gültigen Protokollierungsgrad aus."; "Poland" = "Polen"; "Portrait" = "Hochformat"; "Portugal" = "Portugal"; "Primary DNS" = "Primary DNS"; "Print Group" = "Drucker Gruppe"; "Print Test Page" = "Testseite drucken"; "Print job options:" = "Druckauftrag Optionen:"; "Printer identified." = "Drucker identifiziert."; "Printer is currently active." = "Drucker ist derzeit aktiv."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Druckernamen müssen mit einem Buchstaben oder Unterstrich beginnen und dürfen keine Sonderzeichen enthalten."; "Printer options:" = "Druckeroptionen:"; "Printer paused." = "Drucker pausiert."; "Printer pausing." = "Drucker pausiert."; "Printer resuming." = "Drucker neu gestartet."; "Printers" = "Drucker"; "Printing Defaults" = "Drucker Voreinstellungen"; "Puerto Rico" = "Puerto Rico"; "Qatar" = "Katar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Auftrag erneut drucken"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Druck fortsetzen"; "Reverse Landscape" = "Querformat (rotiert)"; "Reverse Portrait" = "Hochformat (rotiert)"; "Romania" = "Rumänien"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "In Bearbeitung, %s seit %s %s ."; "Russian Federation" = "Russische Föderation"; "Rwanda" = "Ruanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "St. Helena, Ascension und Tristan da Cunha"; "Saint Kitts and Nevis" = "St. Kitts und Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (französischer Teil)"; "Saint Pierre and Miquelon" = "Saint Pierre und Miquelon"; "Saint Vincent and the Grenadines" = "St. Vincent und die Grenadinen"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome und Principe"; "Saudi Arabia" = "Saudi-Arabien"; "Save Changes" = "Änderungen speichern"; "Secondary DNS" = "Secondary DNS"; "Security" = "Sicherheit"; "Select Driver" = "Wählen Sie einen Treiber"; "Senegal" = "Senegal"; "Serbia" = "Serbien"; "Server is not running." = "Server läuft nicht."; "Set Access Password" = "Zugangspasswort setzen"; "Set as Default" = "Als Standard setzen"; "Seychelles" = "Seychellen"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapur"; "Sint Maarten (Dutch part)" = "Sint Maarten (niederländischer Teil)"; "Slovakia" = "Slowakei"; "Slovenia" = "Slowenien"; "Solomon Islands" = "Salomonen"; "Somalia" = "Somalia"; "South Africa" = "Südafrika"; "South Georgia and the South Sandwich Islands" = "Südgeorgien und südliche Sandwichinseln"; "South Sudan" = "Südsudan"; "Spain" = "Spanien"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "Status"; "Sub-commands:" = "Unterbefehle:"; "Sudan" = "Sudan"; "Supplies" = "Verbrauchsmaterialien"; "Suriname" = "Surinam"; "Svalbard and Jan Mayen" = "Svalbard und Jan Mayen"; "Sweden" = "Schweden"; "Switzerland" = "Schweiz"; "Syrian Arab Republic" = "Arabische Republik Syrien"; "Taiwan, Province of China" = "Taiwan"; "Tajikistan" = "Tadschikistan"; "Tanzania, United Republic of" = "Tansania, Vereinigte Republik"; "Test page printed." = "Testseite gedruckt."; "Thailand" = "Thailand"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Dieses Formular erstellt eine Bescheinigungsunterzeichnungsanfrage (CSR), die Sie an eine Bescheinigungsbehörde (CA) senden können, um ein vertrauenswürdiges TLS-Zertifikat zu erhalten. Der private Schlüssel wird für die Verwendung mit dem Zertifikat, das Sie von der CA erhalten, separat gespeichert."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Dieses Formular erstellt ein neues selbstsigniertes TLS-Zertifikat zum sicheren Drucken. Selbstsignierte Zertifikate werden nicht automatisch von Webbrowsern akzeptiert."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Dieses Formular wird ein vertrauenswürdiges TLS-Zertifikat installieren, das Sie von einer Certificate Authority (CA.) erhalten haben. Nach der Installation wird es sofort verwendet."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad und Tobago"; "Tunisia" = "Tunesien"; "Turkey" = "Türkei"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Turks- und Caicosinseln"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukraine"; "Unable to access test print file." = "Zugriff auf Test-Druckdatei fehlgeschlagen."; "Unable to copy print job." = "Druckauftrag konnte nicht kopiert werden."; "Unable to create certificate request." = "Zertifikatsanforderung konnte nicht erstellt werden."; "Unable to create certificate." = "Zertifikat zu konnte nicht erstellt werden."; "Unable to create test print job." = "Test-Druckauftrag konnte nicht erstellt werden."; "Unable to identify printer." = "Drucker konnte nicht identifiziert werden."; "Unable to lookup address." = "Adresse nicht gefunden."; "Unable to use that driver." = "Dieser Treiber konnte nicht benutzt werden."; "United Arab Emirates" = "Vereinigte Arabische Emirate"; "United Kingdom" = "Vereinigtes Königreich"; "United Kingdom of Great Britain and Northern Ireland" = "Vereinigtes Königreich Großbritannien und Nordirland"; "United States Minor Outlying Islands" = "Kleinere Inselbesitzungen der Vereinigten Staaten"; "United States of America" = "Vereinigte Staaten von Amerika"; "Unknown" = "Unbekannt"; "Unknown action." = "Unbekannte Handlung."; "Unknown form action." = "Unbekannte Formular Aktivität."; "Unknown form request." = "Unbekannte Formularanfrage."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Verwendung: %s SUB-COMMAND [OPTIONEN] (DATEINAME)\n"; "Use My Position" = "Verwenden Sie meine Position"; "Users" = "Benutzer"; "Uzbekistan" = "Usbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (Bolivarianische Republik)"; "Version %s" = "Version %s"; "Viet Nam" = "Vietnam"; "View Logs" = "Protokoll anzeigen"; "Virgin Islands (British)" = "Jungferninseln (Britisch)"; "Virgin Islands (U.S.)" = "Jungferninseln (USA)"; "Wallis and Futuna" = "Wallis und Futuna"; "Warning" = "Warnung"; "Western Sahara" = "Westsahara"; "Wi-Fi Configuration" = "Wi-Fi Konfiguration"; "Wi-Fi Network" = "WLAN-Netzwerk"; "Width" = "Breite"; "Wrong old password." = "Altes Passwort war falsch."; "Yemen" = "Jemen"; "Zambia" = "Sambia"; "Zimbabwe" = "Simbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Anzahl der Kopien"; "default printer" = "Standarddrucker"; "finishings" = "Veredelung"; "finishings.10" = "Faltung"; "finishings.100" = "Z Faltung"; "finishings.101" = "Engineering Z falten"; "finishings.11" = "Schneiden"; "finishings.12" = "Balsame"; "finishings.13" = "Buchmacher"; "finishings.15" = "Beschichtung"; "finishings.16" = "Laminat"; "finishings.20" = "Oben links klammern"; "finishings.21" = "Unten links klammern"; "finishings.22" = "Oben rechts klammern"; "finishings.23" = "Unten rechts klammern"; "finishings.24" = "Randstich links"; "finishings.25" = "Randstich oben"; "finishings.26" = "Randstich rechts"; "finishings.27" = "Randstich unten"; "finishings.28" = "2 Klammern auf der linken Seite"; "finishings.29" = "2 Klammern oben"; "finishings.3" = "Keine"; "finishings.30" = "2 Klammern rechts"; "finishings.31" = "2 Klammern auf der Unterseite"; "finishings.32" = "3 Klammern auf der linken Seite"; "finishings.33" = "3 Klammern oben"; "finishings.34" = "3 Klammern rechts"; "finishings.35" = "3 Klammern auf der Unterseite"; "finishings.4" = "Stapel"; "finishings.5" = "Lochen"; "finishings.50" = "Bindung links"; "finishings.51" = "Bindung oben"; "finishings.52" = "Bindung rechts"; "finishings.53" = "Bindung unten"; "finishings.6" = "Deckblatt"; "finishings.60" = "Nach jeder Seite schneiden"; "finishings.61" = "Nach jedem Dokument schneiden"; "finishings.62" = "Nach jedem Set schneiden"; "finishings.63" = "Nach dem Job schneiden"; "finishings.7" = "Bindung"; "finishings.70" = "Punch oben links"; "finishings.71" = "Punch unten links"; "finishings.72" = "Punch oben rechts"; "finishings.73" = "Punch unten rechts"; "finishings.74" = "2-Loch-Punch links"; "finishings.75" = "2-Loch-Dämpfung"; "finishings.76" = "2-Loch-Puzzle rechts"; "finishings.77" = "2-Loch-Dämpfung"; "finishings.78" = "3-Loch-Stempel links"; "finishings.79" = "3-Loch-Puzzle"; "finishings.8" = "Sattelstich"; "finishings.80" = "3-Loch-Stempel rechts"; "finishings.81" = "3-Loch-Plattenboden"; "finishings.82" = "4-Loch-Stempel links"; "finishings.83" = "4-Loch-Puzzle"; "finishings.84" = "4-Loch-Stempel rechts"; "finishings.85" = "4-Loch-Plattenboden"; "finishings.86" = "Mehrlochstempel links"; "finishings.87" = "Multi-Loch-Stempel oben"; "finishings.88" = "Mehrlochstempel rechts"; "finishings.89" = "Mehrloch-Stanzboden"; "finishings.9" = "Randstich"; "finishings.90" = "Akkordeonfaltung"; "finishings.91" = "Doppeltorfalte"; "finishings.92" = "Torfalte"; "finishings.93" = "Halbe Falte"; "finishings.94" = "Halbe Z Falten"; "finishings.95" = "linke Torfalte"; "finishings.96" = "Brieffaltung"; "finishings.97" = "Parallelfaltung"; "finishings.98" = "Posterfaltung"; "finishings.99" = "rechte Torfalte"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Stoppen."; "job-state-reasons.compression-error" = "Dekompressionsfehler."; "job-state-reasons.document-format-error" = "Dokument-Format-Fehler."; "job-state-reasons.document-password-error" = "Dokument-Passwort-Fehler."; "job-state-reasons.document-permission-error" = "Dokument-Berechtigungsfehler."; "job-state-reasons.document-unprintable-error" = "Fehler: Dokument nicht druckbar."; "job-state-reasons.errors-detected" = "Fehler erkannt."; "job-state-reasons.job-canceled-at-device" = "Am Drucker abgebrochen."; "job-state-reasons.job-canceled-by-user" = "Vom Benutzer abgebrochen."; "job-state-reasons.job-completed-successfully" = "Gedruckt."; "job-state-reasons.job-completed-with-errors" = "Gedruckt (mit Fehlern)."; "job-state-reasons.job-completed-with-warnings" = "Gedruckt (mit Warnungen)."; "job-state-reasons.job-data-insufficient" = "Unzureichende Daten."; "job-state-reasons.job-fetchable" = "Abholbereit."; "job-state-reasons.job-incoming" = "Eingehend."; "job-state-reasons.job-printing" = "Druck läuft."; "job-state-reasons.job-queued" = "Vorbereitung auf den Druck."; "job-state-reasons.job-spooling" = "Warteschlange."; "job-state-reasons.none" = "Wartend."; "job-state-reasons.printer-stopped" = "Drucker offline."; "job-state-reasons.printer-stopped-partly" = "Der Drucker wurde teilweise gestoppt."; "job-state-reasons.processing-to-stop-point" = "Stoppend."; "job-state-reasons.queued-in-device" = "Fertig."; "job-state-reasons.warnings-detected" = "Warnungen entdeckt."; "job-state.3" = "Anstehend"; "job-state.4" = "Zurückgehalten"; "job-state.5" = "In Verarbeitung"; "job-state.6" = "Gestoppt"; "job-state.7" = "Zurückgezogen"; "job-state.8" = "Abgebrochen"; "job-state.9" = "Abgeschlossen"; "joining" = "Fügen Sie"; "media" = "Medien"; "media-col" = "Medien"; "media-size" = "Mediengröße"; "media-size-name" = "Mediengröße"; "media-source" = "Eingabeschacht"; "media-source.alternate" = "Alternativer Ausgabeschacht"; "media-source.alternate-roll" = "Rollenwechsel"; "media-source.auto" = "Automatisch"; "media-source.bottom" = "Unten"; "media-source.by-pass-tray" = "Mehrzweck-Zuführung"; "media-source.center" = "Mitte"; "media-source.disc" = "Scheiben"; "media-source.envelope" = "Briefumschlag (Envelope)"; "media-source.hagaki" = "Postkarte ('Hagaki')"; "media-source.large-capacity" = "Große Kapazität"; "media-source.left" = "Links"; "media-source.main" = "Haupt"; "media-source.main-roll" = "Hauptrolle"; "media-source.manual" = "Handbuch"; "media-source.middle" = "Mittel"; "media-source.photo" = "Foto"; "media-source.rear" = "Rückseitig"; "media-source.right" = "Rechts"; "media-source.roll-1" = "Rolle 1"; "media-source.roll-10" = "Rolle 10"; "media-source.roll-2" = "Rolle 2"; "media-source.roll-3" = "Rolle 3"; "media-source.roll-4" = "Rolle 4"; "media-source.roll-5" = "Rolle 5"; "media-source.roll-6" = "Rolle 6"; "media-source.roll-7" = "Rolle 7"; "media-source.roll-8" = "Rolle 8"; "media-source.roll-9" = "Rolle 9"; "media-source.side" = "Seite"; "media-source.top" = "Oben"; "media-source.tray-1" = "Schacht 1"; "media-source.tray-10" = "Schacht 10"; "media-source.tray-11" = "Schacht 11"; "media-source.tray-12" = "Schacht 12"; "media-source.tray-13" = "Schacht 13"; "media-source.tray-14" = "Schacht 14"; "media-source.tray-15" = "Schacht 15"; "media-source.tray-16" = "Schacht 16"; "media-source.tray-17" = "Schacht 17"; "media-source.tray-18" = "Schacht 18"; "media-source.tray-19" = "Schacht 19"; "media-source.tray-2" = "Schacht 2"; "media-source.tray-20" = "Schacht 20"; "media-source.tray-3" = "Schacht 3"; "media-source.tray-4" = "Schacht 4"; "media-source.tray-5" = "Schacht 5"; "media-source.tray-6" = "Schacht 6"; "media-source.tray-7" = "Schacht 7"; "media-source.tray-8" = "Schacht 8"; "media-source.tray-9" = "Schacht 9"; "media-tracking" = "Medienverfolgung"; "media-tracking.continuous" = "Kontinuierlich"; "media-tracking.gap" = "Abstand"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Internet"; "media-type" = "Medientyp"; "media-type.aluminum" = "Aluminium"; "media-type.auto" = "Automatisch"; "media-type.back-print-film" = "Rückseitig bedruckte Folie"; "media-type.cardboard" = "Pappe"; "media-type.cardstock" = "Karten"; "media-type.cd" = "CD"; "media-type.continuous" = "Kontinuierlich"; "media-type.continuous-long" = "Kontinuierlich (lang)"; "media-type.continuous-short" = "Kontinuierlich (kurz)"; "media-type.corrugated-board" = "Wellpappe"; "media-type.disc" = "Optischer Datenträger"; "media-type.disc-glossy" = "Optischer Datenträger (glänzend)"; "media-type.disc-high-gloss" = "Optischer Datenträger (hochglänzend)"; "media-type.disc-matte" = "Optischer Datenträger (matt)"; "media-type.disc-satin" = "Optischer Datenträger (satin)"; "media-type.disc-semi-gloss" = "Optischer Datenträger (halbglänzend)"; "media-type.double-wall" = "Doppelwand"; "media-type.dry-film" = "Trockenfilm"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Prägefolie"; "media-type.end-board" = "Endpunkt"; "media-type.envelope" = "Umschlag"; "media-type.envelope-archival" = "Archiv-Umschlag"; "media-type.envelope-bond" = "Umschlag (Bond)"; "media-type.envelope-coated" = "Umschlag (Beschichtet)"; "media-type.envelope-cotton" = "Umschlag (Baumwolle)"; "media-type.envelope-fine" = "Umschlag (Fein)"; "media-type.envelope-heavyweight" = "Umschlag (schwer)"; "media-type.envelope-inkjet" = "Umschlag (Tintenstrahldruck)"; "media-type.envelope-lightweight" = "Umschlag (leicht)"; "media-type.envelope-plain" = "Umschlag (unbedruckt)"; "media-type.envelope-preprinted" = "Umschlag (bedruckt)"; "media-type.envelope-window" = "Umschlag (mit Sichtfenster)"; "media-type.fabric" = "Gewebe"; "media-type.fabric-archival" = "Gewebe (Archivierung)"; "media-type.fabric-glossy" = "Stoff (glänzend)"; "media-type.fabric-high-gloss" = "Stoff (hochglänzend)"; "media-type.fabric-matte" = "Stoff (matt)"; "media-type.fabric-semi-gloss" = "Gewebe (halbglänzend)"; "media-type.fabric-waterproof" = "Gewebe (wasserfest)"; "media-type.film" = "Film-Medium"; "media-type.flexo-base" = "Flexo-Basis"; "media-type.flexo-photo-polymer" = "Flexo-Fotopolymer"; "media-type.flute" = "Fluten"; "media-type.foil" = "Folie"; "media-type.full-cut-tabs" = "Vollschnitt Tabs"; "media-type.glass" = "Glas"; "media-type.glass-colored" = "Glas (gefärbt)"; "media-type.glass-opaque" = "Glas (undurchsichtig)"; "media-type.glass-surfaced" = "Glas (beschichtet)"; "media-type.glass-textured" = "Glas (strukturiert)"; "media-type.gravure-cylinder" = "Gravurzylinder"; "media-type.image-setter-paper" = "Belichterpapier"; "media-type.imaging-cylinder" = "Imaging-Zylinder"; "media-type.labels" = "Etiketten"; "media-type.labels-colored" = "Farbige Etiketten"; "media-type.labels-glossy" = "Glossy Etiketten"; "media-type.labels-high-gloss" = "Hochglänzende Etiketten"; "media-type.labels-inkjet" = "Inkjet Etiketten"; "media-type.labels-matte" = "Matte Etiketten"; "media-type.labels-permanent" = "Permanente Etiketten"; "media-type.labels-satin" = "Satin Etiketten"; "media-type.labels-security" = "Sicherheitsetiketten"; "media-type.labels-semi-gloss" = "Halbglänzende Etiketten"; "media-type.laminating-foil" = "Laminierfolie"; "media-type.letterhead" = "Briefkopf (vorbedruckt)"; "media-type.metal" = "Metall"; "media-type.metal-glossy" = "Metall glänzend"; "media-type.metal-high-gloss" = "Metall Hochglanz"; "media-type.metal-matte" = "Metall matt"; "media-type.metal-satin" = "Metall satiniert"; "media-type.metal-semi-gloss" = "Metall Halbglanz"; "media-type.mounting-tape" = "Montageband"; "media-type.multi-layer" = "Mehrere Lagen"; "media-type.multi-part-form" = "Mehrteilige Form"; "media-type.other" = "Sonstige"; "media-type.paper" = "Papier"; "media-type.photographic" = "Fotopapier"; "media-type.photographic-archival" = "Fotografische Archivierung"; "media-type.photographic-film" = "Fotofilm"; "media-type.photographic-glossy" = "Glossy Fotopapier"; "media-type.photographic-high-gloss" = "Hochglanz-Fotopapier"; "media-type.photographic-matte" = "Mattes Fotopapier"; "media-type.photographic-satin" = "Satin Fotopapier"; "media-type.photographic-semi-gloss" = "Halbglänzendes Fotopapier"; "media-type.plastic" = "Kunststoff"; "media-type.plastic-archival" = "Kunststoff (Archivierung)"; "media-type.plastic-colored" = "Kunststoff gefärbt"; "media-type.plastic-glossy" = "Kunststoff glänzend"; "media-type.plastic-high-gloss" = "Kunststoff Hochglanz"; "media-type.plastic-matte" = "Kunststoff matt"; "media-type.plastic-satin" = "Kunststoff satiniert"; "media-type.plastic-semi-gloss" = "Kunststoff Halbglanz"; "media-type.plate" = "Druckplatte"; "media-type.polyester" = "Polyestermaterial"; "media-type.pre-cut-tabs" = "Vorgeschnittene Tabs"; "media-type.roll" = "Rollen"; "media-type.screen" = "Bildschirm"; "media-type.screen-paged" = "Bildschirm (paginiert)"; "media-type.self-adhesive" = "Selbstklebend"; "media-type.self-adhesive-film" = "Selbstklebende Folie"; "media-type.shrink-foil" = "Schrumpffolie"; "media-type.single-face" = "Einzelfläche"; "media-type.single-wall" = "Einzelwand"; "media-type.sleeve" = "Hülse (Sleeve)"; "media-type.stationery" = "Schreibpapier"; "media-type.stationery-archival" = "Schreibpapier (für Archivierung)"; "media-type.stationery-coated" = "beschichtetes Papier"; "media-type.stationery-cotton" = "Schreibpapier (aus Baumwolle)"; "media-type.stationery-fine" = "Pergament"; "media-type.stationery-heavyweight" = "Schweres Papier"; "media-type.stationery-heavyweight-coated" = "Schreibpapier (schwer, beschichtet)"; "media-type.stationery-inkjet" = "Inkjet-Papiere für Schreibwaren"; "media-type.stationery-letterhead" = "Briefkopf (vorbedruckt)"; "media-type.stationery-lightweight" = "Leichtes Papier"; "media-type.stationery-preprinted" = "Papier (vorbedruckt)"; "media-type.stationery-prepunched" = "Papier (gelocht)"; "media-type.tab-stock" = "Auf Lager"; "media-type.tractor" = "Traktor"; "media-type.transfer" = "Transfermedium"; "media-type.transparency" = "Transparentes Medium"; "media-type.triple-wall" = "Triple Wand"; "media-type.wet-film" = "Nassfilm"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 oder US-Brief"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Umschlag"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Entwicklung"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Umschlag"; "media.iso_c10_28x40mm" = "C10 Umschlag"; "media.iso_c1_648x917mm" = "C1 Umschlag"; "media.iso_c2_458x648mm" = "C2 Umschlag"; "media.iso_c3_324x458mm" = "C3 Umschlag"; "media.iso_c4_229x324mm" = "C4 Umschlag"; "media.iso_c5_162x229mm" = "C5 Umschlag"; "media.iso_c6_114x162mm" = "C6 Umschlag"; "media.iso_c6c5_114x229mm" = "C6/C5 Umschlag"; "media.iso_c7_81x114mm" = "C7 Umschlag"; "media.iso_c7c6_81x162mm" = "C7/C6 Umschlag"; "media.iso_c8_57x81mm" = "C8 Umschlag"; "media.iso_c9_40x57mm" = "C9 Umschlag"; "media.iso_dl_110x220mm" = "DL Umschlag"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Exekutive"; "media.jpn_chou2_111.1x146mm" = "Umbau Chou 2"; "media.jpn_chou3_120x235mm" = "Umschlag Chou 3"; "media.jpn_chou40_90x225mm" = "Umschlag Chou 40"; "media.jpn_chou4_90x205mm" = "Umbau Chou 4"; "media.jpn_hagaki_100x148mm" = "Postkarte (Hagaki)"; "media.jpn_kahu_240x322.1mm" = "Umschlag (Kahu)"; "media.jpn_kaku2_240x332mm" = "Umschlag Kahu 2"; "media.jpn_oufuku_148x200mm" = "Antwortpostkarte (Oufuku Reply Postcard)"; "media.jpn_you4_105x235mm" = "Envelope Sie 4"; "media.na_a2_4.375x5.75in" = "Umbau A2"; "media.na_c5_6.5x9.5in" = "Umbau C5"; "media.na_executive_7.25x10.5in" = "Exekutive"; "media.na_fanfold-eur_8.5x12in" = "Endlospapier (EU)"; "media.na_fanfold-us_11x14.875in" = "Endlospapier (US)"; "media.na_foolscap_8.5x13in" = "Kanzleipapier (Foolscap)"; "media.na_invoice_5.5x8.5in" = "Rechnung"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US 'Letter' Format (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US 'Letter' Format (Plus)"; "media.na_letter_8.5x11in" = "US 'Letter' Format"; "media.na_monarch_3.875x7.5in" = "Monarch Briefumschlag"; "media.na_number-10_4.125x9.5in" = "Briefumschlag #10"; "media.na_number-11_4.5x10.375in" = "Briefumschlag #11"; "media.na_number-12_4.75x11in" = "Briefumschlag #12"; "media.na_number-14_5x11.5in" = "Briefumschlag #14"; "media.na_number-9_3.875x8.875in" = "Briefumschlag #9"; "media.na_personal_3.625x6.5in" = "Persönlicher Umschlag"; "media.na_quarto_8.5x10.83in" = "Amerikanisches Quarto"; "media.om_folio-sp_215x315mm" = "Fohlen"; "media.om_folio_210x330mm" = "Folioformat (Spezial)"; "media.om_invite_220x220mm" = "Envelope Einladung"; "media.om_italian_110x230mm" = "Briefumschlag Italienisch"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389m m"; "media.om_postfix_114x229mm" = "Postfix umwandeln"; "media.prc_10_324x458mm" = "Briefumschlag chinesisch #10"; "media.prc_16k_146x215mm" = "Chinesisch 16k"; "media.prc_1_102x165mm" = "Briefumschlag chinesisch #1"; "media.prc_2_102x176mm" = "Briefumschlag chinesisch #2"; "media.prc_32k_97x151mm" = "Chinesisch 32k"; "media.prc_3_125x176mm" = "Briefumschlag chinesisch #3"; "media.prc_4_110x208mm" = "Briefumschlag chinesisch #4"; "media.prc_5_110x220mm" = "Briefumschlag chinesisch #5"; "media.prc_6_120x320mm" = "Briefumschlag chinesisch #6"; "media.prc_7_160x230mm" = "Briefumschlag chinesisch #7"; "media.prc_8_120x309mm" = "Briefumschlag chinesisch #8"; "media.roc_16k_7.75x10.75in" = "ROC/Kai 16k"; "media.roc_8k_10.75x15.5in" = "ROG 8k"; "not configured" = "nicht konfiguriert"; "not visible" = "nicht sichtbar"; "off" = "Aus"; "on" = "An"; "orientation-requested" = "Orientierung"; "orientation-requested.3" = "Hochformat (Portrait)"; "orientation-requested.4" = "Querformat (Landscape)"; "orientation-requested.5" = "Querformat (gespiegelt)"; "orientation-requested.6" = "Hochformat (gespiegelt)"; "orientation-requested.7" = "Keine"; "output-bin" = "Ausgabeschacht"; "output-bin.auto" = "Automatisch"; "output-bin.bottom" = "Unten"; "output-bin.center" = "Mitte"; "output-bin.face-down" = "Druckseite nach unten"; "output-bin.face-up" = "Druckseite nach oben"; "output-bin.large-capacity" = "Große Kapazität"; "output-bin.left" = "Links"; "output-bin.mailbox-1" = "Postfach 1"; "output-bin.mailbox-10" = "Postfach 10"; "output-bin.mailbox-2" = "Postfach 2"; "output-bin.mailbox-3" = "Postfach 3"; "output-bin.mailbox-4" = "Postfach 4"; "output-bin.mailbox-5" = "Postfach 5"; "output-bin.mailbox-6" = "Postfach 6"; "output-bin.mailbox-7" = "Postfach 7"; "output-bin.mailbox-8" = "Postfach 8"; "output-bin.mailbox-9" = "Postfach 9"; "output-bin.middle" = "Mitte"; "output-bin.my-mailbox" = "Mein Postfach"; "output-bin.rear" = "Rückseitig"; "output-bin.right" = "Rechts"; "output-bin.side" = "Seitlich"; "output-bin.stacker-1" = "Stapler 1"; "output-bin.stacker-10" = "Stapler 10"; "output-bin.stacker-2" = "Stapler 2"; "output-bin.stacker-3" = "Stapler 3"; "output-bin.stacker-4" = "Stapler 4"; "output-bin.stacker-5" = "Stapler 5"; "output-bin.stacker-6" = "Stapler 6"; "output-bin.stacker-7" = "Stapler 7"; "output-bin.stacker-8" = "Stapler 8"; "output-bin.stacker-9" = "Stapler 9"; "output-bin.top" = "Oben"; "output-bin.tray-1" = "Ausgabeschacht 1"; "output-bin.tray-10" = "Ausgabeschacht 10"; "output-bin.tray-2" = "Ausgabeschacht 2"; "output-bin.tray-3" = "Ausgabeschacht 3"; "output-bin.tray-4" = "Ausgabeschacht 4"; "output-bin.tray-5" = "Ausgabeschacht 5"; "output-bin.tray-6" = "Ausgabeschacht 6"; "output-bin.tray-7" = "Ausgabeschacht 7"; "output-bin.tray-8" = "Ausgabeschacht 8"; "output-bin.tray-9" = "Ausgabeschacht 9"; "print-color-mode" = "Druckmodus"; "print-color-mode.auto" = "Automatisch"; "print-color-mode.auto-monochrome" = "Auto monochrom"; "print-color-mode.bi-level" = "Text"; "print-color-mode.color" = "Farbe"; "print-color-mode.highlight" = "Hervorhebung"; "print-color-mode.monochrome" = "Monochrom"; "print-color-mode.process-bi-level" = "Verfahren Text"; "print-color-mode.process-monochrome" = "Verfahren monochrom"; "print-content-optimize" = "Optimieren für"; "print-content-optimize.auto" = "Automatisch"; "print-content-optimize.graphic" = "Grafik"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text und Grafik"; "print-darkness" = "Drucksättigung"; "print-quality" = "Druckqualität"; "print-quality.3" = "Entwurf"; "print-quality.4" = "Normal"; "print-quality.5" = "Beste"; "print-scaling" = "Skalierung"; "print-scaling.auto" = "Automatisch"; "print-scaling.auto-fit" = "Automatisch einpassen"; "print-scaling.fill" = "Füllung"; "print-scaling.fit" = "Einpassen"; "print-scaling.none" = "Keine"; "print-speed" = "Druckgeschwindigkeit"; "printer-resolution" = "Druckauflösung"; "printer-state-reasons.cover-open" = "Abdeckung offen."; "printer-state-reasons.door-open" = "Tür offen."; "printer-state-reasons.identify-printer-requested" = "Drucker identifizieren."; "printer-state-reasons.input-tray-missing" = "Papierzuführung fehlt."; "printer-state-reasons.marker-supply-empty" = "Tintentank leer."; "printer-state-reasons.marker-supply-low" = "Tintenstand niedrig."; "printer-state-reasons.marker-waste-almost-full" = "Abfallbehälter fast voll."; "printer-state-reasons.marker-waste-full" = "Abfallbehälter voll."; "printer-state-reasons.media-empty" = "Papierzuführung leer."; "printer-state-reasons.media-jam" = "Papierstau."; "printer-state-reasons.media-low" = "Füllen Sie bald Papier nach."; "printer-state-reasons.media-needed" = "Papier laden."; "printer-state-reasons.none" = "Fertig."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "Siehe Drucker."; "printer-state-reasons.spool-area-full" = "Drucker beschäftigt."; "printer-state-reasons.toner-empty" = "Tonerbehälter leer."; "printer-state-reasons.toner-low" = "Tonerstand niedrig."; "printer-state.3" = "Leerlauf"; "printer-state.4" = "Verarbeitung"; "printer-state.5" = "Gestoppt"; "sides" = "Doppelseitiger Druck"; "sides.one-sided" = "Aus"; "sides.two-sided-long-edge" = "An (Hochformat)"; "sides.two-sided-short-edge" = "An (Querformat)"; "unable to join" = "Zusammenfügen fehlgeschlagen"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Åland (Inselgruppe)"; pappl-1.4.9/pappl/strings/de_strings.h000066400000000000000000001606261476704353100200050ustar00rootroot00000000000000static const char *de_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Alle Jobs abbrechen (cancel).\";\n" "\" -c COPIES\" = \" -c KOPIEN\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Drucker angeben.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Druckjob ID angeben (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Geben Sie den Treiber an (Hinzufügen/Ändern).\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Geben Sie die Anzahl der Exemplare an.\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (Standard)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=WERT Option angeben (add,modify,server,submit).\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 bis 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 bis 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='ORT'\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organizationn='ORGANISATION'\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='Abteilung'\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Spezifizieren Sie ipp: oder ipps: Drucker/Server.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Schnittstelle / Socket angeben: oder USB: Gerät (add/modify).\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Einen Drucker hinzufügen.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Unterstützte Drucker automatisch hinzufügen.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Stornierung einer oder mehrerer Druckaufträge.\";\n" "\" default Set the default printer.\" = \" default Setzen Sie den Standarddrucker.\";\n" "\" delete Delete a printer.\" = \" delete Löschen eines Druckers.\";\n" "\" devices List devices.\" = \" devices Geräte auflisten.\";\n" "\" drivers List drivers.\" = \" drivers Treiber auflisten.\";\n" "\" jobs List jobs.\" = \" jobs Aufträge auflisten.\";\n" "\" modify Modify a printer.\" = \" modify Drucker ändern.\";\n" "\" options List printer options.\" = \" options Liste der Druckeroptionen.\";\n" "\" pause Pause printing for a printer.\" = \" pause Druck pausieren.\";\n" "\" printers List printers.\" = \" printers Drucker auflisten.\";\n" "\" resume Resume printing for a printer.\" = \" resume Druck fortsetzen.\";\n" "\" server Run a server.\" = \" server Server ausführen.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Abschalten eines laufenden Servers.\";\n" "\" status Show server/printer/job status.\" = \" status Server/Drucker/Auftragsstatus anzeigen.\";\n" "\" submit Submit a file for printing.\" = \" submit Senden Sie eine Datei zum Drucken.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d zoll/s\";\n" "\"%d job\" = \"%d Job\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%d dpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g \\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s ( %s %s )\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) aus %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Medien\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Unpassender Server-Port.\";\n" "\"%s: Bad job ID.\" = \"%s: Unpassende Job-ID.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Unpassender Drucker URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Kann nicht mehr als einen Unterbefehl angeben.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Leere Druckdatei, die auf der Standardeingabe empfangen wurde.\";\n" "\"%s: Failed to create a system.\" = \"%s: Erstellung eines Systems fehlgeschlagen.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Fehlende Option '-d PRINTER'.\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Fehlende Option '-m DRIVER-NAME'.\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Fehlende Option '-v DEVICE-URI'.\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Fehlende Kopien-Anzahl nach -n.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Fehlender Gerät URI nach -v.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Fehlender Treibername nach -m.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Fehlender Dateiname nach '--'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Fehlender Rechnername nach '-h'.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Fehlende Auftrags-ID nach '-j'.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: Fehlende Option(en) nach '-o'.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Fehlender Drucker URI nach '-u'.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Fehlender Druckername nach '-d'.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Fehlendes Leerzeichen nach '-o'.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Fehlender Titel nach '-t'.\";\n" "\"%s: No default printer available.\" = \"%s: Kein Standarddrucker verfügbar.\";\n" "\"%s: No files to print.\" = \"%s: Keine Dateien zum Drucken.\";\n" "\"%s: Server is not running.\" = \"%s: Server läuft nicht.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Unterbefehl '%s' akzeptiert keine Dateien.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Unterbefehl 'autoadd' wird nicht unterstützt.\";\n" "\"%s: Too many files.\" = \"%s: Zu viele Dateien.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Zugriff auf '%s': %s nicht möglich\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Hinzufügen des Druckers nicht möglich: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Job %s konnte nicht storniert werden\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Drucker konnte nicht verbunden werden: '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Verbindung zu Server nicht möglich: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Temporäre Datei konnte nicht erstellt werden: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Drucker konnte nicht gelöscht werden: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Information nicht verfügbar '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Drucker-Information nicht verfügbar: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Druckeroptionen konnten nicht abgerufen werden: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Drucker konnte nicht geändert werden: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Drucker konnte nicht pausiert werden: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Konnte nicht gedruckt werden: %s ': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Drucker konnte nicht wieder gestartet werden: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Standard-Drucker konnte nicht festgelegt werden: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Server konnte nicht heruntergefahren werden: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Server konnte nicht gestartet werden: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Konnte nicht in temporäre Datei schreiben: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Unbekannte Option '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Unbekannte Option '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Unbekannter Unterbefehl '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Nicht unterstütztes URI-System '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Warnung - Persönliche Benutzerinformationen werden nicht in URIs unterstützt.\";\n" "\", Borderless\" = \", Randlos\";\n" "\"A printer with that name already exists.\" = \"Ein Drucker mit diesem Namen existiert bereits.\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"Drucker hinzufügen\";\n" "\"Admin Group\" = \"Admin Gruppe\";\n" "\"Afghanistan\" = \"Afghanistan\";\n" "\"Albania\" = \"Albanien\";\n" "\"Algeria\" = \"Algerien\";\n" "\"American Samoa\" = \"Amerikanisch-Samoa\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarktis\";\n" "\"Antigua and Barbuda\" = \"Antigua und Barbuda\";\n" "\"Argentina\" = \"Argentinien\";\n" "\"Armenia\" = \"Armenien\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australien\";\n" "\"Austria\" = \"Österreich\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Treiber automatisch erkennen\";\n" "\"Azerbaijan\" = \"Aserbaidschan\";\n" "\"Bad administration group.\" = \"Unpassende Verwaltungsgruppe.\";\n" "\"Bad port number.\" = \"Unpassende Port-Nummer.\";\n" "\"Bad print group.\" = \"Unpassende Druckgruppe.\";\n" "\"Bad printer defaults.\" = \"Unpassende Standard-Druckereinstellungen.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahrain\";\n" "\"Bangladesh\" = \"Bangladesch\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Weißrussland\";\n" "\"Belgium\" = \"Belgien\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermuda\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivien\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius und Saba\";\n" "\"Borderless\" = \"Randlos\";\n" "\"Bosnia and Herzegovina\" = \"Bosnien und Herzegowina\";\n" "\"Botswana\" = \"Botsuana\";\n" "\"Bouvet Island\" = \"Bouvetinsel\";\n" "\"Brazil\" = \"Brasilien\";\n" "\"British Indian Ocean Territory\" = \"Britisches Territorium im Indischen Ozean\";\n" "\"Brunei Darussalam\" = \"Brunei\";\n" "\"Bulgaria\" = \"Bulgarien\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cap Verde\";\n" "\"Cambodia\" = \"Kambodscha\";\n" "\"Cameroon\" = \"Kamerun\";\n" "\"Canada\" = \"Kanada\";\n" "\"Cancel All Jobs\" = \"Alle Druckaufträge löschen\";\n" "\"Cancel Job\" = \"Druckauftrag abbrechen\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"Abbrechend\";\n" "\"Cayman Islands\" = \"Cayman Inseln\";\n" "\"Central African Republic\" = \"Zentralafrikanische Republik\";\n" "\"Certificate created.\" = \"Zertifikat erstellt.\";\n" "\"Certificate installed.\" = \"Zertifikat installiert.\";\n" "\"Certificate request created.\" = \"Zertifikatsanfrage erstellt.\";\n" "\"Chad\" = \"Tschad\";\n" "\"Change Access Password\" = \"Zugangspasswort ändern\";\n" "\"Change Log Level\" = \"Log Level ändern\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"WLAN-Netzwerk ändern\";\n" "\"Changes Saved.\" = \"Änderungen gespeichert.\";\n" "\"Changes saved.\" = \"Änderungen gespeichert.\";\n" "\"Chile\" = \"Chile\";\n" "\"China\" = \"China\";\n" "\"Christmas Island\" = \"Weihnachtsinsel\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"Kakao (Keeling) Inseln\";\n" "\"Colombia\" = \"Kolumbien\";\n" "\"Comoros\" = \"Komoren\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"Konfiguration\";\n" "\"Configure Media\" = \"Medien konfigurieren\";\n" "\"Confirm Cancel All\" = \"Abbruch bestätigen: Alle\";\n" "\"Confirm Delete Printer\" = \"Löschung des Druckers bestätigen\";\n" "\"Congo\" = \"Kongo\";\n" "\"Congo, Democratic Republic of the\" = \"Kongo, Demokratische Republik\";\n" "\"Contact\" = \"Kontakt\";\n" "\"Cook Islands\" = \"Cookinseln\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Signatur-Anfrage für Zertifikat erzeugen\";\n" "\"Create New Certificate\" = \"Neues Zertifikat erstellen\";\n" "\"Create New TLS Certificate\" = \"Neues TLS-Zertifikat erstellen\";\n" "\"Create TLS Certificate Request\" = \"TLS Zertifikat Anfrage erzeugen\";\n" "\"Croatia\" = \"Kroatien\";\n" "\"Cuba\" = \"Kuba\";\n" "\"Curaçao\" = \"Curaçao\";\n" "\"Current Password\" = \"Aktuelles Passwort\";\n" "\"Custom Size\" = \"Benutzerdefinierte Größe\";\n" "\"Cyprus\" = \"Zypern\";\n" "\"Czechia\" = \"Tschechien\";\n" "\"Côte d'Ivoire\" = \"Côte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Service Name\";\n" "\"Debugging\" = \"Fehleranalyse\";\n" "\"Default printer set.\" = \"Standarddruckersatz.\";\n" "\"Delete\" = \"Löschen\";\n" "\"Delete Printer\" = \"Drucker löschen\";\n" "\"Denmark\" = \"Dänemark\";\n" "\"Djibouti\" = \"Dschibuti\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"Dominica\";\n" "\"Dominican Republic\" = \"Dominikanische Republik\";\n" "\"Download Certificate Request File\" = \"Certificate Request File herunterladen\";\n" "\"Ecuador\" = \"Ecuador\";\n" "\"Egypt\" = \"Ägypten\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Äquatorialguinea\";\n" "\"Eritrea\" = \"Eritrea\";\n" "\"Errors\" = \"Fehler\";\n" "\"Estonia\" = \"Estland\";\n" "\"Eswatini\" = \"Swasiland\";\n" "\"Ethiopia\" = \"Äthiopien\";\n" "\"Falkland Islands (Malvinas)\" = \"Falklandinseln (Malvinas)\";\n" "\"Faroe Islands\" = \"Färöer\";\n" "\"Fatal Errors/Conditions\" = \"Gravierende Fehler/Zustände\";\n" "\"Fiji\" = \"Fidschi\";\n" "\"Finland\" = \"Finnland\";\n" "\"France\" = \"Frankreich\";\n" "\"French Guiana\" = \"Französisch-Guayana\";\n" "\"French Polynesia\" = \"Französisch-Polynesien\";\n" "\"French Southern Territories\" = \"Französische südliche Gebiete\";\n" "\"Gabon\" = \"Gabun\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Georgien\";\n" "\"Germany\" = \"Deutschland\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Griechenland\";\n" "\"Greenland\" = \"Grönland\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Gruppenänderungen gespeichert.\";\n" "\"Guadeloupe\" = \"Guadeloupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Guinea\";\n" "\"Guinea-Bissau\" = \"Guinea-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island und McDonald Inseln\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"Heiliger Stuhl\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hongkong\";\n" "\"Hostname\" = \"Rechnername (Hostname)\";\n" "\"Human-Readable Location\" = \"Ortsbezeichnung\";\n" "\"Hungary\" = \"Ungarn\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"Island\";\n" "\"Identify Printer\" = \"Drucker identifizieren\";\n" "\"India\" = \"Indien\";\n" "\"Indonesia\" = \"Indonesien\";\n" "\"Informational\" = \"Informativ\";\n" "\"Install TLS Certificate\" = \"TLS Zertifikat installieren\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"Ungültige Auftragsnummer (Job-ID).\";\n" "\"Invalid certificate or private key.\" = \"Zertifikat oder privater Schlüssel ungültig.\";\n" "\"Invalid form data.\" = \"Formulardaten ungültig.\";\n" "\"Invalid form submission.\" = \"Formulardaten ungültig.\";\n" "\"Invalid job ID.\" = \"Auftragsnummer ungültig.\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (Islamische Republik)\";\n" "\"Iraq\" = \"Irak\";\n" "\"Ireland\" = \"Irland\";\n" "\"Isle of Man\" = \"Isle of Man\";\n" "\"Israel\" = \"Israel\";\n" "\"Italy\" = \"Italien\";\n" "\"Jamaica\" = \"Jamaika\";\n" "\"Japan\" = \"Japan\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Auftrag #\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"Aufträge\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"Jordanien\";\n" "\"Kazakhstan\" = \"Kasachstan\";\n" "\"Kenya\" = \"Kenia\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Korea (Demokratische Volksrepublik)\";\n" "\"Korea, Republic of\" = \"Korea, Republik\";\n" "\"Kuwait\" = \"Kuwait\";\n" "\"Kyrgyzstan\" = \"Kirgisistan\";\n" "\"Landscape\" = \"Querformat\";\n" "\"Lao People's Democratic Republic\" = \"Laos\";\n" "\"Latvia\" = \"Lettland\";\n" "\"Lebanon\" = \"Libanon\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Ebene\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libyen\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Litauen\";\n" "\"Location\" = \"Standort\";\n" "\"Log Level\" = \"Protokollierungsstufe\";\n" "\"Logging\" = \"Protokollierung\";\n" "\"Logs\" = \"Protokolle\";\n" "\"Luxembourg\" = \"Luxemburg\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagaskar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malaysia\";\n" "\"Maldives\" = \"Malediven\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"Marshallinseln\";\n" "\"Martinique\" = \"Martinique\";\n" "\"Mauritania\" = \"Mauretanien\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Medien\";\n" "\"Mexico\" = \"Mexiko\";\n" "\"Micronesia (Federated States of)\" = \"Mikronesien (Bundesstaaten)\";\n" "\"Missing action.\" = \"Fehlende Aktivität.\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"Der private Schlüssel fehlt.\";\n" "\"Moldova, Republic of\" = \"Republik Moldau\";\n" "\"Monaco\" = \"Monaco\";\n" "\"Mongolia\" = \"Mongolei\";\n" "\"Montenegro\" = \"Montenegro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Marokko\";\n" "\"Mozambique\" = \"Mosambik\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Name\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Niederlande\";\n" "\"Network\" = \"Netzwerk\";\n" "\"Network Printer\" = \"Netzwerkdrucker\";\n" "\"Networking\" = \"Vernetzung\";\n" "\"New Caledonia\" = \"Neukaledonien\";\n" "\"New Zealand\" = \"Neuseeland\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"Kein Standard-Drucker gesetzt.\";\n" "\"No jobs in history.\" = \"Keine Aufträge in der Historie.\";\n" "\"Norfolk Island\" = \"Norfolk Island\";\n" "\"North Macedonia\" = \"Nordmakedonien\";\n" "\"Northern Mariana Islands\" = \"Nördliche Marianen\";\n" "\"Norway\" = \"Norwegen\";\n" "\"Not set\" = \"Nicht gesetzt\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Optionen:\";\n" "\"Organization\" = \"Organisation\";\n" "\"Organization Name\" = \"Name der Organisation\";\n" "\"Other Settings\" = \"Weitere Einstellungen\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palästina\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua-Neuguinea\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Passwort\";\n" "\"Password changed.\" = \"Passwort geändert.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Das Passwort muss mindestens acht Zeichen lang sein und mindestens einen Großbuchstaben, einen Kleinbuchstaben und eine Ziffer enthalten.\";\n" "\"Passwords do not match.\" = \"Passwörter passen nicht.\";\n" "\"Pause Printing\" = \"Drucken pausieren\";\n" "\"Peru\" = \"Peru\";\n" "\"Philippines\" = \"Philippinen\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Bitte geben Sie einen Hostnamen oder eine IP-Adresse für den Drucker ein.\";\n" "\"Please enter a printer name.\" = \"Bitte geben Sie einen Druckernamen ein.\";\n" "\"Please select a device.\" = \"Bitte wählen Sie ein Gerät aus.\";\n" "\"Please select a driver.\" = \"Bitte wählen Sie einen Treiber aus.\";\n" "\"Please select a valid log level.\" = \"Bitte wählen Sie einen gültigen Protokollierungsgrad aus.\";\n" "\"Poland\" = \"Polen\";\n" "\"Portrait\" = \"Hochformat\";\n" "\"Portugal\" = \"Portugal\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"Drucker Gruppe\";\n" "\"Print Test Page\" = \"Testseite drucken\";\n" "\"Print job options:\" = \"Druckauftrag Optionen:\";\n" "\"Printer identified.\" = \"Drucker identifiziert.\";\n" "\"Printer is currently active.\" = \"Drucker ist derzeit aktiv.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Druckernamen müssen mit einem Buchstaben oder Unterstrich beginnen und dürfen keine Sonderzeichen enthalten.\";\n" "\"Printer options:\" = \"Druckeroptionen:\";\n" "\"Printer paused.\" = \"Drucker pausiert.\";\n" "\"Printer pausing.\" = \"Drucker pausiert.\";\n" "\"Printer resuming.\" = \"Drucker neu gestartet.\";\n" "\"Printers\" = \"Drucker\";\n" "\"Printing Defaults\" = \"Drucker Voreinstellungen\";\n" "\"Puerto Rico\" = \"Puerto Rico\";\n" "\"Qatar\" = \"Katar\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"Auftrag erneut drucken\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"Druck fortsetzen\";\n" "\"Reverse Landscape\" = \"Querformat (rotiert)\";\n" "\"Reverse Portrait\" = \"Hochformat (rotiert)\";\n" "\"Romania\" = \"Rumänien\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"In Bearbeitung, %s seit %s %s .\";\n" "\"Russian Federation\" = \"Russische Föderation\";\n" "\"Rwanda\" = \"Ruanda\";\n" "\"Réunion\" = \"Réunion\";\n" "\"Saint Barthélemy\" = \"Saint Barthélemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"St. Helena, Ascension und Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"St. Kitts und Nevis\";\n" "\"Saint Lucia\" = \"Saint Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (französischer Teil)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre und Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"St. Vincent und die Grenadinen\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Sao Tome und Principe\";\n" "\"Saudi Arabia\" = \"Saudi-Arabien\";\n" "\"Save Changes\" = \"Änderungen speichern\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"Sicherheit\";\n" "\"Select Driver\" = \"Wählen Sie einen Treiber\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbien\";\n" "\"Server is not running.\" = \"Server läuft nicht.\";\n" "\"Set Access Password\" = \"Zugangspasswort setzen\";\n" "\"Set as Default\" = \"Als Standard setzen\";\n" "\"Seychelles\" = \"Seychellen\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapur\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (niederländischer Teil)\";\n" "\"Slovakia\" = \"Slowakei\";\n" "\"Slovenia\" = \"Slowenien\";\n" "\"Solomon Islands\" = \"Salomonen\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"Südafrika\";\n" "\"South Georgia and the South Sandwich Islands\" = \"Südgeorgien und südliche Sandwichinseln\";\n" "\"South Sudan\" = \"Südsudan\";\n" "\"Spain\" = \"Spanien\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"Status\";\n" "\"Sub-commands:\" = \"Unterbefehle:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Verbrauchsmaterialien\";\n" "\"Suriname\" = \"Surinam\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard und Jan Mayen\";\n" "\"Sweden\" = \"Schweden\";\n" "\"Switzerland\" = \"Schweiz\";\n" "\"Syrian Arab Republic\" = \"Arabische Republik Syrien\";\n" "\"Taiwan, Province of China\" = \"Taiwan\";\n" "\"Tajikistan\" = \"Tadschikistan\";\n" "\"Tanzania, United Republic of\" = \"Tansania, Vereinigte Republik\";\n" "\"Test page printed.\" = \"Testseite gedruckt.\";\n" "\"Thailand\" = \"Thailand\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Dieses Formular erstellt eine Bescheinigungsunterzeichnungsanfrage (CSR), die Sie an eine Bescheinigungsbehörde (CA) senden können, um ein vertrauenswürdiges TLS-Zertifikat zu erhalten. Der private Schlüssel wird für die Verwendung mit dem Zertifikat, das Sie von der CA erhalten, separat gespeichert.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Dieses Formular erstellt ein neues selbstsigniertes TLS-Zertifikat zum sicheren Drucken. Selbstsignierte Zertifikate werden nicht automatisch von Webbrowsern akzeptiert.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Dieses Formular wird ein vertrauenswürdiges TLS-Zertifikat installieren, das Sie von einer Certificate Authority (CA.) erhalten haben. Nach der Installation wird es sofort verwendet.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad und Tobago\";\n" "\"Tunisia\" = \"Tunesien\";\n" "\"Turkey\" = \"Türkei\";\n" "\"Turkmenistan\" = \"Turkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Turks- und Caicosinseln\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ukraine\";\n" "\"Unable to access test print file.\" = \"Zugriff auf Test-Druckdatei fehlgeschlagen.\";\n" "\"Unable to copy print job.\" = \"Druckauftrag konnte nicht kopiert werden.\";\n" "\"Unable to create certificate request.\" = \"Zertifikatsanforderung konnte nicht erstellt werden.\";\n" "\"Unable to create certificate.\" = \"Zertifikat zu konnte nicht erstellt werden.\";\n" "\"Unable to create test print job.\" = \"Test-Druckauftrag konnte nicht erstellt werden.\";\n" "\"Unable to identify printer.\" = \"Drucker konnte nicht identifiziert werden.\";\n" "\"Unable to lookup address.\" = \"Adresse nicht gefunden.\";\n" "\"Unable to use that driver.\" = \"Dieser Treiber konnte nicht benutzt werden.\";\n" "\"United Arab Emirates\" = \"Vereinigte Arabische Emirate\";\n" "\"United Kingdom\" = \"Vereinigtes Königreich\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Vereinigtes Königreich Großbritannien und Nordirland\";\n" "\"United States Minor Outlying Islands\" = \"Kleinere Inselbesitzungen der Vereinigten Staaten\";\n" "\"United States of America\" = \"Vereinigte Staaten von Amerika\";\n" "\"Unknown\" = \"Unbekannt\";\n" "\"Unknown action.\" = \"Unbekannte Handlung.\";\n" "\"Unknown form action.\" = \"Unbekannte Formular Aktivität.\";\n" "\"Unknown form request.\" = \"Unbekannte Formularanfrage.\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Verwendung: %s SUB-COMMAND [OPTIONEN] (DATEINAME)\\n\";\n" "\"Use My Position\" = \"Verwenden Sie meine Position\";\n" "\"Users\" = \"Benutzer\";\n" "\"Uzbekistan\" = \"Usbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (Bolivarianische Republik)\";\n" "\"Version %s\" = \"Version %s\";\n" "\"Viet Nam\" = \"Vietnam\";\n" "\"View Logs\" = \"Protokoll anzeigen\";\n" "\"Virgin Islands (British)\" = \"Jungferninseln (Britisch)\";\n" "\"Virgin Islands (U.S.)\" = \"Jungferninseln (USA)\";\n" "\"Wallis and Futuna\" = \"Wallis und Futuna\";\n" "\"Warning\" = \"Warnung\";\n" "\"Western Sahara\" = \"Westsahara\";\n" "\"Wi-Fi Configuration\" = \"Wi-Fi Konfiguration\";\n" "\"Wi-Fi Network\" = \"WLAN-Netzwerk\";\n" "\"Width\" = \"Breite\";\n" "\"Wrong old password.\" = \"Altes Passwort war falsch.\";\n" "\"Yemen\" = \"Jemen\";\n" "\"Zambia\" = \"Sambia\";\n" "\"Zimbabwe\" = \"Simbabwe\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Anzahl der Kopien\";\n" "\"default printer\" = \"Standarddrucker\";\n" "\"finishings\" = \"Veredelung\";\n" "\"finishings.10\" = \"Faltung\";\n" "\"finishings.100\" = \"Z Faltung\";\n" "\"finishings.101\" = \"Engineering Z falten\";\n" "\"finishings.11\" = \"Schneiden\";\n" "\"finishings.12\" = \"Balsame\";\n" "\"finishings.13\" = \"Buchmacher\";\n" "\"finishings.15\" = \"Beschichtung\";\n" "\"finishings.16\" = \"Laminat\";\n" "\"finishings.20\" = \"Oben links klammern\";\n" "\"finishings.21\" = \"Unten links klammern\";\n" "\"finishings.22\" = \"Oben rechts klammern\";\n" "\"finishings.23\" = \"Unten rechts klammern\";\n" "\"finishings.24\" = \"Randstich links\";\n" "\"finishings.25\" = \"Randstich oben\";\n" "\"finishings.26\" = \"Randstich rechts\";\n" "\"finishings.27\" = \"Randstich unten\";\n" "\"finishings.28\" = \"2 Klammern auf der linken Seite\";\n" "\"finishings.29\" = \"2 Klammern oben\";\n" "\"finishings.3\" = \"Keine\";\n" "\"finishings.30\" = \"2 Klammern rechts\";\n" "\"finishings.31\" = \"2 Klammern auf der Unterseite\";\n" "\"finishings.32\" = \"3 Klammern auf der linken Seite\";\n" "\"finishings.33\" = \"3 Klammern oben\";\n" "\"finishings.34\" = \"3 Klammern rechts\";\n" "\"finishings.35\" = \"3 Klammern auf der Unterseite\";\n" "\"finishings.4\" = \"Stapel\";\n" "\"finishings.5\" = \"Lochen\";\n" "\"finishings.50\" = \"Bindung links\";\n" "\"finishings.51\" = \"Bindung oben\";\n" "\"finishings.52\" = \"Bindung rechts\";\n" "\"finishings.53\" = \"Bindung unten\";\n" "\"finishings.6\" = \"Deckblatt\";\n" "\"finishings.60\" = \"Nach jeder Seite schneiden\";\n" "\"finishings.61\" = \"Nach jedem Dokument schneiden\";\n" "\"finishings.62\" = \"Nach jedem Set schneiden\";\n" "\"finishings.63\" = \"Nach dem Job schneiden\";\n" "\"finishings.7\" = \"Bindung\";\n" "\"finishings.70\" = \"Punch oben links\";\n" "\"finishings.71\" = \"Punch unten links\";\n" "\"finishings.72\" = \"Punch oben rechts\";\n" "\"finishings.73\" = \"Punch unten rechts\";\n" "\"finishings.74\" = \"2-Loch-Punch links\";\n" "\"finishings.75\" = \"2-Loch-Dämpfung\";\n" "\"finishings.76\" = \"2-Loch-Puzzle rechts\";\n" "\"finishings.77\" = \"2-Loch-Dämpfung\";\n" "\"finishings.78\" = \"3-Loch-Stempel links\";\n" "\"finishings.79\" = \"3-Loch-Puzzle\";\n" "\"finishings.8\" = \"Sattelstich\";\n" "\"finishings.80\" = \"3-Loch-Stempel rechts\";\n" "\"finishings.81\" = \"3-Loch-Plattenboden\";\n" "\"finishings.82\" = \"4-Loch-Stempel links\";\n" "\"finishings.83\" = \"4-Loch-Puzzle\";\n" "\"finishings.84\" = \"4-Loch-Stempel rechts\";\n" "\"finishings.85\" = \"4-Loch-Plattenboden\";\n" "\"finishings.86\" = \"Mehrlochstempel links\";\n" "\"finishings.87\" = \"Multi-Loch-Stempel oben\";\n" "\"finishings.88\" = \"Mehrlochstempel rechts\";\n" "\"finishings.89\" = \"Mehrloch-Stanzboden\";\n" "\"finishings.9\" = \"Randstich\";\n" "\"finishings.90\" = \"Akkordeonfaltung\";\n" "\"finishings.91\" = \"Doppeltorfalte\";\n" "\"finishings.92\" = \"Torfalte\";\n" "\"finishings.93\" = \"Halbe Falte\";\n" "\"finishings.94\" = \"Halbe Z Falten\";\n" "\"finishings.95\" = \"linke Torfalte\";\n" "\"finishings.96\" = \"Brieffaltung\";\n" "\"finishings.97\" = \"Parallelfaltung\";\n" "\"finishings.98\" = \"Posterfaltung\";\n" "\"finishings.99\" = \"rechte Torfalte\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"Stoppen.\";\n" "\"job-state-reasons.compression-error\" = \"Dekompressionsfehler.\";\n" "\"job-state-reasons.document-format-error\" = \"Dokument-Format-Fehler.\";\n" "\"job-state-reasons.document-password-error\" = \"Dokument-Passwort-Fehler.\";\n" "\"job-state-reasons.document-permission-error\" = \"Dokument-Berechtigungsfehler.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Fehler: Dokument nicht druckbar.\";\n" "\"job-state-reasons.errors-detected\" = \"Fehler erkannt.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Am Drucker abgebrochen.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Vom Benutzer abgebrochen.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Gedruckt.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Gedruckt (mit Fehlern).\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Gedruckt (mit Warnungen).\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Unzureichende Daten.\";\n" "\"job-state-reasons.job-fetchable\" = \"Abholbereit.\";\n" "\"job-state-reasons.job-incoming\" = \"Eingehend.\";\n" "\"job-state-reasons.job-printing\" = \"Druck läuft.\";\n" "\"job-state-reasons.job-queued\" = \"Vorbereitung auf den Druck.\";\n" "\"job-state-reasons.job-spooling\" = \"Warteschlange.\";\n" "\"job-state-reasons.none\" = \"Wartend.\";\n" "\"job-state-reasons.printer-stopped\" = \"Drucker offline.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Der Drucker wurde teilweise gestoppt.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Stoppend.\";\n" "\"job-state-reasons.queued-in-device\" = \"Fertig.\";\n" "\"job-state-reasons.warnings-detected\" = \"Warnungen entdeckt.\";\n" "\"job-state.3\" = \"Anstehend\";\n" "\"job-state.4\" = \"Zurückgehalten\";\n" "\"job-state.5\" = \"In Verarbeitung\";\n" "\"job-state.6\" = \"Gestoppt\";\n" "\"job-state.7\" = \"Zurückgezogen\";\n" "\"job-state.8\" = \"Abgebrochen\";\n" "\"job-state.9\" = \"Abgeschlossen\";\n" "\"joining\" = \"Fügen Sie\";\n" "\"media\" = \"Medien\";\n" "\"media-col\" = \"Medien\";\n" "\"media-size\" = \"Mediengröße\";\n" "\"media-size-name\" = \"Mediengröße\";\n" "\"media-source\" = \"Eingabeschacht\";\n" "\"media-source.alternate\" = \"Alternativer Ausgabeschacht\";\n" "\"media-source.alternate-roll\" = \"Rollenwechsel\";\n" "\"media-source.auto\" = \"Automatisch\";\n" "\"media-source.bottom\" = \"Unten\";\n" "\"media-source.by-pass-tray\" = \"Mehrzweck-Zuführung\";\n" "\"media-source.center\" = \"Mitte\";\n" "\"media-source.disc\" = \"Scheiben\";\n" "\"media-source.envelope\" = \"Briefumschlag (Envelope)\";\n" "\"media-source.hagaki\" = \"Postkarte ('Hagaki')\";\n" "\"media-source.large-capacity\" = \"Große Kapazität\";\n" "\"media-source.left\" = \"Links\";\n" "\"media-source.main\" = \"Haupt\";\n" "\"media-source.main-roll\" = \"Hauptrolle\";\n" "\"media-source.manual\" = \"Handbuch\";\n" "\"media-source.middle\" = \"Mittel\";\n" "\"media-source.photo\" = \"Foto\";\n" "\"media-source.rear\" = \"Rückseitig\";\n" "\"media-source.right\" = \"Rechts\";\n" "\"media-source.roll-1\" = \"Rolle 1\";\n" "\"media-source.roll-10\" = \"Rolle 10\";\n" "\"media-source.roll-2\" = \"Rolle 2\";\n" "\"media-source.roll-3\" = \"Rolle 3\";\n" "\"media-source.roll-4\" = \"Rolle 4\";\n" "\"media-source.roll-5\" = \"Rolle 5\";\n" "\"media-source.roll-6\" = \"Rolle 6\";\n" "\"media-source.roll-7\" = \"Rolle 7\";\n" "\"media-source.roll-8\" = \"Rolle 8\";\n" "\"media-source.roll-9\" = \"Rolle 9\";\n" "\"media-source.side\" = \"Seite\";\n" "\"media-source.top\" = \"Oben\";\n" "\"media-source.tray-1\" = \"Schacht 1\";\n" "\"media-source.tray-10\" = \"Schacht 10\";\n" "\"media-source.tray-11\" = \"Schacht 11\";\n" "\"media-source.tray-12\" = \"Schacht 12\";\n" "\"media-source.tray-13\" = \"Schacht 13\";\n" "\"media-source.tray-14\" = \"Schacht 14\";\n" "\"media-source.tray-15\" = \"Schacht 15\";\n" "\"media-source.tray-16\" = \"Schacht 16\";\n" "\"media-source.tray-17\" = \"Schacht 17\";\n" "\"media-source.tray-18\" = \"Schacht 18\";\n" "\"media-source.tray-19\" = \"Schacht 19\";\n" "\"media-source.tray-2\" = \"Schacht 2\";\n" "\"media-source.tray-20\" = \"Schacht 20\";\n" "\"media-source.tray-3\" = \"Schacht 3\";\n" "\"media-source.tray-4\" = \"Schacht 4\";\n" "\"media-source.tray-5\" = \"Schacht 5\";\n" "\"media-source.tray-6\" = \"Schacht 6\";\n" "\"media-source.tray-7\" = \"Schacht 7\";\n" "\"media-source.tray-8\" = \"Schacht 8\";\n" "\"media-source.tray-9\" = \"Schacht 9\";\n" "\"media-tracking\" = \"Medienverfolgung\";\n" "\"media-tracking.continuous\" = \"Kontinuierlich\";\n" "\"media-tracking.gap\" = \"Abstand\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Internet\";\n" "\"media-type\" = \"Medientyp\";\n" "\"media-type.aluminum\" = \"Aluminium\";\n" "\"media-type.auto\" = \"Automatisch\";\n" "\"media-type.back-print-film\" = \"Rückseitig bedruckte Folie\";\n" "\"media-type.cardboard\" = \"Pappe\";\n" "\"media-type.cardstock\" = \"Karten\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Kontinuierlich\";\n" "\"media-type.continuous-long\" = \"Kontinuierlich (lang)\";\n" "\"media-type.continuous-short\" = \"Kontinuierlich (kurz)\";\n" "\"media-type.corrugated-board\" = \"Wellpappe\";\n" "\"media-type.disc\" = \"Optischer Datenträger\";\n" "\"media-type.disc-glossy\" = \"Optischer Datenträger (glänzend)\";\n" "\"media-type.disc-high-gloss\" = \"Optischer Datenträger (hochglänzend)\";\n" "\"media-type.disc-matte\" = \"Optischer Datenträger (matt)\";\n" "\"media-type.disc-satin\" = \"Optischer Datenträger (satin)\";\n" "\"media-type.disc-semi-gloss\" = \"Optischer Datenträger (halbglänzend)\";\n" "\"media-type.double-wall\" = \"Doppelwand\";\n" "\"media-type.dry-film\" = \"Trockenfilm\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Prägefolie\";\n" "\"media-type.end-board\" = \"Endpunkt\";\n" "\"media-type.envelope\" = \"Umschlag\";\n" "\"media-type.envelope-archival\" = \"Archiv-Umschlag\";\n" "\"media-type.envelope-bond\" = \"Umschlag (Bond)\";\n" "\"media-type.envelope-coated\" = \"Umschlag (Beschichtet)\";\n" "\"media-type.envelope-cotton\" = \"Umschlag (Baumwolle)\";\n" "\"media-type.envelope-fine\" = \"Umschlag (Fein)\";\n" "\"media-type.envelope-heavyweight\" = \"Umschlag (schwer)\";\n" "\"media-type.envelope-inkjet\" = \"Umschlag (Tintenstrahldruck)\";\n" "\"media-type.envelope-lightweight\" = \"Umschlag (leicht)\";\n" "\"media-type.envelope-plain\" = \"Umschlag (unbedruckt)\";\n" "\"media-type.envelope-preprinted\" = \"Umschlag (bedruckt)\";\n" "\"media-type.envelope-window\" = \"Umschlag (mit Sichtfenster)\";\n" "\"media-type.fabric\" = \"Gewebe\";\n" "\"media-type.fabric-archival\" = \"Gewebe (Archivierung)\";\n" "\"media-type.fabric-glossy\" = \"Stoff (glänzend)\";\n" "\"media-type.fabric-high-gloss\" = \"Stoff (hochglänzend)\";\n" "\"media-type.fabric-matte\" = \"Stoff (matt)\";\n" "\"media-type.fabric-semi-gloss\" = \"Gewebe (halbglänzend)\";\n" "\"media-type.fabric-waterproof\" = \"Gewebe (wasserfest)\";\n" "\"media-type.film\" = \"Film-Medium\";\n" "\"media-type.flexo-base\" = \"Flexo-Basis\";\n" "\"media-type.flexo-photo-polymer\" = \"Flexo-Fotopolymer\";\n" "\"media-type.flute\" = \"Fluten\";\n" "\"media-type.foil\" = \"Folie\";\n" "\"media-type.full-cut-tabs\" = \"Vollschnitt Tabs\";\n" "\"media-type.glass\" = \"Glas\";\n" "\"media-type.glass-colored\" = \"Glas (gefärbt)\";\n" "\"media-type.glass-opaque\" = \"Glas (undurchsichtig)\";\n" "\"media-type.glass-surfaced\" = \"Glas (beschichtet)\";\n" "\"media-type.glass-textured\" = \"Glas (strukturiert)\";\n" "\"media-type.gravure-cylinder\" = \"Gravurzylinder\";\n" "\"media-type.image-setter-paper\" = \"Belichterpapier\";\n" "\"media-type.imaging-cylinder\" = \"Imaging-Zylinder\";\n" "\"media-type.labels\" = \"Etiketten\";\n" "\"media-type.labels-colored\" = \"Farbige Etiketten\";\n" "\"media-type.labels-glossy\" = \"Glossy Etiketten\";\n" "\"media-type.labels-high-gloss\" = \"Hochglänzende Etiketten\";\n" "\"media-type.labels-inkjet\" = \"Inkjet Etiketten\";\n" "\"media-type.labels-matte\" = \"Matte Etiketten\";\n" "\"media-type.labels-permanent\" = \"Permanente Etiketten\";\n" "\"media-type.labels-satin\" = \"Satin Etiketten\";\n" "\"media-type.labels-security\" = \"Sicherheitsetiketten\";\n" "\"media-type.labels-semi-gloss\" = \"Halbglänzende Etiketten\";\n" "\"media-type.laminating-foil\" = \"Laminierfolie\";\n" "\"media-type.letterhead\" = \"Briefkopf (vorbedruckt)\";\n" "\"media-type.metal\" = \"Metall\";\n" "\"media-type.metal-glossy\" = \"Metall glänzend\";\n" "\"media-type.metal-high-gloss\" = \"Metall Hochglanz\";\n" "\"media-type.metal-matte\" = \"Metall matt\";\n" "\"media-type.metal-satin\" = \"Metall satiniert\";\n" "\"media-type.metal-semi-gloss\" = \"Metall Halbglanz\";\n" "\"media-type.mounting-tape\" = \"Montageband\";\n" "\"media-type.multi-layer\" = \"Mehrere Lagen\";\n" "\"media-type.multi-part-form\" = \"Mehrteilige Form\";\n" "\"media-type.other\" = \"Sonstige\";\n" "\"media-type.paper\" = \"Papier\";\n" "\"media-type.photographic\" = \"Fotopapier\";\n" "\"media-type.photographic-archival\" = \"Fotografische Archivierung\";\n" "\"media-type.photographic-film\" = \"Fotofilm\";\n" "\"media-type.photographic-glossy\" = \"Glossy Fotopapier\";\n" "\"media-type.photographic-high-gloss\" = \"Hochglanz-Fotopapier\";\n" "\"media-type.photographic-matte\" = \"Mattes Fotopapier\";\n" "\"media-type.photographic-satin\" = \"Satin Fotopapier\";\n" "\"media-type.photographic-semi-gloss\" = \"Halbglänzendes Fotopapier\";\n" "\"media-type.plastic\" = \"Kunststoff\";\n" "\"media-type.plastic-archival\" = \"Kunststoff (Archivierung)\";\n" "\"media-type.plastic-colored\" = \"Kunststoff gefärbt\";\n" "\"media-type.plastic-glossy\" = \"Kunststoff glänzend\";\n" "\"media-type.plastic-high-gloss\" = \"Kunststoff Hochglanz\";\n" "\"media-type.plastic-matte\" = \"Kunststoff matt\";\n" "\"media-type.plastic-satin\" = \"Kunststoff satiniert\";\n" "\"media-type.plastic-semi-gloss\" = \"Kunststoff Halbglanz\";\n" "\"media-type.plate\" = \"Druckplatte\";\n" "\"media-type.polyester\" = \"Polyestermaterial\";\n" "\"media-type.pre-cut-tabs\" = \"Vorgeschnittene Tabs\";\n" "\"media-type.roll\" = \"Rollen\";\n" "\"media-type.screen\" = \"Bildschirm\";\n" "\"media-type.screen-paged\" = \"Bildschirm (paginiert)\";\n" "\"media-type.self-adhesive\" = \"Selbstklebend\";\n" "\"media-type.self-adhesive-film\" = \"Selbstklebende Folie\";\n" "\"media-type.shrink-foil\" = \"Schrumpffolie\";\n" "\"media-type.single-face\" = \"Einzelfläche\";\n" "\"media-type.single-wall\" = \"Einzelwand\";\n" "\"media-type.sleeve\" = \"Hülse (Sleeve)\";\n" "\"media-type.stationery\" = \"Schreibpapier\";\n" "\"media-type.stationery-archival\" = \"Schreibpapier (für Archivierung)\";\n" "\"media-type.stationery-coated\" = \"beschichtetes Papier\";\n" "\"media-type.stationery-cotton\" = \"Schreibpapier (aus Baumwolle)\";\n" "\"media-type.stationery-fine\" = \"Pergament\";\n" "\"media-type.stationery-heavyweight\" = \"Schweres Papier\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Schreibpapier (schwer, beschichtet)\";\n" "\"media-type.stationery-inkjet\" = \"Inkjet-Papiere für Schreibwaren\";\n" "\"media-type.stationery-letterhead\" = \"Briefkopf (vorbedruckt)\";\n" "\"media-type.stationery-lightweight\" = \"Leichtes Papier\";\n" "\"media-type.stationery-preprinted\" = \"Papier (vorbedruckt)\";\n" "\"media-type.stationery-prepunched\" = \"Papier (gelocht)\";\n" "\"media-type.tab-stock\" = \"Auf Lager\";\n" "\"media-type.tractor\" = \"Traktor\";\n" "\"media-type.transfer\" = \"Transfermedium\";\n" "\"media-type.transparency\" = \"Transparentes Medium\";\n" "\"media-type.triple-wall\" = \"Triple Wand\";\n" "\"media-type.wet-film\" = \"Nassfilm\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 oder US-Brief\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Umschlag\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Entwicklung\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Umschlag\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Umschlag\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Umschlag\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Umschlag\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Umschlag\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Umschlag\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Umschlag\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Umschlag\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Umschlag\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Umschlag\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Umschlag\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Umschlag\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Umschlag\";\n" "\"media.iso_dl_110x220mm\" = \"DL Umschlag\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Exekutive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Umbau Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Umschlag Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Umschlag Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Umbau Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Postkarte (Hagaki)\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Umschlag (Kahu)\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Umschlag Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Antwortpostkarte (Oufuku Reply Postcard)\";\n" "\"media.jpn_you4_105x235mm\" = \"Envelope Sie 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Umbau A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Umbau C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Exekutive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"Endlospapier (EU)\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"Endlospapier (US)\";\n" "\"media.na_foolscap_8.5x13in\" = \"Kanzleipapier (Foolscap)\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Rechnung\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"US 'Letter' Format (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"US 'Letter' Format (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"US 'Letter' Format\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Monarch Briefumschlag\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Briefumschlag #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Briefumschlag #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Briefumschlag #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Briefumschlag #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Briefumschlag #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Persönlicher Umschlag\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Amerikanisches Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Fohlen\";\n" "\"media.om_folio_210x330mm\" = \"Folioformat (Spezial)\";\n" "\"media.om_invite_220x220mm\" = \"Envelope Einladung\";\n" "\"media.om_italian_110x230mm\" = \"Briefumschlag Italienisch\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389m m\";\n" "\"media.om_postfix_114x229mm\" = \"Postfix umwandeln\";\n" "\"media.prc_10_324x458mm\" = \"Briefumschlag chinesisch #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chinesisch 16k\";\n" "\"media.prc_1_102x165mm\" = \"Briefumschlag chinesisch #1\";\n" "\"media.prc_2_102x176mm\" = \"Briefumschlag chinesisch #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chinesisch 32k\";\n" "\"media.prc_3_125x176mm\" = \"Briefumschlag chinesisch #3\";\n" "\"media.prc_4_110x208mm\" = \"Briefumschlag chinesisch #4\";\n" "\"media.prc_5_110x220mm\" = \"Briefumschlag chinesisch #5\";\n" "\"media.prc_6_120x320mm\" = \"Briefumschlag chinesisch #6\";\n" "\"media.prc_7_160x230mm\" = \"Briefumschlag chinesisch #7\";\n" "\"media.prc_8_120x309mm\" = \"Briefumschlag chinesisch #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC/Kai 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROG 8k\";\n" "\"not configured\" = \"nicht konfiguriert\";\n" "\"not visible\" = \"nicht sichtbar\";\n" "\"off\" = \"Aus\";\n" "\"on\" = \"An\";\n" "\"orientation-requested\" = \"Orientierung\";\n" "\"orientation-requested.3\" = \"Hochformat (Portrait)\";\n" "\"orientation-requested.4\" = \"Querformat (Landscape)\";\n" "\"orientation-requested.5\" = \"Querformat (gespiegelt)\";\n" "\"orientation-requested.6\" = \"Hochformat (gespiegelt)\";\n" "\"orientation-requested.7\" = \"Keine\";\n" "\"output-bin\" = \"Ausgabeschacht\";\n" "\"output-bin.auto\" = \"Automatisch\";\n" "\"output-bin.bottom\" = \"Unten\";\n" "\"output-bin.center\" = \"Mitte\";\n" "\"output-bin.face-down\" = \"Druckseite nach unten\";\n" "\"output-bin.face-up\" = \"Druckseite nach oben\";\n" "\"output-bin.large-capacity\" = \"Große Kapazität\";\n" "\"output-bin.left\" = \"Links\";\n" "\"output-bin.mailbox-1\" = \"Postfach 1\";\n" "\"output-bin.mailbox-10\" = \"Postfach 10\";\n" "\"output-bin.mailbox-2\" = \"Postfach 2\";\n" "\"output-bin.mailbox-3\" = \"Postfach 3\";\n" "\"output-bin.mailbox-4\" = \"Postfach 4\";\n" "\"output-bin.mailbox-5\" = \"Postfach 5\";\n" "\"output-bin.mailbox-6\" = \"Postfach 6\";\n" "\"output-bin.mailbox-7\" = \"Postfach 7\";\n" "\"output-bin.mailbox-8\" = \"Postfach 8\";\n" "\"output-bin.mailbox-9\" = \"Postfach 9\";\n" "\"output-bin.middle\" = \"Mitte\";\n" "\"output-bin.my-mailbox\" = \"Mein Postfach\";\n" "\"output-bin.rear\" = \"Rückseitig\";\n" "\"output-bin.right\" = \"Rechts\";\n" "\"output-bin.side\" = \"Seitlich\";\n" "\"output-bin.stacker-1\" = \"Stapler 1\";\n" "\"output-bin.stacker-10\" = \"Stapler 10\";\n" "\"output-bin.stacker-2\" = \"Stapler 2\";\n" "\"output-bin.stacker-3\" = \"Stapler 3\";\n" "\"output-bin.stacker-4\" = \"Stapler 4\";\n" "\"output-bin.stacker-5\" = \"Stapler 5\";\n" "\"output-bin.stacker-6\" = \"Stapler 6\";\n" "\"output-bin.stacker-7\" = \"Stapler 7\";\n" "\"output-bin.stacker-8\" = \"Stapler 8\";\n" "\"output-bin.stacker-9\" = \"Stapler 9\";\n" "\"output-bin.top\" = \"Oben\";\n" "\"output-bin.tray-1\" = \"Ausgabeschacht 1\";\n" "\"output-bin.tray-10\" = \"Ausgabeschacht 10\";\n" "\"output-bin.tray-2\" = \"Ausgabeschacht 2\";\n" "\"output-bin.tray-3\" = \"Ausgabeschacht 3\";\n" "\"output-bin.tray-4\" = \"Ausgabeschacht 4\";\n" "\"output-bin.tray-5\" = \"Ausgabeschacht 5\";\n" "\"output-bin.tray-6\" = \"Ausgabeschacht 6\";\n" "\"output-bin.tray-7\" = \"Ausgabeschacht 7\";\n" "\"output-bin.tray-8\" = \"Ausgabeschacht 8\";\n" "\"output-bin.tray-9\" = \"Ausgabeschacht 9\";\n" "\"print-color-mode\" = \"Druckmodus\";\n" "\"print-color-mode.auto\" = \"Automatisch\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monochrom\";\n" "\"print-color-mode.bi-level\" = \"Text\";\n" "\"print-color-mode.color\" = \"Farbe\";\n" "\"print-color-mode.highlight\" = \"Hervorhebung\";\n" "\"print-color-mode.monochrome\" = \"Monochrom\";\n" "\"print-color-mode.process-bi-level\" = \"Verfahren Text\";\n" "\"print-color-mode.process-monochrome\" = \"Verfahren monochrom\";\n" "\"print-content-optimize\" = \"Optimieren für\";\n" "\"print-content-optimize.auto\" = \"Automatisch\";\n" "\"print-content-optimize.graphic\" = \"Grafik\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Text\";\n" "\"print-content-optimize.text-and-graphic\" = \"Text und Grafik\";\n" "\"print-darkness\" = \"Drucksättigung\";\n" "\"print-quality\" = \"Druckqualität\";\n" "\"print-quality.3\" = \"Entwurf\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Beste\";\n" "\"print-scaling\" = \"Skalierung\";\n" "\"print-scaling.auto\" = \"Automatisch\";\n" "\"print-scaling.auto-fit\" = \"Automatisch einpassen\";\n" "\"print-scaling.fill\" = \"Füllung\";\n" "\"print-scaling.fit\" = \"Einpassen\";\n" "\"print-scaling.none\" = \"Keine\";\n" "\"print-speed\" = \"Druckgeschwindigkeit\";\n" "\"printer-resolution\" = \"Druckauflösung\";\n" "\"printer-state-reasons.cover-open\" = \"Abdeckung offen.\";\n" "\"printer-state-reasons.door-open\" = \"Tür offen.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Drucker identifizieren.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Papierzuführung fehlt.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Tintentank leer.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Tintenstand niedrig.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Abfallbehälter fast voll.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Abfallbehälter voll.\";\n" "\"printer-state-reasons.media-empty\" = \"Papierzuführung leer.\";\n" "\"printer-state-reasons.media-jam\" = \"Papierstau.\";\n" "\"printer-state-reasons.media-low\" = \"Füllen Sie bald Papier nach.\";\n" "\"printer-state-reasons.media-needed\" = \"Papier laden.\";\n" "\"printer-state-reasons.none\" = \"Fertig.\";\n" "\"printer-state-reasons.offline\" = \"Offline.\";\n" "\"printer-state-reasons.other\" = \"Siehe Drucker.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Drucker beschäftigt.\";\n" "\"printer-state-reasons.toner-empty\" = \"Tonerbehälter leer.\";\n" "\"printer-state-reasons.toner-low\" = \"Tonerstand niedrig.\";\n" "\"printer-state.3\" = \"Leerlauf\";\n" "\"printer-state.4\" = \"Verarbeitung\";\n" "\"printer-state.5\" = \"Gestoppt\";\n" "\"sides\" = \"Doppelseitiger Druck\";\n" "\"sides.one-sided\" = \"Aus\";\n" "\"sides.two-sided-long-edge\" = \"An (Hochformat)\";\n" "\"sides.two-sided-short-edge\" = \"An (Querformat)\";\n" "\"unable to join\" = \"Zusammenfügen fehlgeschlagen\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Åland (Inselgruppe)\";\n"; pappl-1.4.9/pappl/strings/en.strings000066400000000000000000001325201476704353100175000ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Cancel all jobs (cancel)."; " -c COPIES" = " -c COPIES"; " -d PRINTER Specify printer." = " -d PRINTER Specify printer."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Specify job ID (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Specify driver (add/modify)."; " -n COPIES Specify number of copies (submit)." = " -n COPIES Specify number of copies (submit)."; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Specify option (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 to 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 to 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE'"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZATION'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Specify ipp: or ipps: printer/server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Specify socket: or usb: device (add/modify)."; " add PRINTER Add a printer." = " add PRINTER Add a printer."; " autoadd Automatically add supported printers." = " autoadd Automatically add supported printers."; " cancel Cancel one or more jobs." = " cancel Cancel one or more jobs."; " default Set the default printer." = " default Set the default printer."; " delete Delete a printer." = " delete Delete a printer."; " devices List devices." = " devices List devices."; " drivers List drivers." = " drivers List drivers."; " jobs List jobs." = " jobs List jobs."; " modify Modify a printer." = " modify Modify a printer."; " options List printer options." = " options List printer options."; " pause Pause printing for a printer." = " pause Pause printing for a printer."; " printers List printers." = " printers List printers."; " resume Resume printing for a printer." = " resume Resume printing for a printer."; " server Run a server." = " server Run a server."; " shutdown Shutdown a running server." = " shutdown Shutdown a running server."; " status Show server/printer/job status." = " status Show server/printer/job status."; " submit Submit a file for printing." = " submit Submit a file for printing."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d inches/sec"; "%d job" = "%d job"; /* Media size in millimeters */ "%d x %dmm" = "%d x %dmm"; "%ddpi" = "%ddpi"; "%dx%ddpi" = "%dx%ddpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) from %s"; /* Source/Tray Media */ "%s Media" = "%s Media"; "%s: Bad 'server-port' value." = "%s: Bad 'server-port' value."; "%s: Bad job ID." = "%s: Bad job ID."; "%s: Bad printer URI '%s'." = "%s: Bad printer URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Cannot specify more than one sub-command."; "%s: Empty print file received on the standard input." = "%s: Empty print file received on the standard input."; "%s: Failed to create a system." = "%s: Failed to create a system."; "%s: Missing '-d PRINTER'." = "%s: Missing '-d PRINTER'."; "%s: Missing '-m DRIVER-NAME'." = "%s: Missing '-m DRIVER-NAME'."; "%s: Missing '-v DEVICE-URI'." = "%s: Missing '-v DEVICE-URI'."; "%s: Missing copy count after '-n'." = "%s: Missing copy count after '-n'."; "%s: Missing device URI after '-v'." = "%s: Missing device URI after '-v'."; "%s: Missing driver name after '-m'." = "%s: Missing driver name after '-m'."; "%s: Missing filename after '--'." = "%s: Missing filename after '--'."; "%s: Missing hostname after '-h'." = "%s: Missing hostname after '-h'."; "%s: Missing job ID after '-j'." = "%s: Missing job ID after '-j'."; "%s: Missing option(s) after '-o'." = "%s: Missing option(s) after '-o'."; "%s: Missing printer URI after '-u'." = "%s: Missing printer URI after '-u'."; "%s: Missing printer name after '-d'." = "%s: Missing printer name after '-d'."; "%s: Missing space after '-o'." = "%s: Missing space after '-o'."; "%s: Missing title after '-t'." = "%s: Missing title after '-t'."; "%s: No default printer available." = "%s: No default printer available."; "%s: No files to print." = "%s: No files to print."; "%s: Server is not running." = "%s: Server is not running."; "%s: Sub-command '%s' does not accept files." = "%s: Sub-command '%s' does not accept files."; "%s: Sub-command 'autoadd' is not supported." = "%s: Sub-command 'autoadd' is not supported."; "%s: Too many files." = "%s: Too many files."; "%s: Unable to access '%s': %s" = "%s: Unable to access '%s': %s"; "%s: Unable to add printer: %s" = "%s: Unable to add printer: %s"; "%s: Unable to cancel job: %s" = "%s: Unable to cancel job: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Unable to connect to printer at '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Unable to connect to server: %s"; "%s: Unable to create temporary file: %s" = "%s: Unable to create temporary file: %s"; "%s: Unable to delete printer: %s" = "%s: Unable to delete printer: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Unable to get information for '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Unable to get information for printer: %s"; "%s: Unable to get printer options: %s" = "%s: Unable to get printer options: %s"; "%s: Unable to modify printer: %s" = "%s: Unable to modify printer: %s"; "%s: Unable to pause printer: %s" = "%s: Unable to pause printer: %s"; "%s: Unable to print '%s': %s" = "%s: Unable to print '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Unable to resume printer: %s"; "%s: Unable to set default printer: %s" = "%s: Unable to set default printer: %s"; "%s: Unable to shutdown server: %s" = "%s: Unable to shutdown server: %s"; "%s: Unable to start server: %s" = "%s: Unable to start server: %s"; "%s: Unable to write to temporary file: %s" = "%s: Unable to write to temporary file: %s"; "%s: Unknown option '%s'." = "%s: Unknown option '%s'."; "%s: Unknown option '-%c'." = "%s: Unknown option '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Unknown sub-command '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Unsupported URI scheme '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Warning - user credentials are not supported in URIs."; ", Borderless" = ", Borderless"; "A printer with that name already exists." = "A printer with that name already exists."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Add Printer"; "Admin Group" = "Admin Group"; "Afghanistan" = "Afghanistan"; "Albania" = "Albania"; "Algeria" = "Algeria"; "American Samoa" = "American Samoa"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarctica"; "Antigua and Barbuda" = "Antigua and Barbuda"; "Argentina" = "Argentina"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Auto"; "Auto-Detect Driver" = "Auto-Detect Driver"; "Azerbaijan" = "Azerbaijan"; "Bad administration group." = "Bad administration group."; "Bad port number." = "Bad port number."; "Bad print group." = "Bad print group."; "Bad printer defaults." = "Bad printer defaults."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrain"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbados"; "Belarus" = "Belarus"; "Belgium" = "Belgium"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivia (Plurinational State of)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius and Saba"; "Borderless" = "Borderless"; "Bosnia and Herzegovina" = "Bosnia and Herzegovina"; "Botswana" = "Botswana"; "Bouvet Island" = "Bouvet Island"; "Brazil" = "Brazil"; "British Indian Ocean Territory" = "British Indian Ocean Territory"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bulgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Cambodia"; "Cameroon" = "Cameroon"; "Canada" = "Canada"; "Cancel All Jobs" = "Cancel All Jobs"; "Cancel Job" = "Cancel Job"; "Canceled %s" = "Canceled %s"; "Canceling" = "Canceling"; "Cayman Islands" = "Cayman Islands"; "Central African Republic" = "Central African Republic"; "Certificate created." = "Certificate created."; "Certificate installed." = "Certificate installed."; "Certificate request created." = "Certificate request created."; "Chad" = "Chad"; "Change Access Password" = "Change Access Password"; "Change Log Level" = "Change Log Level"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Change Wi-Fi Network"; "Changes Saved." = "Changes Saved."; "Changes saved." = "Changes saved."; "Chile" = "Chile"; "China" = "China"; "Christmas Island" = "Christmas Island"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Cocos (Keeling) Islands"; "Colombia" = "Colombia"; "Comoros" = "Comoros"; "Completed %s" = "Completed %s"; "Configuration" = "Configuration"; "Configure Media" = "Configure Media"; "Confirm Cancel All" = "Confirm Cancel All"; "Confirm Delete Printer" = "Confirm Delete Printer"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, Democratic Republic of the"; "Contact" = "Contact"; "Cook Islands" = "Cook Islands"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Create Certificate Signing Request"; "Create New Certificate" = "Create New Certificate"; "Create New TLS Certificate" = "Create New TLS Certificate"; "Create TLS Certificate Request" = "Create TLS Certificate Request"; "Croatia" = "Croatia"; "Cuba" = "Cuba"; "Curaçao" = "Curaçao"; "Current Password" = "Current Password"; "Custom Size" = "Custom Size"; "Cyprus" = "Cyprus"; "Czechia" = "Czechia"; "Côte d'Ivoire" = "Côte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SD Service Name"; "Debugging" = "Debugging"; "Default printer set." = "Default printer set."; "Delete" = "Delete"; "Delete Printer" = "Delete Printer"; "Denmark" = "Denmark"; "Djibouti" = "Djibouti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominica"; "Dominican Republic" = "Dominican Republic"; "Download Certificate Request File" = "Download Certificate Request File"; "Ecuador" = "Ecuador"; "Egypt" = "Egypt"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Equatorial Guinea"; "Eritrea" = "Eritrea"; "Errors" = "Errors"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Ethiopia"; "Falkland Islands (Malvinas)" = "Falkland Islands (Malvinas)"; "Faroe Islands" = "Faroe Islands"; "Fatal Errors/Conditions" = "Fatal Errors/Conditions"; "Fiji" = "Fiji"; "Finland" = "Finland"; "France" = "France"; "French Guiana" = "French Guiana"; "French Polynesia" = "French Polynesia"; "French Southern Territories" = "French Southern Territories"; "Gabon" = "Gabon"; "Gambia" = "Gambia"; "Georgia" = "Georgia"; "Germany" = "Germany"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Greece"; "Greenland" = "Greenland"; "Grenada" = "Grenada"; "Group changes saved." = "Group changes saved."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Island and McDonald Islands"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Holy See"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Hostname"; "Human-Readable Location" = "Human-Readable Location"; "Hungary" = "Hungary"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Iceland"; "Identify Printer" = "Identify Printer"; "India" = "India"; "Indonesia" = "Indonesia"; "Informational" = "Informational"; "Install TLS Certificate" = "Install TLS Certificate"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Invalid Job ID."; "Invalid certificate or private key." = "Invalid certificate or private key."; "Invalid form data." = "Invalid form data."; "Invalid form submission." = "Invalid form submission."; "Invalid job ID." = "Invalid job ID."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (Islamic Republic of)"; "Iraq" = "Iraq"; "Ireland" = "Ireland"; "Isle of Man" = "Isle of Man"; "Israel" = "Israel"; "Italy" = "Italy"; "Jamaica" = "Jamaica"; "Japan" = "Japan"; "Jersey" = "Jersey"; "Job #" = "Job #"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Jobs"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Jordan"; "Kazakhstan" = "Kazakhstan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Korea (Democratic People's Republic of)"; "Korea, Republic of" = "Korea, Republic of"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kyrgyzstan"; "Landscape" = "Landscape"; "Lao People's Democratic Republic" = "Lao People's Democratic Republic"; "Latvia" = "Latvia"; "Lebanon" = "Lebanon"; "Lesotho" = "Lesotho"; "Level" = "Level"; "Liberia" = "Liberia"; "Libya" = "Libya"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lithuania"; "Location" = "Location"; "Log Level" = "Log Level"; "Logging" = "Logging"; "Logs" = "Logs"; "Luxembourg" = "Luxembourg"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malaysia"; "Maldives" = "Maldives"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Marshall Islands"; "Martinique" = "Martinique"; "Mauritania" = "Mauritania"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Media"; "Mexico" = "Mexico"; "Micronesia (Federated States of)" = "Micronesia (Federated States of)"; "Missing action." = "Missing action."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "Missing private key."; "Moldova, Republic of" = "Moldova, Republic of"; "Monaco" = "Monaco"; "Mongolia" = "Mongolia"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Morocco"; "Mozambique" = "Mozambique"; "Myanmar" = "Myanmar"; "Name" = "Name"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Netherlands"; "Network" = "Network"; "Network Printer" = "Network Printer"; "Networking" = "Networking"; "New Caledonia" = "New Caledonia"; "New Zealand" = "New Zealand"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "No default printer set."; "No jobs in history." = "No jobs in history."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "North Macedonia"; "Northern Mariana Islands" = "Northern Mariana Islands"; "Norway" = "Norway"; "Not set" = "Not set"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Options:"; "Organization" = "Organization"; "Organization Name" = "Organization Name"; "Other Settings" = "Other Settings"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palestine, State of"; "Panama" = "Panama"; "Papua New Guinea" = "Papua New Guinea"; "Paraguay" = "Paraguay"; "Password" = "Password"; "Password changed." = "Password changed."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit."; "Passwords do not match." = "Passwords do not match."; "Pause Printing" = "Pause Printing"; "Peru" = "Peru"; "Philippines" = "Philippines"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Please enter a hostname or IP address for the printer."; "Please enter a printer name." = "Please enter a printer name."; "Please select a device." = "Please select a device."; "Please select a driver." = "Please select a driver."; "Please select a valid log level." = "Please select a valid log level."; "Poland" = "Poland"; "Portrait" = "Portrait"; "Portugal" = "Portugal"; "Primary DNS" = "Primary DNS"; "Print Group" = "Print Group"; "Print Test Page" = "Print Test Page"; "Print job options:" = "Print job options:"; "Printer identified." = "Printer identified."; "Printer is currently active." = "Printer is currently active."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Printer names must start with a letter or underscore and cannot contain special characters."; "Printer options:" = "Printer options:"; "Printer paused." = "Printer paused."; "Printer pausing." = "Printer pausing."; "Printer resuming." = "Printer resuming."; "Printers" = "Printers"; "Printing Defaults" = "Printing Defaults"; "Puerto Rico" = "Puerto Rico"; "Qatar" = "Qatar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Reprint Job"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Resume Printing"; "Reverse Landscape" = "Reverse Landscape"; "Reverse Portrait" = "Reverse Portrait"; "Romania" = "Romania"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Running, %s since %s%s."; "Russian Federation" = "Russian Federation"; "Rwanda" = "Rwanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Saint Helena, Ascension and Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts and Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (French part)"; "Saint Pierre and Miquelon" = "Saint Pierre and Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent and the Grenadines"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome and Principe"; "Saudi Arabia" = "Saudi Arabia"; "Save Changes" = "Save Changes"; "Secondary DNS" = "Secondary DNS"; "Security" = "Security"; "Select Driver" = "Select Driver"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "Server is not running."; "Set Access Password" = "Set Access Password"; "Set as Default" = "Set as Default"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapore"; "Sint Maarten (Dutch part)" = "Sint Maarten (Dutch part)"; "Slovakia" = "Slovakia"; "Slovenia" = "Slovenia"; "Solomon Islands" = "Solomon Islands"; "Somalia" = "Somalia"; "South Africa" = "South Africa"; "South Georgia and the South Sandwich Islands" = "South Georgia and the South Sandwich Islands"; "South Sudan" = "South Sudan"; "Spain" = "Spain"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "Status"; "Sub-commands:" = "Sub-commands:"; "Sudan" = "Sudan"; "Supplies" = "Supplies"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard and Jan Mayen"; "Sweden" = "Sweden"; "Switzerland" = "Switzerland"; "Syrian Arab Republic" = "Syrian Arab Republic"; "Taiwan, Province of China" = "Taiwan, Province of China"; "Tajikistan" = "Tajikistan"; "Tanzania, United Republic of" = "Tanzania, United Republic of"; "Test page printed." = "Test page printed."; "Thailand" = "Thailand"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad and Tobago"; "Tunisia" = "Tunisia"; "Turkey" = "Turkey"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Turks and Caicos Islands"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukraine"; "Unable to access test print file." = "Unable to access test print file."; "Unable to copy print job." = "Unable to copy print job."; "Unable to create certificate request." = "Unable to create certificate request."; "Unable to create certificate." = "Unable to create certificate."; "Unable to create test print job." = "Unable to create test print job."; "Unable to identify printer." = "Unable to identify printer."; "Unable to lookup address." = "Unable to lookup address."; "Unable to use that driver." = "Unable to use that driver."; "United Arab Emirates" = "United Arab Emirates"; "United Kingdom" = "United Kingdom"; "United Kingdom of Great Britain and Northern Ireland" = "United Kingdom of Great Britain and Northern Ireland"; "United States Minor Outlying Islands" = "United States Minor Outlying Islands"; "United States of America" = "United States of America"; "Unknown" = "Unknown"; "Unknown action." = "Unknown action."; "Unknown form action." = "Unknown form action."; "Unknown form request." = "Unknown form request."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Use My Position"; "Users" = "Users"; "Uzbekistan" = "Uzbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (Bolivarian Republic of)"; "Version %s" = "Version %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "View Logs"; "Virgin Islands (British)" = "Virgin Islands (British)"; "Virgin Islands (U.S.)" = "Virgin Islands (U.S.)"; "Wallis and Futuna" = "Wallis and Futuna"; "Warning" = "Warning"; "Western Sahara" = "Western Sahara"; "Wi-Fi Configuration" = "Wi-Fi Configuration"; "Wi-Fi Network" = "Wi-Fi Network"; "Width" = "Width"; "Wrong old password." = "Wrong old password."; "Yemen" = "Yemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Number of Copies"; "default printer" = "default printer"; "finishings" = "Finisher"; "finishings.10" = "Fold"; "finishings.100" = "Z fold"; "finishings.101" = "Engineering Z fold"; "finishings.11" = "Cut"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Staple top left"; "finishings.21" = "Staple bottom left"; "finishings.22" = "Staple top right"; "finishings.23" = "Staple bottom right"; "finishings.24" = "Edge stitch left"; "finishings.25" = "Edge stitch top"; "finishings.26" = "Edge stitch right"; "finishings.27" = "Edge stitch bottom"; "finishings.28" = "2 staples on left"; "finishings.29" = "2 staples on top"; "finishings.3" = "None"; "finishings.30" = "2 staples on right"; "finishings.31" = "2 staples on bottom"; "finishings.32" = "3 staples on left"; "finishings.33" = "3 staples on top"; "finishings.34" = "3 staples on right"; "finishings.35" = "3 staples on bottom"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind left"; "finishings.51" = "Bind top"; "finishings.52" = "Bind right"; "finishings.53" = "Bind bottom"; "finishings.6" = "Cover"; "finishings.60" = "Cut after every page"; "finishings.61" = "Cut after every document"; "finishings.62" = "Cut after every set"; "finishings.63" = "Cut after job"; "finishings.7" = "Bind"; "finishings.70" = "Punch top left"; "finishings.71" = "Punch bottom left"; "finishings.72" = "Punch top right"; "finishings.73" = "Punch bottom right"; "finishings.74" = "2-hole punch left"; "finishings.75" = "2-hole punch top"; "finishings.76" = "2-hole punch right"; "finishings.77" = "2-hole punch bottom"; "finishings.78" = "3-hole punch left"; "finishings.79" = "3-hole punch top"; "finishings.8" = "Saddle stitch"; "finishings.80" = "3-hole punch right"; "finishings.81" = "3-hole punch bottom"; "finishings.82" = "4-hole punch left"; "finishings.83" = "4-hole punch top"; "finishings.84" = "4-hole punch right"; "finishings.85" = "4-hole punch bottom"; "finishings.86" = "Multi-hole punch left"; "finishings.87" = "Multi-hole punch top"; "finishings.88" = "Multi-hole punch right"; "finishings.89" = "Multi-hole punch bottom"; "finishings.9" = "Edge stitch"; "finishings.90" = "Accordion fold"; "finishings.91" = "Double gate fold"; "finishings.92" = "Gate fold"; "finishings.93" = "Half fold"; "finishings.94" = "Half Z fold"; "finishings.95" = "Left gate fold"; "finishings.96" = "Letter fold"; "finishings.97" = "Parallel fold"; "finishings.98" = "Poster fold"; "finishings.99" = "Right gate fold"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Stopping."; "job-state-reasons.compression-error" = "Decompression error."; "job-state-reasons.document-format-error" = "Document format error."; "job-state-reasons.document-password-error" = "Document password error."; "job-state-reasons.document-permission-error" = "Document permission error."; "job-state-reasons.document-unprintable-error" = "Document unprintable error."; "job-state-reasons.errors-detected" = "Errors detected."; "job-state-reasons.job-canceled-at-device" = "Canceled at printer."; "job-state-reasons.job-canceled-by-user" = "Canceled by user."; "job-state-reasons.job-completed-successfully" = "Printed."; "job-state-reasons.job-completed-with-errors" = "Printed with errors."; "job-state-reasons.job-completed-with-warnings" = "Printed with warnings."; "job-state-reasons.job-data-insufficient" = "Insufficient data."; "job-state-reasons.job-fetchable" = "Fetchable."; "job-state-reasons.job-incoming" = "Incoming."; "job-state-reasons.job-printing" = "Printing."; "job-state-reasons.job-queued" = "Preparing to print."; "job-state-reasons.job-spooling" = "Spooling."; "job-state-reasons.none" = "Pending."; "job-state-reasons.printer-stopped" = "Printer offline."; "job-state-reasons.printer-stopped-partly" = "Printer partially stopped."; "job-state-reasons.processing-to-stop-point" = "Stopping."; "job-state-reasons.queued-in-device" = "Ready."; "job-state-reasons.warnings-detected" = "Warnings detected."; "job-state.3" = "Pending"; "job-state.4" = "Held"; "job-state.5" = "Processing"; "job-state.6" = "Stopped"; "job-state.7" = "Canceled"; "job-state.8" = "Aborted"; "job-state.9" = "Completed"; "joining" = "joining"; "media" = "Media"; "media-col" = "Media"; "media-size" = "Media Size"; "media-size-name" = "Media Size"; "media-source" = "Input Tray"; "media-source.alternate" = "Alternate"; "media-source.alternate-roll" = "Alternate roll"; "media-source.auto" = "Automatic"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Multipurpose tray"; "media-source.center" = "Center"; "media-source.disc" = "Disc"; "media-source.envelope" = "Envelope"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Large capacity"; "media-source.left" = "Left"; "media-source.main" = "Main"; "media-source.main-roll" = "Main roll"; "media-source.manual" = "Manual"; "media-source.middle" = "Middle"; "media-source.photo" = "Photo"; "media-source.rear" = "Rear"; "media-source.right" = "Right"; "media-source.roll-1" = "Roll 1"; "media-source.roll-10" = "Roll 10"; "media-source.roll-2" = "Roll 2"; "media-source.roll-3" = "Roll 3"; "media-source.roll-4" = "Roll 4"; "media-source.roll-5" = "Roll 5"; "media-source.roll-6" = "Roll 6"; "media-source.roll-7" = "Roll 7"; "media-source.roll-8" = "Roll 8"; "media-source.roll-9" = "Roll 9"; "media-source.side" = "Side"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Media Tracking"; "media-tracking.continuous" = "Continuous"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Media Type"; "media-type.aluminum" = "Aluminum"; "media-type.auto" = "Automatic"; "media-type.back-print-film" = "Back print film"; "media-type.cardboard" = "Cardboard"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuous"; "media-type.continuous-long" = "Continuous long"; "media-type.continuous-short" = "Continuous short"; "media-type.corrugated-board" = "Corrugated board"; "media-type.disc" = "Optical disc"; "media-type.disc-glossy" = "Glossy optical disc"; "media-type.disc-high-gloss" = "High gloss optical disc"; "media-type.disc-matte" = "Matte optical disc"; "media-type.disc-satin" = "Satin optical disc"; "media-type.disc-semi-gloss" = "Semi-gloss optical disc"; "media-type.double-wall" = "Double wall"; "media-type.dry-film" = "Dry film"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Embossing foil"; "media-type.end-board" = "End board"; "media-type.envelope" = "Envelope"; "media-type.envelope-archival" = "Archival envelope"; "media-type.envelope-bond" = "Bond envelope"; "media-type.envelope-coated" = "Coated envelope"; "media-type.envelope-cotton" = "Cotton envelope"; "media-type.envelope-fine" = "Fine envelope"; "media-type.envelope-heavyweight" = "Heavyweight envelope"; "media-type.envelope-inkjet" = "Inkjet envelope"; "media-type.envelope-lightweight" = "Lightweight envelope"; "media-type.envelope-plain" = "Plain envelope"; "media-type.envelope-preprinted" = "Preprinted envelope"; "media-type.envelope-window" = "Windowed envelope"; "media-type.fabric" = "Fabric"; "media-type.fabric-archival" = "Archival fabric"; "media-type.fabric-glossy" = "Glossy fabric"; "media-type.fabric-high-gloss" = "High gloss fabric"; "media-type.fabric-matte" = "Matte fabric"; "media-type.fabric-semi-gloss" = "Semi-gloss fabric"; "media-type.fabric-waterproof" = "Waterproof fabric"; "media-type.film" = "Film"; "media-type.flexo-base" = "Flexo base"; "media-type.flexo-photo-polymer" = "Flexo photo polymer"; "media-type.flute" = "Flute"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "Full cut tabs"; "media-type.glass" = "Glass"; "media-type.glass-colored" = "Glass colored"; "media-type.glass-opaque" = "Glass opaque"; "media-type.glass-surfaced" = "Glass surfaced"; "media-type.glass-textured" = "Glass textured"; "media-type.gravure-cylinder" = "Gravure cylinder"; "media-type.image-setter-paper" = "Image setter paper"; "media-type.imaging-cylinder" = "Imaging cylinder"; "media-type.labels" = "Labels"; "media-type.labels-colored" = "Colored labels"; "media-type.labels-glossy" = "Glossy labels"; "media-type.labels-high-gloss" = "High gloss labels"; "media-type.labels-inkjet" = "Inkjet labels"; "media-type.labels-matte" = "Matte labels"; "media-type.labels-permanent" = "Permanent labels"; "media-type.labels-satin" = "Satin labels"; "media-type.labels-security" = "Security labels"; "media-type.labels-semi-gloss" = "Semi-gloss labels"; "media-type.laminating-foil" = "Laminating foil"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal glossy"; "media-type.metal-high-gloss" = "Metal high gloss"; "media-type.metal-matte" = "Metal matte"; "media-type.metal-satin" = "Metal satin"; "media-type.metal-semi-gloss" = "Metal semi gloss"; "media-type.mounting-tape" = "Mounting tape"; "media-type.multi-layer" = "Multi layer"; "media-type.multi-part-form" = "Multi part form"; "media-type.other" = "Other"; "media-type.paper" = "Paper"; "media-type.photographic" = "Photo paper"; "media-type.photographic-archival" = "Photographic archival"; "media-type.photographic-film" = "Photo film"; "media-type.photographic-glossy" = "Glossy photo paper"; "media-type.photographic-high-gloss" = "High gloss photo paper"; "media-type.photographic-matte" = "Matte photo paper"; "media-type.photographic-satin" = "Satin photo paper"; "media-type.photographic-semi-gloss" = "Semi-gloss photo paper"; "media-type.plastic" = "Plastic"; "media-type.plastic-archival" = "Plastic archival"; "media-type.plastic-colored" = "Plastic colored"; "media-type.plastic-glossy" = "Plastic glossy"; "media-type.plastic-high-gloss" = "Plastic high gloss"; "media-type.plastic-matte" = "Plastic matte"; "media-type.plastic-satin" = "Plastic satin"; "media-type.plastic-semi-gloss" = "Plastic semi gloss"; "media-type.plate" = "Plate"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "Pre cut tabs"; "media-type.roll" = "Roll"; "media-type.screen" = "Screen"; "media-type.screen-paged" = "Screen paged"; "media-type.self-adhesive" = "Self adhesive"; "media-type.self-adhesive-film" = "Self adhesive film"; "media-type.shrink-foil" = "Shrink foil"; "media-type.single-face" = "Single face"; "media-type.single-wall" = "Single wall"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Stationery"; "media-type.stationery-archival" = "Stationery archival"; "media-type.stationery-coated" = "Coated paper"; "media-type.stationery-cotton" = "Stationery cotton"; "media-type.stationery-fine" = "Vellum paper"; "media-type.stationery-heavyweight" = "Heavyweight paper"; "media-type.stationery-heavyweight-coated" = "Stationery heavyweight coated"; "media-type.stationery-inkjet" = "Stationery inkjet paper"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Lightweight paper"; "media-type.stationery-preprinted" = "Preprinted paper"; "media-type.stationery-prepunched" = "Punched paper"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transfer"; "media-type.transparency" = "Transparency"; "media-type.triple-wall" = "Triple wall"; "media-type.wet-film" = "Wet film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 or US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Envelope"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Envelope"; "media.iso_c10_28x40mm" = "C10 Envelope"; "media.iso_c1_648x917mm" = "C1 Envelope"; "media.iso_c2_458x648mm" = "C2 Envelope"; "media.iso_c3_324x458mm" = "C3 Envelope"; "media.iso_c4_229x324mm" = "C4 Envelope"; "media.iso_c5_162x229mm" = "C5 Envelope"; "media.iso_c6_114x162mm" = "C6 Envelope"; "media.iso_c6c5_114x229mm" = "C6/C5 Envelope"; "media.iso_c7_81x114mm" = "C7 Envelope"; "media.iso_c7c6_81x162mm" = "C7/C6 Envelope"; "media.iso_c8_57x81mm" = "C8 Envelope"; "media.iso_c9_40x57mm" = "C9 Envelope"; "media.iso_dl_110x220mm" = "DL Envelope"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Envelope Chou 2"; "media.jpn_chou3_120x235mm" = "Envelope Chou 3"; "media.jpn_chou40_90x225mm" = "Envelope Chou 40"; "media.jpn_chou4_90x205mm" = "Envelope Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Envelope Kahu"; "media.jpn_kaku2_240x332mm" = "Envelope Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Reply Postcard"; "media.jpn_you4_105x235mm" = "Envelope You 4"; "media.na_a2_4.375x5.75in" = "Envelope A2"; "media.na_c5_6.5x9.5in" = "Envelope C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "US Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "Statement"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US Letter (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US Letter (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Envelope Monarch"; "media.na_number-10_4.125x9.5in" = "Envelope #10"; "media.na_number-11_4.5x10.375in" = "Envelope #11"; "media.na_number-12_4.75x11in" = "Envelope #12"; "media.na_number-14_5x11.5in" = "Envelope #14"; "media.na_number-9_3.875x8.875in" = "Envelope #9"; "media.na_personal_3.625x6.5in" = "Envelope Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Envelope Invitation"; "media.om_italian_110x230mm" = "Envelope Italian"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389mm"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Envelope chinese #10"; "media.prc_16k_146x215mm" = "Chinese 16k"; "media.prc_1_102x165mm" = "Envelope chinese #1"; "media.prc_2_102x176mm" = "Envelope chinese #2"; "media.prc_32k_97x151mm" = "Chinese 32k"; "media.prc_3_125x176mm" = "Envelope chinese #3"; "media.prc_4_110x208mm" = "Envelope chinese #4"; "media.prc_5_110x220mm" = "Envelope chinese #5"; "media.prc_6_120x320mm" = "Envelope chinese #6"; "media.prc_7_160x230mm" = "Envelope chinese #7"; "media.prc_8_120x309mm" = "Envelope chinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "not configured"; "not visible" = "not visible"; "off" = "off"; "on" = "on"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Landscape"; "orientation-requested.5" = "Reverse landscape"; "orientation-requested.6" = "Reverse portrait"; "orientation-requested.7" = "None"; "output-bin" = "Output Tray"; "output-bin.auto" = "Automatic"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Face down"; "output-bin.face-up" = "Face up"; "output-bin.large-capacity" = "Large capacity"; "output-bin.left" = "Left"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Middle"; "output-bin.my-mailbox" = "My mailbox"; "output-bin.rear" = "Rear"; "output-bin.right" = "Right"; "output-bin.side" = "Side"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Print Mode"; "print-color-mode.auto" = "Automatic"; "print-color-mode.auto-monochrome" = "Auto monochrome"; "print-color-mode.bi-level" = "Text"; "print-color-mode.color" = "Color"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monochrome"; "print-color-mode.process-bi-level" = "Process Text"; "print-color-mode.process-monochrome" = "Process monochrome"; "print-content-optimize" = "Optimize For"; "print-content-optimize.auto" = "Automatic"; "print-content-optimize.graphic" = "Graphics"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text and graphics"; "print-darkness" = "Print Darkness"; "print-quality" = "Print Quality"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Best"; "print-scaling" = "Scaling"; "print-scaling.auto" = "Automatic"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Fill"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "None"; "print-speed" = "Print Speed"; "printer-resolution" = "Resolution"; "printer-state-reasons.cover-open" = "Cover open."; "printer-state-reasons.door-open" = "Door open."; "printer-state-reasons.identify-printer-requested" = "Identify printer."; "printer-state-reasons.input-tray-missing" = "Paper tray missing."; "printer-state-reasons.marker-supply-empty" = "Out of ink."; "printer-state-reasons.marker-supply-low" = "Low ink."; "printer-state-reasons.marker-waste-almost-full" = "Waste bin almost full."; "printer-state-reasons.marker-waste-full" = "Waste bin full."; "printer-state-reasons.media-empty" = "Out of paper."; "printer-state-reasons.media-jam" = "Paper jam."; "printer-state-reasons.media-low" = "Replace paper soon."; "printer-state-reasons.media-needed" = "Load paper."; "printer-state-reasons.none" = "Ready."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "See printer."; "printer-state-reasons.spool-area-full" = "Printer busy."; "printer-state-reasons.toner-empty" = "Out of toner."; "printer-state-reasons.toner-low" = "Toner low."; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "sides" = "2-Sided Printing"; "sides.one-sided" = "Off"; "sides.two-sided-long-edge" = "On (portrait)"; "sides.two-sided-short-edge" = "On (landscape)"; "unable to join" = "unable to join"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Åland Islands"; pappl-1.4.9/pappl/strings/en_strings.h000066400000000000000000001532071476704353100200140ustar00rootroot00000000000000static const char *en_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Cancel all jobs (cancel).\";\n" "\" -c COPIES\" = \" -c COPIES\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Specify printer.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Specify job ID (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Specify driver (add/modify).\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Specify number of copies (submit).\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (default)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=VALUE Specify option (add,modify,server,submit).\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 to 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 to 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOCATION'\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZATION'\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION'\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Specify ipp: or ipps: printer/server.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Specify socket: or usb: device (add/modify).\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Add a printer.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Automatically add supported printers.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Cancel one or more jobs.\";\n" "\" default Set the default printer.\" = \" default Set the default printer.\";\n" "\" delete Delete a printer.\" = \" delete Delete a printer.\";\n" "\" devices List devices.\" = \" devices List devices.\";\n" "\" drivers List drivers.\" = \" drivers List drivers.\";\n" "\" jobs List jobs.\" = \" jobs List jobs.\";\n" "\" modify Modify a printer.\" = \" modify Modify a printer.\";\n" "\" options List printer options.\" = \" options List printer options.\";\n" "\" pause Pause printing for a printer.\" = \" pause Pause printing for a printer.\";\n" "\" printers List printers.\" = \" printers List printers.\";\n" "\" resume Resume printing for a printer.\" = \" resume Resume printing for a printer.\";\n" "\" server Run a server.\" = \" server Run a server.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Shutdown a running server.\";\n" "\" status Show server/printer/job status.\" = \" status Show server/printer/job status.\";\n" "\" submit Submit a file for printing.\" = \" submit Submit a file for printing.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d inches/sec\";\n" "\"%d job\" = \"%d job\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %dmm\";\n" "\"%ddpi\" = \"%ddpi\";\n" "\"%dx%ddpi\" = \"%dx%ddpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g\\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s (%s%s)\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) from %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Media\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Bad 'server-port' value.\";\n" "\"%s: Bad job ID.\" = \"%s: Bad job ID.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Bad printer URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Cannot specify more than one sub-command.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Empty print file received on the standard input.\";\n" "\"%s: Failed to create a system.\" = \"%s: Failed to create a system.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Missing '-d PRINTER'.\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Missing '-m DRIVER-NAME'.\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Missing '-v DEVICE-URI'.\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Missing copy count after '-n'.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Missing device URI after '-v'.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Missing driver name after '-m'.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Missing filename after '--'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Missing hostname after '-h'.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Missing job ID after '-j'.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: Missing option(s) after '-o'.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Missing printer URI after '-u'.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Missing printer name after '-d'.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Missing space after '-o'.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Missing title after '-t'.\";\n" "\"%s: No default printer available.\" = \"%s: No default printer available.\";\n" "\"%s: No files to print.\" = \"%s: No files to print.\";\n" "\"%s: Server is not running.\" = \"%s: Server is not running.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Sub-command '%s' does not accept files.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Sub-command 'autoadd' is not supported.\";\n" "\"%s: Too many files.\" = \"%s: Too many files.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Unable to access '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Unable to add printer: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Unable to cancel job: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Unable to connect to printer at '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Unable to connect to server: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Unable to create temporary file: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Unable to delete printer: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Unable to get information for '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Unable to get information for printer: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Unable to get printer options: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Unable to modify printer: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Unable to pause printer: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Unable to print '%s': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Unable to resume printer: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Unable to set default printer: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Unable to shutdown server: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Unable to start server: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Unable to write to temporary file: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Unknown option '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Unknown option '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Unknown sub-command '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Unsupported URI scheme '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Warning - user credentials are not supported in URIs.\";\n" "\", Borderless\" = \", Borderless\";\n" "\"A printer with that name already exists.\" = \"A printer with that name already exists.\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"Add Printer\";\n" "\"Admin Group\" = \"Admin Group\";\n" "\"Afghanistan\" = \"Afghanistan\";\n" "\"Albania\" = \"Albania\";\n" "\"Algeria\" = \"Algeria\";\n" "\"American Samoa\" = \"American Samoa\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarctica\";\n" "\"Antigua and Barbuda\" = \"Antigua and Barbuda\";\n" "\"Argentina\" = \"Argentina\";\n" "\"Armenia\" = \"Armenia\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australia\";\n" "\"Austria\" = \"Austria\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Auto-Detect Driver\";\n" "\"Azerbaijan\" = \"Azerbaijan\";\n" "\"Bad administration group.\" = \"Bad administration group.\";\n" "\"Bad port number.\" = \"Bad port number.\";\n" "\"Bad print group.\" = \"Bad print group.\";\n" "\"Bad printer defaults.\" = \"Bad printer defaults.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahrain\";\n" "\"Bangladesh\" = \"Bangladesh\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Belarus\";\n" "\"Belgium\" = \"Belgium\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermuda\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivia (Plurinational State of)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius and Saba\";\n" "\"Borderless\" = \"Borderless\";\n" "\"Bosnia and Herzegovina\" = \"Bosnia and Herzegovina\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Bouvet Island\";\n" "\"Brazil\" = \"Brazil\";\n" "\"British Indian Ocean Territory\" = \"British Indian Ocean Territory\";\n" "\"Brunei Darussalam\" = \"Brunei Darussalam\";\n" "\"Bulgaria\" = \"Bulgaria\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cabo Verde\";\n" "\"Cambodia\" = \"Cambodia\";\n" "\"Cameroon\" = \"Cameroon\";\n" "\"Canada\" = \"Canada\";\n" "\"Cancel All Jobs\" = \"Cancel All Jobs\";\n" "\"Cancel Job\" = \"Cancel Job\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"Canceling\";\n" "\"Cayman Islands\" = \"Cayman Islands\";\n" "\"Central African Republic\" = \"Central African Republic\";\n" "\"Certificate created.\" = \"Certificate created.\";\n" "\"Certificate installed.\" = \"Certificate installed.\";\n" "\"Certificate request created.\" = \"Certificate request created.\";\n" "\"Chad\" = \"Chad\";\n" "\"Change Access Password\" = \"Change Access Password\";\n" "\"Change Log Level\" = \"Change Log Level\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"Change Wi-Fi Network\";\n" "\"Changes Saved.\" = \"Changes Saved.\";\n" "\"Changes saved.\" = \"Changes saved.\";\n" "\"Chile\" = \"Chile\";\n" "\"China\" = \"China\";\n" "\"Christmas Island\" = \"Christmas Island\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"Cocos (Keeling) Islands\";\n" "\"Colombia\" = \"Colombia\";\n" "\"Comoros\" = \"Comoros\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"Configuration\";\n" "\"Configure Media\" = \"Configure Media\";\n" "\"Confirm Cancel All\" = \"Confirm Cancel All\";\n" "\"Confirm Delete Printer\" = \"Confirm Delete Printer\";\n" "\"Congo\" = \"Congo\";\n" "\"Congo, Democratic Republic of the\" = \"Congo, Democratic Republic of the\";\n" "\"Contact\" = \"Contact\";\n" "\"Cook Islands\" = \"Cook Islands\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Create Certificate Signing Request\";\n" "\"Create New Certificate\" = \"Create New Certificate\";\n" "\"Create New TLS Certificate\" = \"Create New TLS Certificate\";\n" "\"Create TLS Certificate Request\" = \"Create TLS Certificate Request\";\n" "\"Croatia\" = \"Croatia\";\n" "\"Cuba\" = \"Cuba\";\n" "\"Curaçao\" = \"Curaçao\";\n" "\"Current Password\" = \"Current Password\";\n" "\"Custom Size\" = \"Custom Size\";\n" "\"Cyprus\" = \"Cyprus\";\n" "\"Czechia\" = \"Czechia\";\n" "\"Côte d'Ivoire\" = \"Côte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Service Name\";\n" "\"Debugging\" = \"Debugging\";\n" "\"Default printer set.\" = \"Default printer set.\";\n" "\"Delete\" = \"Delete\";\n" "\"Delete Printer\" = \"Delete Printer\";\n" "\"Denmark\" = \"Denmark\";\n" "\"Djibouti\" = \"Djibouti\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"Dominica\";\n" "\"Dominican Republic\" = \"Dominican Republic\";\n" "\"Download Certificate Request File\" = \"Download Certificate Request File\";\n" "\"Ecuador\" = \"Ecuador\";\n" "\"Egypt\" = \"Egypt\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Equatorial Guinea\";\n" "\"Eritrea\" = \"Eritrea\";\n" "\"Errors\" = \"Errors\";\n" "\"Estonia\" = \"Estonia\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Ethiopia\";\n" "\"Falkland Islands (Malvinas)\" = \"Falkland Islands (Malvinas)\";\n" "\"Faroe Islands\" = \"Faroe Islands\";\n" "\"Fatal Errors/Conditions\" = \"Fatal Errors/Conditions\";\n" "\"Fiji\" = \"Fiji\";\n" "\"Finland\" = \"Finland\";\n" "\"France\" = \"France\";\n" "\"French Guiana\" = \"French Guiana\";\n" "\"French Polynesia\" = \"French Polynesia\";\n" "\"French Southern Territories\" = \"French Southern Territories\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Georgia\";\n" "\"Germany\" = \"Germany\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Greece\";\n" "\"Greenland\" = \"Greenland\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Group changes saved.\";\n" "\"Guadeloupe\" = \"Guadeloupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Guinea\";\n" "\"Guinea-Bissau\" = \"Guinea-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island and McDonald Islands\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"Holy See\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Hostname\";\n" "\"Human-Readable Location\" = \"Human-Readable Location\";\n" "\"Hungary\" = \"Hungary\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"Iceland\";\n" "\"Identify Printer\" = \"Identify Printer\";\n" "\"India\" = \"India\";\n" "\"Indonesia\" = \"Indonesia\";\n" "\"Informational\" = \"Informational\";\n" "\"Install TLS Certificate\" = \"Install TLS Certificate\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"Invalid Job ID.\";\n" "\"Invalid certificate or private key.\" = \"Invalid certificate or private key.\";\n" "\"Invalid form data.\" = \"Invalid form data.\";\n" "\"Invalid form submission.\" = \"Invalid form submission.\";\n" "\"Invalid job ID.\" = \"Invalid job ID.\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (Islamic Republic of)\";\n" "\"Iraq\" = \"Iraq\";\n" "\"Ireland\" = \"Ireland\";\n" "\"Isle of Man\" = \"Isle of Man\";\n" "\"Israel\" = \"Israel\";\n" "\"Italy\" = \"Italy\";\n" "\"Jamaica\" = \"Jamaica\";\n" "\"Japan\" = \"Japan\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Job #\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"Jobs\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"Jordan\";\n" "\"Kazakhstan\" = \"Kazakhstan\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Korea (Democratic People's Republic of)\";\n" "\"Korea, Republic of\" = \"Korea, Republic of\";\n" "\"Kuwait\" = \"Kuwait\";\n" "\"Kyrgyzstan\" = \"Kyrgyzstan\";\n" "\"Landscape\" = \"Landscape\";\n" "\"Lao People's Democratic Republic\" = \"Lao People's Democratic Republic\";\n" "\"Latvia\" = \"Latvia\";\n" "\"Lebanon\" = \"Lebanon\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Level\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libya\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Lithuania\";\n" "\"Location\" = \"Location\";\n" "\"Log Level\" = \"Log Level\";\n" "\"Logging\" = \"Logging\";\n" "\"Logs\" = \"Logs\";\n" "\"Luxembourg\" = \"Luxembourg\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagascar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malaysia\";\n" "\"Maldives\" = \"Maldives\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"Marshall Islands\";\n" "\"Martinique\" = \"Martinique\";\n" "\"Mauritania\" = \"Mauritania\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Media\";\n" "\"Mexico\" = \"Mexico\";\n" "\"Micronesia (Federated States of)\" = \"Micronesia (Federated States of)\";\n" "\"Missing action.\" = \"Missing action.\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"Missing private key.\";\n" "\"Moldova, Republic of\" = \"Moldova, Republic of\";\n" "\"Monaco\" = \"Monaco\";\n" "\"Mongolia\" = \"Mongolia\";\n" "\"Montenegro\" = \"Montenegro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Morocco\";\n" "\"Mozambique\" = \"Mozambique\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Name\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Netherlands\";\n" "\"Network\" = \"Network\";\n" "\"Network Printer\" = \"Network Printer\";\n" "\"Networking\" = \"Networking\";\n" "\"New Caledonia\" = \"New Caledonia\";\n" "\"New Zealand\" = \"New Zealand\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"No default printer set.\";\n" "\"No jobs in history.\" = \"No jobs in history.\";\n" "\"Norfolk Island\" = \"Norfolk Island\";\n" "\"North Macedonia\" = \"North Macedonia\";\n" "\"Northern Mariana Islands\" = \"Northern Mariana Islands\";\n" "\"Norway\" = \"Norway\";\n" "\"Not set\" = \"Not set\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Options:\";\n" "\"Organization\" = \"Organization\";\n" "\"Organization Name\" = \"Organization Name\";\n" "\"Other Settings\" = \"Other Settings\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palestine, State of\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua New Guinea\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Password\";\n" "\"Password changed.\" = \"Password changed.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\";\n" "\"Passwords do not match.\" = \"Passwords do not match.\";\n" "\"Pause Printing\" = \"Pause Printing\";\n" "\"Peru\" = \"Peru\";\n" "\"Philippines\" = \"Philippines\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Please enter a hostname or IP address for the printer.\";\n" "\"Please enter a printer name.\" = \"Please enter a printer name.\";\n" "\"Please select a device.\" = \"Please select a device.\";\n" "\"Please select a driver.\" = \"Please select a driver.\";\n" "\"Please select a valid log level.\" = \"Please select a valid log level.\";\n" "\"Poland\" = \"Poland\";\n" "\"Portrait\" = \"Portrait\";\n" "\"Portugal\" = \"Portugal\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"Print Group\";\n" "\"Print Test Page\" = \"Print Test Page\";\n" "\"Print job options:\" = \"Print job options:\";\n" "\"Printer identified.\" = \"Printer identified.\";\n" "\"Printer is currently active.\" = \"Printer is currently active.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Printer names must start with a letter or underscore and cannot contain special characters.\";\n" "\"Printer options:\" = \"Printer options:\";\n" "\"Printer paused.\" = \"Printer paused.\";\n" "\"Printer pausing.\" = \"Printer pausing.\";\n" "\"Printer resuming.\" = \"Printer resuming.\";\n" "\"Printers\" = \"Printers\";\n" "\"Printing Defaults\" = \"Printing Defaults\";\n" "\"Puerto Rico\" = \"Puerto Rico\";\n" "\"Qatar\" = \"Qatar\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"Reprint Job\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"Resume Printing\";\n" "\"Reverse Landscape\" = \"Reverse Landscape\";\n" "\"Reverse Portrait\" = \"Reverse Portrait\";\n" "\"Romania\" = \"Romania\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Running, %s since %s%s.\";\n" "\"Russian Federation\" = \"Russian Federation\";\n" "\"Rwanda\" = \"Rwanda\";\n" "\"Réunion\" = \"Réunion\";\n" "\"Saint Barthélemy\" = \"Saint Barthélemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Saint Helena, Ascension and Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts and Nevis\";\n" "\"Saint Lucia\" = \"Saint Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (French part)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre and Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint Vincent and the Grenadines\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Sao Tome and Principe\";\n" "\"Saudi Arabia\" = \"Saudi Arabia\";\n" "\"Save Changes\" = \"Save Changes\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"Security\";\n" "\"Select Driver\" = \"Select Driver\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbia\";\n" "\"Server is not running.\" = \"Server is not running.\";\n" "\"Set Access Password\" = \"Set Access Password\";\n" "\"Set as Default\" = \"Set as Default\";\n" "\"Seychelles\" = \"Seychelles\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapore\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (Dutch part)\";\n" "\"Slovakia\" = \"Slovakia\";\n" "\"Slovenia\" = \"Slovenia\";\n" "\"Solomon Islands\" = \"Solomon Islands\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"South Africa\";\n" "\"South Georgia and the South Sandwich Islands\" = \"South Georgia and the South Sandwich Islands\";\n" "\"South Sudan\" = \"South Sudan\";\n" "\"Spain\" = \"Spain\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"Status\";\n" "\"Sub-commands:\" = \"Sub-commands:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Supplies\";\n" "\"Suriname\" = \"Suriname\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard and Jan Mayen\";\n" "\"Sweden\" = \"Sweden\";\n" "\"Switzerland\" = \"Switzerland\";\n" "\"Syrian Arab Republic\" = \"Syrian Arab Republic\";\n" "\"Taiwan, Province of China\" = \"Taiwan, Province of China\";\n" "\"Tajikistan\" = \"Tajikistan\";\n" "\"Tanzania, United Republic of\" = \"Tanzania, United Republic of\";\n" "\"Test page printed.\" = \"Test page printed.\";\n" "\"Thailand\" = \"Thailand\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad and Tobago\";\n" "\"Tunisia\" = \"Tunisia\";\n" "\"Turkey\" = \"Turkey\";\n" "\"Turkmenistan\" = \"Turkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Turks and Caicos Islands\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ukraine\";\n" "\"Unable to access test print file.\" = \"Unable to access test print file.\";\n" "\"Unable to copy print job.\" = \"Unable to copy print job.\";\n" "\"Unable to create certificate request.\" = \"Unable to create certificate request.\";\n" "\"Unable to create certificate.\" = \"Unable to create certificate.\";\n" "\"Unable to create test print job.\" = \"Unable to create test print job.\";\n" "\"Unable to identify printer.\" = \"Unable to identify printer.\";\n" "\"Unable to lookup address.\" = \"Unable to lookup address.\";\n" "\"Unable to use that driver.\" = \"Unable to use that driver.\";\n" "\"United Arab Emirates\" = \"United Arab Emirates\";\n" "\"United Kingdom\" = \"United Kingdom\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"United Kingdom of Great Britain and Northern Ireland\";\n" "\"United States Minor Outlying Islands\" = \"United States Minor Outlying Islands\";\n" "\"United States of America\" = \"United States of America\";\n" "\"Unknown\" = \"Unknown\";\n" "\"Unknown action.\" = \"Unknown action.\";\n" "\"Unknown form action.\" = \"Unknown form action.\";\n" "\"Unknown form request.\" = \"Unknown form request.\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\";\n" "\"Use My Position\" = \"Use My Position\";\n" "\"Users\" = \"Users\";\n" "\"Uzbekistan\" = \"Uzbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (Bolivarian Republic of)\";\n" "\"Version %s\" = \"Version %s\";\n" "\"Viet Nam\" = \"Viet Nam\";\n" "\"View Logs\" = \"View Logs\";\n" "\"Virgin Islands (British)\" = \"Virgin Islands (British)\";\n" "\"Virgin Islands (U.S.)\" = \"Virgin Islands (U.S.)\";\n" "\"Wallis and Futuna\" = \"Wallis and Futuna\";\n" "\"Warning\" = \"Warning\";\n" "\"Western Sahara\" = \"Western Sahara\";\n" "\"Wi-Fi Configuration\" = \"Wi-Fi Configuration\";\n" "\"Wi-Fi Network\" = \"Wi-Fi Network\";\n" "\"Width\" = \"Width\";\n" "\"Wrong old password.\" = \"Wrong old password.\";\n" "\"Yemen\" = \"Yemen\";\n" "\"Zambia\" = \"Zambia\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Number of Copies\";\n" "\"default printer\" = \"default printer\";\n" "\"finishings\" = \"Finisher\";\n" "\"finishings.10\" = \"Fold\";\n" "\"finishings.100\" = \"Z fold\";\n" "\"finishings.101\" = \"Engineering Z fold\";\n" "\"finishings.11\" = \"Cut\";\n" "\"finishings.12\" = \"Bale\";\n" "\"finishings.13\" = \"Booklet maker\";\n" "\"finishings.15\" = \"Coat\";\n" "\"finishings.16\" = \"Laminate\";\n" "\"finishings.20\" = \"Staple top left\";\n" "\"finishings.21\" = \"Staple bottom left\";\n" "\"finishings.22\" = \"Staple top right\";\n" "\"finishings.23\" = \"Staple bottom right\";\n" "\"finishings.24\" = \"Edge stitch left\";\n" "\"finishings.25\" = \"Edge stitch top\";\n" "\"finishings.26\" = \"Edge stitch right\";\n" "\"finishings.27\" = \"Edge stitch bottom\";\n" "\"finishings.28\" = \"2 staples on left\";\n" "\"finishings.29\" = \"2 staples on top\";\n" "\"finishings.3\" = \"None\";\n" "\"finishings.30\" = \"2 staples on right\";\n" "\"finishings.31\" = \"2 staples on bottom\";\n" "\"finishings.32\" = \"3 staples on left\";\n" "\"finishings.33\" = \"3 staples on top\";\n" "\"finishings.34\" = \"3 staples on right\";\n" "\"finishings.35\" = \"3 staples on bottom\";\n" "\"finishings.4\" = \"Staple\";\n" "\"finishings.5\" = \"Punch\";\n" "\"finishings.50\" = \"Bind left\";\n" "\"finishings.51\" = \"Bind top\";\n" "\"finishings.52\" = \"Bind right\";\n" "\"finishings.53\" = \"Bind bottom\";\n" "\"finishings.6\" = \"Cover\";\n" "\"finishings.60\" = \"Cut after every page\";\n" "\"finishings.61\" = \"Cut after every document\";\n" "\"finishings.62\" = \"Cut after every set\";\n" "\"finishings.63\" = \"Cut after job\";\n" "\"finishings.7\" = \"Bind\";\n" "\"finishings.70\" = \"Punch top left\";\n" "\"finishings.71\" = \"Punch bottom left\";\n" "\"finishings.72\" = \"Punch top right\";\n" "\"finishings.73\" = \"Punch bottom right\";\n" "\"finishings.74\" = \"2-hole punch left\";\n" "\"finishings.75\" = \"2-hole punch top\";\n" "\"finishings.76\" = \"2-hole punch right\";\n" "\"finishings.77\" = \"2-hole punch bottom\";\n" "\"finishings.78\" = \"3-hole punch left\";\n" "\"finishings.79\" = \"3-hole punch top\";\n" "\"finishings.8\" = \"Saddle stitch\";\n" "\"finishings.80\" = \"3-hole punch right\";\n" "\"finishings.81\" = \"3-hole punch bottom\";\n" "\"finishings.82\" = \"4-hole punch left\";\n" "\"finishings.83\" = \"4-hole punch top\";\n" "\"finishings.84\" = \"4-hole punch right\";\n" "\"finishings.85\" = \"4-hole punch bottom\";\n" "\"finishings.86\" = \"Multi-hole punch left\";\n" "\"finishings.87\" = \"Multi-hole punch top\";\n" "\"finishings.88\" = \"Multi-hole punch right\";\n" "\"finishings.89\" = \"Multi-hole punch bottom\";\n" "\"finishings.9\" = \"Edge stitch\";\n" "\"finishings.90\" = \"Accordion fold\";\n" "\"finishings.91\" = \"Double gate fold\";\n" "\"finishings.92\" = \"Gate fold\";\n" "\"finishings.93\" = \"Half fold\";\n" "\"finishings.94\" = \"Half Z fold\";\n" "\"finishings.95\" = \"Left gate fold\";\n" "\"finishings.96\" = \"Letter fold\";\n" "\"finishings.97\" = \"Parallel fold\";\n" "\"finishings.98\" = \"Poster fold\";\n" "\"finishings.99\" = \"Right gate fold\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"Stopping.\";\n" "\"job-state-reasons.compression-error\" = \"Decompression error.\";\n" "\"job-state-reasons.document-format-error\" = \"Document format error.\";\n" "\"job-state-reasons.document-password-error\" = \"Document password error.\";\n" "\"job-state-reasons.document-permission-error\" = \"Document permission error.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Document unprintable error.\";\n" "\"job-state-reasons.errors-detected\" = \"Errors detected.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Canceled at printer.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Canceled by user.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Printed.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Printed with errors.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Printed with warnings.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Insufficient data.\";\n" "\"job-state-reasons.job-fetchable\" = \"Fetchable.\";\n" "\"job-state-reasons.job-incoming\" = \"Incoming.\";\n" "\"job-state-reasons.job-printing\" = \"Printing.\";\n" "\"job-state-reasons.job-queued\" = \"Preparing to print.\";\n" "\"job-state-reasons.job-spooling\" = \"Spooling.\";\n" "\"job-state-reasons.none\" = \"Pending.\";\n" "\"job-state-reasons.printer-stopped\" = \"Printer offline.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Printer partially stopped.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Stopping.\";\n" "\"job-state-reasons.queued-in-device\" = \"Ready.\";\n" "\"job-state-reasons.warnings-detected\" = \"Warnings detected.\";\n" "\"job-state.3\" = \"Pending\";\n" "\"job-state.4\" = \"Held\";\n" "\"job-state.5\" = \"Processing\";\n" "\"job-state.6\" = \"Stopped\";\n" "\"job-state.7\" = \"Canceled\";\n" "\"job-state.8\" = \"Aborted\";\n" "\"job-state.9\" = \"Completed\";\n" "\"joining\" = \"joining\";\n" "\"media\" = \"Media\";\n" "\"media-col\" = \"Media\";\n" "\"media-size\" = \"Media Size\";\n" "\"media-size-name\" = \"Media Size\";\n" "\"media-source\" = \"Input Tray\";\n" "\"media-source.alternate\" = \"Alternate\";\n" "\"media-source.alternate-roll\" = \"Alternate roll\";\n" "\"media-source.auto\" = \"Automatic\";\n" "\"media-source.bottom\" = \"Bottom\";\n" "\"media-source.by-pass-tray\" = \"Multipurpose tray\";\n" "\"media-source.center\" = \"Center\";\n" "\"media-source.disc\" = \"Disc\";\n" "\"media-source.envelope\" = \"Envelope\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Large capacity\";\n" "\"media-source.left\" = \"Left\";\n" "\"media-source.main\" = \"Main\";\n" "\"media-source.main-roll\" = \"Main roll\";\n" "\"media-source.manual\" = \"Manual\";\n" "\"media-source.middle\" = \"Middle\";\n" "\"media-source.photo\" = \"Photo\";\n" "\"media-source.rear\" = \"Rear\";\n" "\"media-source.right\" = \"Right\";\n" "\"media-source.roll-1\" = \"Roll 1\";\n" "\"media-source.roll-10\" = \"Roll 10\";\n" "\"media-source.roll-2\" = \"Roll 2\";\n" "\"media-source.roll-3\" = \"Roll 3\";\n" "\"media-source.roll-4\" = \"Roll 4\";\n" "\"media-source.roll-5\" = \"Roll 5\";\n" "\"media-source.roll-6\" = \"Roll 6\";\n" "\"media-source.roll-7\" = \"Roll 7\";\n" "\"media-source.roll-8\" = \"Roll 8\";\n" "\"media-source.roll-9\" = \"Roll 9\";\n" "\"media-source.side\" = \"Side\";\n" "\"media-source.top\" = \"Top\";\n" "\"media-source.tray-1\" = \"Tray 1\";\n" "\"media-source.tray-10\" = \"Tray 10\";\n" "\"media-source.tray-11\" = \"Tray 11\";\n" "\"media-source.tray-12\" = \"Tray 12\";\n" "\"media-source.tray-13\" = \"Tray 13\";\n" "\"media-source.tray-14\" = \"Tray 14\";\n" "\"media-source.tray-15\" = \"Tray 15\";\n" "\"media-source.tray-16\" = \"Tray 16\";\n" "\"media-source.tray-17\" = \"Tray 17\";\n" "\"media-source.tray-18\" = \"Tray 18\";\n" "\"media-source.tray-19\" = \"Tray 19\";\n" "\"media-source.tray-2\" = \"Tray 2\";\n" "\"media-source.tray-20\" = \"Tray 20\";\n" "\"media-source.tray-3\" = \"Tray 3\";\n" "\"media-source.tray-4\" = \"Tray 4\";\n" "\"media-source.tray-5\" = \"Tray 5\";\n" "\"media-source.tray-6\" = \"Tray 6\";\n" "\"media-source.tray-7\" = \"Tray 7\";\n" "\"media-source.tray-8\" = \"Tray 8\";\n" "\"media-source.tray-9\" = \"Tray 9\";\n" "\"media-tracking\" = \"Media Tracking\";\n" "\"media-tracking.continuous\" = \"Continuous\";\n" "\"media-tracking.gap\" = \"Gap\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Media Type\";\n" "\"media-type.aluminum\" = \"Aluminum\";\n" "\"media-type.auto\" = \"Automatic\";\n" "\"media-type.back-print-film\" = \"Back print film\";\n" "\"media-type.cardboard\" = \"Cardboard\";\n" "\"media-type.cardstock\" = \"Cardstock\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Continuous\";\n" "\"media-type.continuous-long\" = \"Continuous long\";\n" "\"media-type.continuous-short\" = \"Continuous short\";\n" "\"media-type.corrugated-board\" = \"Corrugated board\";\n" "\"media-type.disc\" = \"Optical disc\";\n" "\"media-type.disc-glossy\" = \"Glossy optical disc\";\n" "\"media-type.disc-high-gloss\" = \"High gloss optical disc\";\n" "\"media-type.disc-matte\" = \"Matte optical disc\";\n" "\"media-type.disc-satin\" = \"Satin optical disc\";\n" "\"media-type.disc-semi-gloss\" = \"Semi-gloss optical disc\";\n" "\"media-type.double-wall\" = \"Double wall\";\n" "\"media-type.dry-film\" = \"Dry film\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Embossing foil\";\n" "\"media-type.end-board\" = \"End board\";\n" "\"media-type.envelope\" = \"Envelope\";\n" "\"media-type.envelope-archival\" = \"Archival envelope\";\n" "\"media-type.envelope-bond\" = \"Bond envelope\";\n" "\"media-type.envelope-coated\" = \"Coated envelope\";\n" "\"media-type.envelope-cotton\" = \"Cotton envelope\";\n" "\"media-type.envelope-fine\" = \"Fine envelope\";\n" "\"media-type.envelope-heavyweight\" = \"Heavyweight envelope\";\n" "\"media-type.envelope-inkjet\" = \"Inkjet envelope\";\n" "\"media-type.envelope-lightweight\" = \"Lightweight envelope\";\n" "\"media-type.envelope-plain\" = \"Plain envelope\";\n" "\"media-type.envelope-preprinted\" = \"Preprinted envelope\";\n" "\"media-type.envelope-window\" = \"Windowed envelope\";\n" "\"media-type.fabric\" = \"Fabric\";\n" "\"media-type.fabric-archival\" = \"Archival fabric\";\n" "\"media-type.fabric-glossy\" = \"Glossy fabric\";\n" "\"media-type.fabric-high-gloss\" = \"High gloss fabric\";\n" "\"media-type.fabric-matte\" = \"Matte fabric\";\n" "\"media-type.fabric-semi-gloss\" = \"Semi-gloss fabric\";\n" "\"media-type.fabric-waterproof\" = \"Waterproof fabric\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Flexo base\";\n" "\"media-type.flexo-photo-polymer\" = \"Flexo photo polymer\";\n" "\"media-type.flute\" = \"Flute\";\n" "\"media-type.foil\" = \"Foil\";\n" "\"media-type.full-cut-tabs\" = \"Full cut tabs\";\n" "\"media-type.glass\" = \"Glass\";\n" "\"media-type.glass-colored\" = \"Glass colored\";\n" "\"media-type.glass-opaque\" = \"Glass opaque\";\n" "\"media-type.glass-surfaced\" = \"Glass surfaced\";\n" "\"media-type.glass-textured\" = \"Glass textured\";\n" "\"media-type.gravure-cylinder\" = \"Gravure cylinder\";\n" "\"media-type.image-setter-paper\" = \"Image setter paper\";\n" "\"media-type.imaging-cylinder\" = \"Imaging cylinder\";\n" "\"media-type.labels\" = \"Labels\";\n" "\"media-type.labels-colored\" = \"Colored labels\";\n" "\"media-type.labels-glossy\" = \"Glossy labels\";\n" "\"media-type.labels-high-gloss\" = \"High gloss labels\";\n" "\"media-type.labels-inkjet\" = \"Inkjet labels\";\n" "\"media-type.labels-matte\" = \"Matte labels\";\n" "\"media-type.labels-permanent\" = \"Permanent labels\";\n" "\"media-type.labels-satin\" = \"Satin labels\";\n" "\"media-type.labels-security\" = \"Security labels\";\n" "\"media-type.labels-semi-gloss\" = \"Semi-gloss labels\";\n" "\"media-type.laminating-foil\" = \"Laminating foil\";\n" "\"media-type.letterhead\" = \"Letterhead\";\n" "\"media-type.metal\" = \"Metal\";\n" "\"media-type.metal-glossy\" = \"Metal glossy\";\n" "\"media-type.metal-high-gloss\" = \"Metal high gloss\";\n" "\"media-type.metal-matte\" = \"Metal matte\";\n" "\"media-type.metal-satin\" = \"Metal satin\";\n" "\"media-type.metal-semi-gloss\" = \"Metal semi gloss\";\n" "\"media-type.mounting-tape\" = \"Mounting tape\";\n" "\"media-type.multi-layer\" = \"Multi layer\";\n" "\"media-type.multi-part-form\" = \"Multi part form\";\n" "\"media-type.other\" = \"Other\";\n" "\"media-type.paper\" = \"Paper\";\n" "\"media-type.photographic\" = \"Photo paper\";\n" "\"media-type.photographic-archival\" = \"Photographic archival\";\n" "\"media-type.photographic-film\" = \"Photo film\";\n" "\"media-type.photographic-glossy\" = \"Glossy photo paper\";\n" "\"media-type.photographic-high-gloss\" = \"High gloss photo paper\";\n" "\"media-type.photographic-matte\" = \"Matte photo paper\";\n" "\"media-type.photographic-satin\" = \"Satin photo paper\";\n" "\"media-type.photographic-semi-gloss\" = \"Semi-gloss photo paper\";\n" "\"media-type.plastic\" = \"Plastic\";\n" "\"media-type.plastic-archival\" = \"Plastic archival\";\n" "\"media-type.plastic-colored\" = \"Plastic colored\";\n" "\"media-type.plastic-glossy\" = \"Plastic glossy\";\n" "\"media-type.plastic-high-gloss\" = \"Plastic high gloss\";\n" "\"media-type.plastic-matte\" = \"Plastic matte\";\n" "\"media-type.plastic-satin\" = \"Plastic satin\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastic semi gloss\";\n" "\"media-type.plate\" = \"Plate\";\n" "\"media-type.polyester\" = \"Polyester\";\n" "\"media-type.pre-cut-tabs\" = \"Pre cut tabs\";\n" "\"media-type.roll\" = \"Roll\";\n" "\"media-type.screen\" = \"Screen\";\n" "\"media-type.screen-paged\" = \"Screen paged\";\n" "\"media-type.self-adhesive\" = \"Self adhesive\";\n" "\"media-type.self-adhesive-film\" = \"Self adhesive film\";\n" "\"media-type.shrink-foil\" = \"Shrink foil\";\n" "\"media-type.single-face\" = \"Single face\";\n" "\"media-type.single-wall\" = \"Single wall\";\n" "\"media-type.sleeve\" = \"Sleeve\";\n" "\"media-type.stationery\" = \"Stationery\";\n" "\"media-type.stationery-archival\" = \"Stationery archival\";\n" "\"media-type.stationery-coated\" = \"Coated paper\";\n" "\"media-type.stationery-cotton\" = \"Stationery cotton\";\n" "\"media-type.stationery-fine\" = \"Vellum paper\";\n" "\"media-type.stationery-heavyweight\" = \"Heavyweight paper\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Stationery heavyweight coated\";\n" "\"media-type.stationery-inkjet\" = \"Stationery inkjet paper\";\n" "\"media-type.stationery-letterhead\" = \"Letterhead\";\n" "\"media-type.stationery-lightweight\" = \"Lightweight paper\";\n" "\"media-type.stationery-preprinted\" = \"Preprinted paper\";\n" "\"media-type.stationery-prepunched\" = \"Punched paper\";\n" "\"media-type.tab-stock\" = \"Tab stock\";\n" "\"media-type.tractor\" = \"Tractor\";\n" "\"media-type.transfer\" = \"Transfer\";\n" "\"media-type.transparency\" = \"Transparency\";\n" "\"media-type.triple-wall\" = \"Triple wall\";\n" "\"media-type.wet-film\" = \"Wet film\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 or US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Envelope\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Envelope\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Envelope\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Envelope\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Envelope\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Envelope\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Envelope\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Envelope\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Envelope\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Envelope\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Envelope\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Envelope\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Envelope\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Envelope\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Envelope\";\n" "\"media.iso_dl_110x220mm\" = \"DL Envelope\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Executive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Envelope Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Envelope Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Envelope Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Envelope Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Envelope Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Envelope Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Reply Postcard\";\n" "\"media.jpn_you4_105x235mm\" = \"Envelope You 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Envelope A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Envelope C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Executive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"European Fanfold\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"US Fanfold\";\n" "\"media.na_foolscap_8.5x13in\" = \"Foolscap\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Statement\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"US Letter (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"US Letter (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"US Letter\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Envelope Monarch\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Envelope #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Envelope #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Envelope #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Envelope #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Envelope #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Envelope Personal\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (Special)\";\n" "\"media.om_invite_220x220mm\" = \"Envelope Invitation\";\n" "\"media.om_italian_110x230mm\" = \"Envelope Italian\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389mm\";\n" "\"media.om_postfix_114x229mm\" = \"Envelope Postfix\";\n" "\"media.prc_10_324x458mm\" = \"Envelope chinese #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chinese 16k\";\n" "\"media.prc_1_102x165mm\" = \"Envelope chinese #1\";\n" "\"media.prc_2_102x176mm\" = \"Envelope chinese #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chinese 32k\";\n" "\"media.prc_3_125x176mm\" = \"Envelope chinese #3\";\n" "\"media.prc_4_110x208mm\" = \"Envelope chinese #4\";\n" "\"media.prc_5_110x220mm\" = \"Envelope chinese #5\";\n" "\"media.prc_6_120x320mm\" = \"Envelope chinese #6\";\n" "\"media.prc_7_160x230mm\" = \"Envelope chinese #7\";\n" "\"media.prc_8_120x309mm\" = \"Envelope chinese #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"not configured\";\n" "\"not visible\" = \"not visible\";\n" "\"off\" = \"off\";\n" "\"on\" = \"on\";\n" "\"orientation-requested\" = \"Orientation\";\n" "\"orientation-requested.3\" = \"Portrait\";\n" "\"orientation-requested.4\" = \"Landscape\";\n" "\"orientation-requested.5\" = \"Reverse landscape\";\n" "\"orientation-requested.6\" = \"Reverse portrait\";\n" "\"orientation-requested.7\" = \"None\";\n" "\"output-bin\" = \"Output Tray\";\n" "\"output-bin.auto\" = \"Automatic\";\n" "\"output-bin.bottom\" = \"Bottom\";\n" "\"output-bin.center\" = \"Center\";\n" "\"output-bin.face-down\" = \"Face down\";\n" "\"output-bin.face-up\" = \"Face up\";\n" "\"output-bin.large-capacity\" = \"Large capacity\";\n" "\"output-bin.left\" = \"Left\";\n" "\"output-bin.mailbox-1\" = \"Mailbox 1\";\n" "\"output-bin.mailbox-10\" = \"Mailbox 10\";\n" "\"output-bin.mailbox-2\" = \"Mailbox 2\";\n" "\"output-bin.mailbox-3\" = \"Mailbox 3\";\n" "\"output-bin.mailbox-4\" = \"Mailbox 4\";\n" "\"output-bin.mailbox-5\" = \"Mailbox 5\";\n" "\"output-bin.mailbox-6\" = \"Mailbox 6\";\n" "\"output-bin.mailbox-7\" = \"Mailbox 7\";\n" "\"output-bin.mailbox-8\" = \"Mailbox 8\";\n" "\"output-bin.mailbox-9\" = \"Mailbox 9\";\n" "\"output-bin.middle\" = \"Middle\";\n" "\"output-bin.my-mailbox\" = \"My mailbox\";\n" "\"output-bin.rear\" = \"Rear\";\n" "\"output-bin.right\" = \"Right\";\n" "\"output-bin.side\" = \"Side\";\n" "\"output-bin.stacker-1\" = \"Stacker 1\";\n" "\"output-bin.stacker-10\" = \"Stacker 10\";\n" "\"output-bin.stacker-2\" = \"Stacker 2\";\n" "\"output-bin.stacker-3\" = \"Stacker 3\";\n" "\"output-bin.stacker-4\" = \"Stacker 4\";\n" "\"output-bin.stacker-5\" = \"Stacker 5\";\n" "\"output-bin.stacker-6\" = \"Stacker 6\";\n" "\"output-bin.stacker-7\" = \"Stacker 7\";\n" "\"output-bin.stacker-8\" = \"Stacker 8\";\n" "\"output-bin.stacker-9\" = \"Stacker 9\";\n" "\"output-bin.top\" = \"Top\";\n" "\"output-bin.tray-1\" = \"Tray 1\";\n" "\"output-bin.tray-10\" = \"Tray 10\";\n" "\"output-bin.tray-2\" = \"Tray 2\";\n" "\"output-bin.tray-3\" = \"Tray 3\";\n" "\"output-bin.tray-4\" = \"Tray 4\";\n" "\"output-bin.tray-5\" = \"Tray 5\";\n" "\"output-bin.tray-6\" = \"Tray 6\";\n" "\"output-bin.tray-7\" = \"Tray 7\";\n" "\"output-bin.tray-8\" = \"Tray 8\";\n" "\"output-bin.tray-9\" = \"Tray 9\";\n" "\"print-color-mode\" = \"Print Mode\";\n" "\"print-color-mode.auto\" = \"Automatic\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monochrome\";\n" "\"print-color-mode.bi-level\" = \"Text\";\n" "\"print-color-mode.color\" = \"Color\";\n" "\"print-color-mode.highlight\" = \"Highlight\";\n" "\"print-color-mode.monochrome\" = \"Monochrome\";\n" "\"print-color-mode.process-bi-level\" = \"Process Text\";\n" "\"print-color-mode.process-monochrome\" = \"Process monochrome\";\n" "\"print-content-optimize\" = \"Optimize For\";\n" "\"print-content-optimize.auto\" = \"Automatic\";\n" "\"print-content-optimize.graphic\" = \"Graphics\";\n" "\"print-content-optimize.photo\" = \"Photo\";\n" "\"print-content-optimize.text\" = \"Text\";\n" "\"print-content-optimize.text-and-graphic\" = \"Text and graphics\";\n" "\"print-darkness\" = \"Print Darkness\";\n" "\"print-quality\" = \"Print Quality\";\n" "\"print-quality.3\" = \"Draft\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Best\";\n" "\"print-scaling\" = \"Scaling\";\n" "\"print-scaling.auto\" = \"Automatic\";\n" "\"print-scaling.auto-fit\" = \"Auto-fit\";\n" "\"print-scaling.fill\" = \"Fill\";\n" "\"print-scaling.fit\" = \"Fit\";\n" "\"print-scaling.none\" = \"None\";\n" "\"print-speed\" = \"Print Speed\";\n" "\"printer-resolution\" = \"Resolution\";\n" "\"printer-state-reasons.cover-open\" = \"Cover open.\";\n" "\"printer-state-reasons.door-open\" = \"Door open.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Identify printer.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Paper tray missing.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Out of ink.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Low ink.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Waste bin almost full.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Waste bin full.\";\n" "\"printer-state-reasons.media-empty\" = \"Out of paper.\";\n" "\"printer-state-reasons.media-jam\" = \"Paper jam.\";\n" "\"printer-state-reasons.media-low\" = \"Replace paper soon.\";\n" "\"printer-state-reasons.media-needed\" = \"Load paper.\";\n" "\"printer-state-reasons.none\" = \"Ready.\";\n" "\"printer-state-reasons.offline\" = \"Offline.\";\n" "\"printer-state-reasons.other\" = \"See printer.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Printer busy.\";\n" "\"printer-state-reasons.toner-empty\" = \"Out of toner.\";\n" "\"printer-state-reasons.toner-low\" = \"Toner low.\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Processing\";\n" "\"printer-state.5\" = \"Stopped\";\n" "\"sides\" = \"2-Sided Printing\";\n" "\"sides.one-sided\" = \"Off\";\n" "\"sides.two-sided-long-edge\" = \"On (portrait)\";\n" "\"sides.two-sided-short-edge\" = \"On (landscape)\";\n" "\"unable to join\" = \"unable to join\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Åland Islands\";\n"; pappl-1.4.9/pappl/strings/es.strings000066400000000000000000001376211476704353100175140ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Cancelar todos los trabajos (cancelar)."; " -c COPIES" = " -c COPIAS"; " -d PRINTER Specify printer." = " -d PRINTER Especifique la impresora."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Especifique el ID de trabajo (cancel.)"; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Especificar controlador (add/modify.)"; " -n COPIES Specify number of copies (submit)." = " -n COPIES Especifique el número de copias (presente.)"; " -o %s=%s (default)" = " -o %s=%s (por defecto)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Especifique la opción (add,modify,server,submit.)"; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 a 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 a 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE"; " -o printer-location='LOCATION'" = " -o printer-locations='LOCATION"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZACIÓN"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Especifique ipp: o ipps: impresora/servidor."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Especifique el socket: o usb: dispositivo (add/modify.)"; " add PRINTER Add a printer." = " add PRINTER Añadir una impresora."; " autoadd Automatically add supported printers." = " autoadd Agregue automáticamente impresoras compatibles."; " cancel Cancel one or more jobs." = " cancel Cancelar uno o más trabajos."; " default Set the default printer." = " default Establecer la impresora predeterminada."; " delete Delete a printer." = " delete Eliminar una impresora."; " devices List devices." = " devices Dispositivos Listos."; " drivers List drivers." = "conductores List drivers."; " jobs List jobs." = " jobs Empleo Listos."; " modify Modify a printer." = " modify Modifique una impresora."; " options List printer options." = " options Listar opciones de impresora."; " pause Pause printing for a printer." = " pause Impresión de pausa para una impresora."; " printers List printers." = " printers Lista de impresoras."; " resume Resume printing for a printer." = " resume Resumir la impresión para una impresora."; " server Run a server." = " server Ejecute un servidor."; " shutdown Shutdown a running server." = " shutdown Apaga un servidor en funcionamiento."; " status Show server/printer/job status." = " status Mostrar el estado del servidor/printer/job."; " submit Submit a file for printing." = " submit Enviar un archivo para imprimir."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "hace %d días a las %02d:%02d:%02d"; "%d inches/sec" = "%d pulgadas/sec"; "%d job" = "%d trabajo"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%d dpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g \""; /* size (type+borderless) */ "%s (%s%s)" = "%s ( %s %s )"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) de %s"; /* Source/Tray Media */ "%s Media" = "%s Media"; "%s: Bad 'server-port' value." = "%s: Mal valor de puerto de servidor."; "%s: Bad job ID." = "Mala identificación de trabajo."; "%s: Bad printer URI '%s'." = "%s: Bad printer URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: No se puede especificar más de un sub-command."; "%s: Empty print file received on the standard input." = "%s: Archivo de impresión vacío recibido en la entrada estándar."; "%s: Failed to create a system." = "%s: Failed to create a system."; "%s: Missing '-d PRINTER'." = "Desaparecido '-d PRINTER. '"; "%s: Missing '-m DRIVER-NAME'." = "Perdiendo mi ADN. '"; "%s: Missing '-v DEVICE-URI'." = "- Perdiendo a la policía. '"; "%s: Missing copy count after '-n'." = "%s: Una copia perdida cuenta después de -n."; "%s: Missing device URI after '-v'." = "%s: Dispositivo perdido URI después de -v."; "%s: Missing driver name after '-m'." = "%s: Falta el nombre del conductor después de -m."; "%s: Missing filename after '--'." = "%s: Desapareciendo el nombre de archivo después de '--'."; "%s: Missing hostname after '-h'." = "%s: Desapareciendo el nombre de host después de -h."; "%s: Missing job ID after '-j'." = "%s: Falta de identificación de trabajo después de -j."; "%s: Missing option(s) after '-o'." = "%s: opción oscurecer después de -o."; "%s: Missing printer URI after '-u'." = "%s: Impresora desaparecida URI después de -u."; "%s: Missing printer name after '-d'." = "%s: Falta el nombre de la impresora después de -d."; "%s: Missing space after '-o'." = "%s: Falta espacio después de -o."; "%s: Missing title after '-t'." = "%s: Perder el título después de -t."; "%s: No default printer available." = "%s: No hay impresora predeterminada disponible."; "%s: No files to print." = "%s: No hay archivos que imprimir."; "%s: Server is not running." = "%s: El servidor no está funcionando."; "%s: Sub-command '%s' does not accept files." = "%s: Sub-command '%s' no acepta archivos."; "%s: Sub-command 'autoadd' is not supported." = "%s: Autoadd subcommand no es compatible."; "%s: Too many files." = "%s: Demasiados archivos."; "%s: Unable to access '%s': %s" = "%s: Incapaz de acceder a '%s': %s"; "%s: Unable to add printer: %s" = "%s: Incapaz de añadir la impresora: %s"; "%s: Unable to cancel job: %s" = "%s: Incapaz de cancelar el trabajo: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Incapaz de conectarse a la impresora en '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Incapaz de conectarse al servidor: %s"; "%s: Unable to create temporary file: %s" = "%s: Incapaz de crear un archivo temporal: %s"; "%s: Unable to delete printer: %s" = "%s: Incapaz de eliminar la impresora: %s"; "%s: Unable to get available devices: %s" = "%s: No se pueden obtener los dispositivos disponibles: %s"; "%s: Unable to get information for '%s': %s" = "%s: Incapaz de obtener información para '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Incapaz de obtener información para la impresora: %s"; "%s: Unable to get printer options: %s" = "%s: Incapaz de obtener opciones de impresora: %s"; "%s: Unable to modify printer: %s" = "%s: Incapaz de modificar la impresora: %s"; "%s: Unable to pause printer: %s" = "%s: Incapacidad para detener la impresora: %s"; "%s: Unable to print '%s': %s" = "%s: Incapaz de imprimir '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Incapaz de reanudar la impresora: %s"; "%s: Unable to set default printer: %s" = "%s: Incapaz de configurar la impresora predeterminada: %s"; "%s: Unable to shutdown server: %s" = "%s: Incapaz de apagar el servidor: %s"; "%s: Unable to start server: %s" = "%s: Incapaz de iniciar servidor: %s"; "%s: Unable to write to temporary file: %s" = "%s: Incapaz de escribir al archivo temporal: %s"; "%s: Unknown option '%s'." = "%s: Opción desconocida '%s'."; "%s: Unknown option '-%c'." = "%s: Opción desconocida '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Unknown sub-command '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Unsupported URI scheme '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Advertencia - las credenciales del usuario no son compatibles con URIs."; ", Borderless" = ", sin fronteras"; "A printer with that name already exists." = "Una impresora con ese nombre ya existe."; "Aborted %s" = "Abortado %s"; "Add Printer" = "Añadir impresora"; "Admin Group" = "Admin Group"; "Afghanistan" = "Afganistán"; "Albania" = "Albania"; "Algeria" = "Argelia"; "American Samoa" = "Samoa Americana"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguila"; "Antarctica" = "Antártida"; "Antigua and Barbuda" = "Antigua y Barbuda"; "Argentina" = "Argentina"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Auto"; "Auto-Detect Driver" = "Auto-Detect Driver"; "Azerbaijan" = "Azerbaiyán"; "Bad administration group." = "Grupo de mala administración."; "Bad port number." = "Mal número de puerto."; "Bad print group." = "Grupo de impresión malo."; "Bad printer defaults." = "Impresoras malas."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrein"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbados"; "Belarus" = "Belarús"; "Belgium" = "Bélgica"; "Belize" = "Belice"; "Benin" = "Benin"; "Bermuda" = "Bermudas"; "Bhutan" = "Bhután"; "Bolivia (Plurinational State of)" = "Bolivia (Estado Plurinacional de)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius y Saba"; "Borderless" = "Sin fronteras"; "Bosnia and Herzegovina" = "Bosnia y Herzegovina"; "Botswana" = "Botswana"; "Bouvet Island" = "Bouvet Island"; "Brazil" = "Brasil"; "British Indian Ocean Territory" = "British Indian Ocean Territory"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bulgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Camboya"; "Cameroon" = "Camerún"; "Canada" = "Canadá"; "Cancel All Jobs" = "Cancelar Todos los trabajos"; "Cancel Job" = "Cancelar trabajo"; "Canceled %s" = "Cancelado %s"; "Canceling" = "Cancelación"; "Cayman Islands" = "Islas Caimán"; "Central African Republic" = "República Centroafricana"; "Certificate created." = "Certificado creado."; "Certificate installed." = "Certificado instalado."; "Certificate request created." = "Solicitud de certificado creada."; "Chad" = "Chad"; "Change Access Password" = "Cambiar contraseña"; "Change Log Level" = "Nivel de registro de cambios"; "Change Network Settings" = "Cambiar la configuración de la red"; "Change Wi-Fi Network" = "Cambiar red Wi-Fi"; "Changes Saved." = "Cambios guardados."; "Changes saved." = "Cambios salvados."; "Chile" = "Chile"; "China" = "China"; "Christmas Island" = "Isla de Navidad"; "City/Locality" = "Ciudad/Localidad"; "Cocos (Keeling) Islands" = "Islas Cocos (Keeling)"; "Colombia" = "Colombia"; "Comoros" = "Comoras"; "Completed %s" = "Completado %s"; "Configuration" = "Configuración"; "Configure Media" = "Configure Media"; "Confirm Cancel All" = "Confirmación Todos"; "Confirm Delete Printer" = "Confirmar la impresora"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, República Democrática del Congo"; "Contact" = "Contacto"; "Cook Islands" = "Islas Cook"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Crear solicitud de registro de certificados"; "Create New Certificate" = "Crear nuevo certificado"; "Create New TLS Certificate" = "Crear nuevo certificado TLS"; "Create TLS Certificate Request" = "Crear TLS Solicitud de certificado"; "Croatia" = "Croacia"; "Cuba" = "Cuba"; "Curaçao" = "Curaao"; "Current Password" = "Contraseña actual"; "Custom Size" = "Tamaño personalizado"; "Cyprus" = "Chipre"; "Czechia" = "Czechia"; "Côte d'Ivoire" = "Cte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP con dirección manual"; "DNS-SD Service Name" = "DNS-SD Nombre del servicio"; "Debugging" = "Debugging"; "Default printer set." = "Juego de impresora predeterminado."; "Delete" = "Suprimir"; "Delete Printer" = "Eliminar la impresora"; "Denmark" = "Dinamarca"; "Djibouti" = "Djibouti"; "Domain Name" = "Nombre del dominio"; "Dominica" = "Dominica"; "Dominican Republic" = "República Dominicana"; "Download Certificate Request File" = "Descargar certificado Solicitar archivo"; "Ecuador" = "Ecuador"; "Egypt" = "Egipto"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Guinea Ecuatorial"; "Eritrea" = "Eritrea"; "Errors" = "Errores"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Etiopía"; "Falkland Islands (Malvinas)" = "Islas Malvinas (Falkland Islands)"; "Faroe Islands" = "Islas Feroe"; "Fatal Errors/Conditions" = "Errores/Condiciones fatales"; "Fiji" = "Fiji"; "Finland" = "Finlandia"; "France" = "Francia"; "French Guiana" = "Guayana Francesa"; "French Polynesia" = "Polinesia Francesa"; "French Southern Territories" = "Territorios del Sur"; "Gabon" = "Gabón"; "Gambia" = "Gambia"; "Georgia" = "Georgia"; "Germany" = "Alemania"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Grecia"; "Greenland" = "Groenlandia"; "Grenada" = "Granada"; "Group changes saved." = "Cambios de grupo guardados."; "Guadeloupe" = "Guadalupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haití"; "Heard Island and McDonald Islands" = "Heard Island y McDonald Islands"; "Hidden SSID" = "SSID oculto"; "Hold Job" = "Mantener el empleo"; "Hold New Jobs" = "Mantener los nuevos empleos"; "Holding new jobs." = "Mantener nuevos puestos de trabajo."; "Holy See" = "Santa Sede"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Nombre de host"; "Human-Readable Location" = "Ubicación legible por humanos"; "Hungary" = "Hungría"; "IPv4 Address" = "Dirección IPv4"; "IPv4 Configuration" = "Configuración IPv4"; "IPv4 Gateway" = "Puerta de enlace IPv4"; "IPv4 Netmask" = "Máscara de red IPv4"; "IPv6 Address" = "Direcciones IPv6"; "IPv6 Configuration" = "Configuración IPv6"; "IPv6 Link-Local" = "Enlace local IPv6"; "IPv6 Prefix Length" = "Longitud del prefijo IPv6"; "Iceland" = "Islandia"; "Identify Printer" = "Identifique la impresora"; "India" = "India"; "Indonesia" = "Indonesia"; "Informational" = "Información"; "Install TLS Certificate" = "Instala TLS Certificado"; "Invalid IPv4 address." = "Dirección IPv4 incorrecta."; "Invalid IPv4 netmask." = "Máscara de red IPv4 incorrecta."; "Invalid IPv6 address." = "Dirección IPv6 incorrecta."; "Invalid IPv6 prefix length." = "Longitud del prefijo IPv6 incorrecto."; "Invalid Job ID." = "ID de trabajo inválido."; "Invalid certificate or private key." = "Certificado inválido o clave privada."; "Invalid form data." = "Datos de formulario inválidos."; "Invalid form submission." = "Sumisión de formulario inválido."; "Invalid job ID." = "ID de trabajo inválido."; "Invalid network configuration." = "Configuración de red incorrecta."; "Iran (Islamic Republic of)" = "Irán (República Islámica del)"; "Iraq" = "Iraq"; "Ireland" = "Irlanda"; "Isle of Man" = "Isla de Man"; "Israel" = "Israel"; "Italy" = "Italia"; "Jamaica" = "Jamaica"; "Japan" = "Japón"; "Jersey" = "Jersey"; "Job #" = "Job"; "Job canceled." = "Trabajo cancelado."; "Job held." = "Puesto ocupado."; "Job released." = "Trabajo liberado."; "Jobs" = "Empleo"; "Joining Wi-Fi Network" = "Unirse a la red Wi-Fi"; "Jordan" = "Jordania"; "Kazakhstan" = "Kazajstán"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Corea (República Popular Democrática de)"; "Korea, Republic of" = "Corea, República de Corea"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kirguistán"; "Landscape" = "Paisaje"; "Lao People's Democratic Republic" = "República Democrática Popular Lao"; "Latvia" = "Letonia"; "Lebanon" = "Líbano"; "Lesotho" = "Lesotho"; "Level" = "Nivel"; "Liberia" = "Liberia"; "Libya" = "Libia"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lituania"; "Location" = "Ubicación"; "Log Level" = "Nivel de registro"; "Logging" = "Registro"; "Logs" = "Logs"; "Luxembourg" = "Luxemburgo"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malasia"; "Maldives" = "Maldivas"; "Mali" = "Malí"; "Malta" = "Malta"; "Manual Configuration" = "Configuración manual"; "Marshall Islands" = "Islas Marshall"; "Martinique" = "Martinica"; "Mauritania" = "Mauritania"; "Mauritius" = "Mauricio"; "Mayotte" = "Mayotte"; "Media" = "Media"; "Mexico" = "México"; "Micronesia (Federated States of)" = "Micronesia (Estados Federados de)"; "Missing action." = "Falta de acción."; "Missing job ID." = "Falta el identificador del trabajo."; "Missing network name." = "Falta el nombre de la red."; "Missing private key." = "Falta la llave privada."; "Moldova, Republic of" = "República de Moldova"; "Monaco" = "Mónaco"; "Mongolia" = "Mongolia"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Marruecos"; "Mozambique" = "Mozambique"; "Myanmar" = "Myanmar"; "Name" = "Nombre"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Países Bajos"; "Network" = "Red"; "Network Printer" = "Impresora de red"; "Networking" = "Redes"; "New Caledonia" = "Nueva Caledonia"; "New Zealand" = "Nueva Zelandia"; "Nicaragua" = "Nicaragua"; "Niger" = "Níger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "No hay configuración de impresora predeterminada."; "No jobs in history." = "No hay trabajos en la historia."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "North Macedonia"; "Northern Mariana Islands" = "Islas Marianas del Norte"; "Norway" = "Noruega"; "Not set" = "No está listo."; "Off" = "Apagado"; "Offset" = "Offset"; "Oman" = "Omán"; "Options:" = "Opciones:"; "Organization" = "Organización"; "Organization Name" = "Nombre de la Organización"; "Other Settings" = "Otras configuraciones"; "Pakistan" = "Pakistán"; "Palau" = "Palau"; "Palestine, State of" = "Palestina, Estado de Palestina"; "Panama" = "Panamá"; "Papua New Guinea" = "Papua Nueva Guinea"; "Paraguay" = "Paraguay"; "Password" = "Contraseña"; "Password changed." = "La contraseña cambió."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "La contraseña debe tener al menos ocho caracteres de largo y contener al menos una letra mayúscula, una letra minúscula y un dígito."; "Passwords do not match." = "Las contraseñas no coinciden."; "Pause Printing" = "Impresión de pausa"; "Peru" = "Perú"; "Philippines" = "Philippines"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Por favor introduzca un nombre de host o dirección IP para la impresora."; "Please enter a printer name." = "Por favor, introduzca un nombre de impresora."; "Please select a device." = "Por favor, seleccione un dispositivo."; "Please select a driver." = "Por favor, seleccione un conductor."; "Please select a valid log level." = "Seleccione un nivel de registro válido."; "Poland" = "Polonia"; "Portrait" = "Retrato"; "Portugal" = "Portugal"; "Primary DNS" = "DNS principal"; "Print Group" = "Print Group"; "Print Test Page" = "Página de prueba de impresión"; "Print job options:" = "Opciones de trabajo para imprimir:"; "Printer identified." = "Impresora identificada."; "Printer is currently active." = "La impresora está activa."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Los nombres de las impresoras deben comenzar con una letra o subrayar y no pueden contener caracteres especiales."; "Printer options:" = "Opciones de impresión:"; "Printer paused." = "La impresora se detuvo."; "Printer pausing." = "Impresora pausando."; "Printer resuming." = "Reanuda la impresora."; "Printers" = "Impresoras"; "Printing Defaults" = "Impresos"; "Puerto Rico" = "Puerto Rico"; "Qatar" = "Qatar"; "Queued %s" = "En espera %s"; "Release Held New Jobs" = "Liberación de nuevos puestos de trabajo"; "Release Job" = "Liberar el trabajo"; "Released held new jobs." = "Se han reanudado los nuevos trabajos en pausa."; "Reprint Job" = "Reprint Job"; "Reprinted job." = "Trabajo reeditado."; "Resume Printing" = "Resume Printing"; "Reverse Landscape" = "Paisaje inverso"; "Reverse Portrait" = "Retrato inverso"; "Romania" = "Rumania"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Corriendo, %s desde %s %s ."; "Russian Federation" = "Russian Federation"; "Rwanda" = "Rwanda"; "Réunion" = "Corrección"; "Saint Barthélemy" = "Saint Barthlemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Santa Elena, Ascensión y Tristán da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts y Nevis"; "Saint Lucia" = "Santa Lucía"; "Saint Martin (French part)" = "Saint Martin (parte francesa)"; "Saint Pierre and Miquelon" = "Saint Pierre y Miquelon"; "Saint Vincent and the Grenadines" = "San Vicente y las Granadinas"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Santo Tomé y Príncipe"; "Saudi Arabia" = "Arabia Saudita"; "Save Changes" = "Guardar cambios"; "Secondary DNS" = "DNS secundarias"; "Security" = "Seguridad"; "Select Driver" = "Select Driver"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "El servidor no está funcionando."; "Set Access Password" = "Establecer contraseña"; "Set as Default" = "Set as Default"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leona"; "Singapore" = "Singapur"; "Sint Maarten (Dutch part)" = "Sint Maarten (parte holandesa)"; "Slovakia" = "Eslovaquia"; "Slovenia" = "Eslovenia"; "Solomon Islands" = "Islas Salomón"; "Somalia" = "Somalia"; "South Africa" = "Sudáfrica"; "South Georgia and the South Sandwich Islands" = "South Georgia and the South Sandwich Islands"; "South Sudan" = "Sudán del Sur"; "Spain" = "España"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Empezó %s"; "Status" = "Situación"; "Sub-commands:" = "Subcomandantes:"; "Sudan" = "Sudán"; "Supplies" = "Suministros"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard y Jan Mayen"; "Sweden" = "Suecia"; "Switzerland" = "Suiza"; "Syrian Arab Republic" = "República Árabe Siria"; "Taiwan, Province of China" = "Taiwán, Provincia de China"; "Tajikistan" = "Tayikistán"; "Tanzania, United Republic of" = "República Unida de Tanzanía"; "Test page printed." = "Ficha de prueba impresa."; "Thailand" = "Tailandia"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Este formulario crea una solicitud de firma de certificados (CSR) que puede enviar a una Autoridad de Certificados (CA) para obtener un certificado TLS de confianza. La clave privada se guarda por separado para su uso con el certificado que obtiene de la CA."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Este formulario crea un nuevo certificado TLS auto-firmado para impresión segura. Los navegadores web no confían automáticamente certificados auto-firmados."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Este formulario instalará un certificado TLS de confianza que haya obtenido de una Autoridad de Certificados (CA.) Una vez instalado, se utilizará inmediatamente."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad y Tabago"; "Tunisia" = "Túnez"; "Turkey" = "Turquía"; "Turkmenistan" = "Turkmenistán"; "Turks and Caicos Islands" = "Islas Turcas y Caicos"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ucrania"; "Unable to access test print file." = "Incapaz de acceder al archivo de impresión de prueba."; "Unable to copy print job." = "Incapaz de copiar el trabajo de impresión."; "Unable to create certificate request." = "Incapaz de crear solicitud de certificado."; "Unable to create certificate." = "Incapaz de crear certificado."; "Unable to create test print job." = "Incapaz de crear trabajo de impresión de prueba."; "Unable to identify printer." = "Incapaz de identificar la impresora."; "Unable to lookup address." = "Incapaz de buscar la dirección."; "Unable to use that driver." = "Incapaz de usar ese conductor."; "United Arab Emirates" = "Emiratos Árabes Unidos"; "United Kingdom" = "Reino Unido"; "United Kingdom of Great Britain and Northern Ireland" = "Reino Unido de Gran Bretaña e Irlanda del Norte"; "United States Minor Outlying Islands" = "Islas Menores de los Estados Unidos"; "United States of America" = "Estados Unidos de América"; "Unknown" = "Desconocida"; "Unknown action." = "Acción desconocida."; "Unknown form action." = "Acción de forma desconocida."; "Unknown form request." = "Solicitud de formulario desconocido."; "Updating Network Configuration" = "Actualizar la configuración de red"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Usar mi posición"; "Users" = "Usuarios"; "Uzbekistan" = "Uzbekistán"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (República Bolivariana de)"; "Version %s" = "Versión %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "Ver los registros"; "Virgin Islands (British)" = "Islas Vírgenes (British)"; "Virgin Islands (U.S.)" = "Islas Vírgenes (U.S)"; "Wallis and Futuna" = "Wallis y Futuna"; "Warning" = "Advertencia"; "Western Sahara" = "Sáhara Occidental"; "Wi-Fi Configuration" = "Configuración Wi-Fi"; "Wi-Fi Network" = "Wi-Fi Network"; "Width" = "Width"; "Wrong old password." = "contraseña vieja incorrecta."; "Yemen" = "Yemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "en %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Número de copias"; "default printer" = "impresora predeterminada"; "finishings" = "Acabado"; "finishings.10" = "Fold"; "finishings.100" = "Z plegable"; "finishings.101" = "Ingeniería Z plegable"; "finishings.11" = "Corte"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Parte superior izquierda"; "finishings.21" = "Fondo básico izquierdo"; "finishings.22" = "Parte superior derecha"; "finishings.23" = "Parte inferior derecha"; "finishings.24" = "Punto izquierdo"; "finishings.25" = "Parte superior"; "finishings.26" = "Sutura de borde derecha"; "finishings.27" = "Parte inferior de la puntada"; "finishings.28" = "2 grapas a la izquierda"; "finishings.29" = "2 grapas en la parte superior"; "finishings.3" = "Ninguno"; "finishings.30" = "2 grapas a la derecha"; "finishings.31" = "2 grapas en la parte inferior"; "finishings.32" = "3 grapas a la izquierda"; "finishings.33" = "3 grapas en la parte superior"; "finishings.34" = "3 grapas a la derecha"; "finishings.35" = "3 grapas en la parte inferior"; "finishings.4" = "Grado"; "finishings.5" = "Punch"; "finishings.50" = "Bind izquierda"; "finishings.51" = "Parte superior"; "finishings.52" = "Apunta derecho"; "finishings.53" = "Parte inferior"; "finishings.6" = "Cubierta"; "finishings.60" = "Cortar después de cada página"; "finishings.61" = "Corte después de cada documento"; "finishings.62" = "Corte después de cada set"; "finishings.63" = "Cortar después del trabajo"; "finishings.7" = "Bind"; "finishings.70" = "Punch superior izquierdo"; "finishings.71" = "Punch inferior izquierdo"; "finishings.72" = "Punch superior derecho"; "finishings.73" = "Punch fondo derecho"; "finishings.74" = "2-hole punch left"; "finishings.75" = "Top de 2 agujeros"; "finishings.76" = "2 agujeros derecho"; "finishings.77" = "Parte inferior de 2 agujeros"; "finishings.78" = "3-hole punch left"; "finishings.79" = "Top de 3 hoyos"; "finishings.8" = "Sutura de asiento"; "finishings.80" = "3 agujeros derecho"; "finishings.81" = "3-hole punch bottom"; "finishings.82" = "4-hole punch left"; "finishings.83" = "Top de 4 agujeros"; "finishings.84" = "4 agujeros derecho"; "finishings.85" = "4 agujeros abajo"; "finishings.86" = "Golpe de agujero múltiple izquierda"; "finishings.87" = "Top de perforación de agujeros múltiples"; "finishings.88" = "Multi-hole punch right"; "finishings.89" = "Fondo de perforación de agujeros múltiples"; "finishings.9" = "Sutura de borde"; "finishings.90" = "Pliegue de acordeón"; "finishings.91" = "Doble puerta"; "finishings.92" = "Puerta plegable"; "finishings.93" = "Media pliegue"; "finishings.94" = "Media Z plegable"; "finishings.95" = "Puerta izquierda"; "finishings.96" = "Carta plegable"; "finishings.97" = "Pliegue paralelo"; "finishings.98" = "Cargador"; "finishings.99" = "Puerta derecha"; "holding new jobs" = "ocupar nuevos puestos"; "job-state-reasons.aborted-by-system" = "Para."; "job-state-reasons.compression-error" = "Error de descompresión."; "job-state-reasons.document-format-error" = "Error de formato de documento."; "job-state-reasons.document-password-error" = "Error de contraseña de documento."; "job-state-reasons.document-permission-error" = "Error de permiso de documento."; "job-state-reasons.document-unprintable-error" = "Documente error imprimible."; "job-state-reasons.errors-detected" = "Errores detectados."; "job-state-reasons.job-canceled-at-device" = "Cancelado en la impresora."; "job-state-reasons.job-canceled-by-user" = "Cancelado por el usuario."; "job-state-reasons.job-completed-successfully" = "Impresión."; "job-state-reasons.job-completed-with-errors" = "Imprimido con errores."; "job-state-reasons.job-completed-with-warnings" = "Imprimido con advertencias."; "job-state-reasons.job-data-insufficient" = "Datos insuficientes."; "job-state-reasons.job-fetchable" = "Increíble."; "job-state-reasons.job-incoming" = "Entrando."; "job-state-reasons.job-printing" = "Impresión."; "job-state-reasons.job-queued" = "Preparando para imprimir."; "job-state-reasons.job-spooling" = "Compartir."; "job-state-reasons.none" = "Esperando."; "job-state-reasons.printer-stopped" = "Impresora fuera de línea."; "job-state-reasons.printer-stopped-partly" = "La impresora paró parcialmente."; "job-state-reasons.processing-to-stop-point" = "Para."; "job-state-reasons.queued-in-device" = "Listo."; "job-state-reasons.warnings-detected" = "Advertencias detectadas."; "job-state.3" = "Pendiente"; "job-state.4" = "Soldado"; "job-state.5" = "Procesamiento"; "job-state.6" = "Detenido"; "job-state.7" = "Cancelado"; "job-state.8" = "Abortados"; "job-state.9" = "Completado"; "joining" = "unirse"; "media" = "Media"; "media-col" = "Media"; "media-size" = "Tamaño de los medios"; "media-size-name" = "Tamaño de los medios"; "media-source" = "Input Tray"; "media-source.alternate" = "Suplente"; "media-source.alternate-roll" = "Rollo alternativo"; "media-source.auto" = "Automático"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Bandera multiusos"; "media-source.center" = "Center"; "media-source.disc" = "Disco"; "media-source.envelope" = "Envelope"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Gran capacidad"; "media-source.left" = "Izquierda"; "media-source.main" = "Main"; "media-source.main-roll" = "Rollo principal"; "media-source.manual" = "Manual"; "media-source.middle" = "Medio ambiente"; "media-source.photo" = "Foto"; "media-source.rear" = "Rear"; "media-source.right" = "Bien."; "media-source.roll-1" = "Rollo 1"; "media-source.roll-10" = "Rollo 10"; "media-source.roll-2" = "Rollo 2"; "media-source.roll-3" = "Rollo 3"; "media-source.roll-4" = "Rollo 4"; "media-source.roll-5" = "Rollo 5"; "media-source.roll-6" = "Rollo 6"; "media-source.roll-7" = "Rollo 7"; "media-source.roll-8" = "Rollo 8"; "media-source.roll-9" = "Rollo 9"; "media-source.side" = "Lado"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Seguimiento de medios"; "media-tracking.continuous" = "Continua"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Tipo de medio"; "media-type.aluminum" = "Aluminio"; "media-type.auto" = "Automático"; "media-type.back-print-film" = "Imágenes de impresión"; "media-type.cardboard" = "Cartón"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continua"; "media-type.continuous-long" = "Extremo continuo"; "media-type.continuous-short" = "corto continuo"; "media-type.corrugated-board" = "Tablero ondulado"; "media-type.disc" = "Disco óptico"; "media-type.disc-glossy" = "Disco óptico brillante"; "media-type.disc-high-gloss" = "Disco óptico de alto brillo"; "media-type.disc-matte" = "Disco óptico mate"; "media-type.disc-satin" = "Disco óptico Satin"; "media-type.disc-semi-gloss" = "Disco óptico semi-gloss"; "media-type.double-wall" = "Doble pared"; "media-type.dry-film" = "Cine seco"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Incrustación de láminas"; "media-type.end-board" = "Junta final"; "media-type.envelope" = "Envelope"; "media-type.envelope-archival" = "Sobre Archival"; "media-type.envelope-bond" = "Envoltorio de huesos"; "media-type.envelope-coated" = "Sobre coado"; "media-type.envelope-cotton" = "Sobre de algodón"; "media-type.envelope-fine" = "Envoltura fina"; "media-type.envelope-heavyweight" = "Sobres pesados"; "media-type.envelope-inkjet" = "Sobre de inyección de tinta"; "media-type.envelope-lightweight" = "Sobre ligero"; "media-type.envelope-plain" = "Envoltura plana"; "media-type.envelope-preprinted" = "Sobre impreso"; "media-type.envelope-window" = "Sobre ventana"; "media-type.fabric" = "Tejido"; "media-type.fabric-archival" = "Tejido de arquitectura"; "media-type.fabric-glossy" = "Tela brillante"; "media-type.fabric-high-gloss" = "Tejido alto brillo"; "media-type.fabric-matte" = "Tejido mate"; "media-type.fabric-semi-gloss" = "Tejido semi-gloss"; "media-type.fabric-waterproof" = "Tejido impermeable"; "media-type.film" = "Film"; "media-type.flexo-base" = "Base flexible"; "media-type.flexo-photo-polymer" = "Polómero de foto Flexo"; "media-type.flute" = "Fluido"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "pestañas de corte completo"; "media-type.glass" = "Cristal"; "media-type.glass-colored" = "Color de vidrio"; "media-type.glass-opaque" = "Opaque de vidrio"; "media-type.glass-surfaced" = "Vidrio en superficie"; "media-type.glass-textured" = "Textura de vidrio"; "media-type.gravure-cylinder" = "Cilindro de gravure"; "media-type.image-setter-paper" = "Papel de setter de imagen"; "media-type.imaging-cylinder" = "Cilindro de imagen"; "media-type.labels" = "Etiquetas"; "media-type.labels-colored" = "Etiquetas de colores"; "media-type.labels-glossy" = "Etiquetas brillantesy"; "media-type.labels-high-gloss" = "Altas etiquetas de brillo"; "media-type.labels-inkjet" = "Etiquetas de inyección de tinta"; "media-type.labels-matte" = "Etiquetas de la materia"; "media-type.labels-permanent" = "Etiquetas permanentes"; "media-type.labels-satin" = "Etiquetas Satin"; "media-type.labels-security" = "Etiquetas de seguridad"; "media-type.labels-semi-gloss" = "Etiquetas semi-gloss"; "media-type.laminating-foil" = "Laminating foil"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal brillante"; "media-type.metal-high-gloss" = "Metal alto brillo"; "media-type.metal-matte" = "Matte de metal"; "media-type.metal-satin" = "Metal satinado"; "media-type.metal-semi-gloss" = "Metal semi brillo"; "media-type.mounting-tape" = "Cinta de montaje"; "media-type.multi-layer" = "Multi capa"; "media-type.multi-part-form" = "Forma de múltiples piezas"; "media-type.other" = "Otros"; "media-type.paper" = "Documento"; "media-type.photographic" = "Papel fotográfico"; "media-type.photographic-archival" = "Archivo fotográfico"; "media-type.photographic-film" = "Cine fotográfico"; "media-type.photographic-glossy" = "Papel fotográfico brillante"; "media-type.photographic-high-gloss" = "Papel fotográfico alto brillo"; "media-type.photographic-matte" = "Papel fotográfico mate"; "media-type.photographic-satin" = "Papel fotográfico Satin"; "media-type.photographic-semi-gloss" = "Papel fotográfico semi-gloss"; "media-type.plastic" = "Plástico"; "media-type.plastic-archival" = "Archivo de plástico"; "media-type.plastic-colored" = "Color de plástico"; "media-type.plastic-glossy" = "Plástico brillante"; "media-type.plastic-high-gloss" = "Plástico alto brillo"; "media-type.plastic-matte" = "Aparato plástico"; "media-type.plastic-satin" = "satinado plástico"; "media-type.plastic-semi-gloss" = "Plástico semi brillante"; "media-type.plate" = "Placa"; "media-type.polyester" = "Poliéster"; "media-type.pre-cut-tabs" = "pestañas de corte pre"; "media-type.roll" = "Roll"; "media-type.screen" = "Pantalla"; "media-type.screen-paged" = "Paged"; "media-type.self-adhesive" = "Auto adhesivo"; "media-type.self-adhesive-film" = "Película autoadhesiva"; "media-type.shrink-foil" = "Barbacoa"; "media-type.single-face" = "Cara individual"; "media-type.single-wall" = "Pared individual"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Papelería"; "media-type.stationery-archival" = "Archivo de papelería"; "media-type.stationery-coated" = "Papel coado"; "media-type.stationery-cotton" = "Algodón de papelería"; "media-type.stationery-fine" = "Papel de aluminio"; "media-type.stationery-heavyweight" = "Papel pesado"; "media-type.stationery-heavyweight-coated" = "Papelería pesada recubierto"; "media-type.stationery-inkjet" = "Papel de inyección de tinta"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Papel ligero"; "media-type.stationery-preprinted" = "Papel impreso"; "media-type.stationery-prepunched" = "Papel picado"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transferencia"; "media-type.transparency" = "Transparencia"; "media-type.triple-wall" = "Triple pared"; "media-type.wet-film" = "Película húmeda"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 o US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Envelope"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Envelope"; "media.iso_c10_28x40mm" = "C10 Envelope"; "media.iso_c1_648x917mm" = "C1 Envelope"; "media.iso_c2_458x648mm" = "C2 Envelope"; "media.iso_c3_324x458mm" = "C3 Envelope"; "media.iso_c4_229x324mm" = "C4 Envelope"; "media.iso_c5_162x229mm" = "C5 Envelope"; "media.iso_c6_114x162mm" = "C6 Envelope"; "media.iso_c6c5_114x229mm" = "C6/C5 Envelope"; "media.iso_c7_81x114mm" = "C7 Envelope"; "media.iso_c7c6_81x162mm" = "C7/C6 Envelope"; "media.iso_c8_57x81mm" = "C8 Envelope"; "media.iso_c9_40x57mm" = "C9 Envelope"; "media.iso_dl_110x220mm" = "DL Envelope"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Envelope Chou 2"; "media.jpn_chou3_120x235mm" = "Envelope Chou 3"; "media.jpn_chou40_90x225mm" = "Envelope Chou 40"; "media.jpn_chou4_90x205mm" = "Envelope Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Envelope Kahu"; "media.jpn_kaku2_240x332mm" = "Envelope Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Responder Postcard"; "media.jpn_you4_105x235mm" = "Envelope Tú 4"; "media.na_a2_4.375x5.75in" = "Envelope A2"; "media.na_c5_6.5x9.5in" = "Envelope C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "US Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "Estado"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "Carta de los Estados Unidos (Extra)"; "media.na_letter-plus_8.5x12.69in" = "Carta de los Estados Unidos (Plus)"; "media.na_letter_8.5x11in" = "Carta de los Estados Unidos"; "media.na_monarch_3.875x7.5in" = "Envelope Monarch"; "media.na_number-10_4.125x9.5in" = "Envelope #10"; "media.na_number-11_4.5x10.375in" = "Envelope #11"; "media.na_number-12_4.75x11in" = "Envelope #12"; "media.na_number-14_5x11.5in" = "Envelope #14"; "media.na_number-9_3.875x8.875in" = "Envelope #9"; "media.na_personal_3.625x6.5in" = "Envelope Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (especial)"; "media.om_invite_220x220mm" = "Invitación de Envelope"; "media.om_italian_110x230mm" = "Envelope Italian"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275 mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180 mm"; "media.om_pa-kai_267x389mm" = "267 x 389m m"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Envelope chinese #10"; "media.prc_16k_146x215mm" = "Chino 16k"; "media.prc_1_102x165mm" = "Envelope chinese #1"; "media.prc_2_102x176mm" = "Envelope chinese #2"; "media.prc_32k_97x151mm" = "Chino 32k"; "media.prc_3_125x176mm" = "Envelope chinese #3"; "media.prc_4_110x208mm" = "Envelope chinese #4"; "media.prc_5_110x220mm" = "Envelope chinese #5"; "media.prc_6_120x320mm" = "Envelope chinese #6"; "media.prc_7_160x230mm" = "Envelope chinese #7"; "media.prc_8_120x309mm" = "Envelope chinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "no configurado"; "not visible" = "no visible"; "off" = "apagado"; "on" = "on"; "orientation-requested" = "Orientación"; "orientation-requested.3" = "Retrato"; "orientation-requested.4" = "Paisaje"; "orientation-requested.5" = "Paisaje inverso"; "orientation-requested.6" = "Retrato inverso"; "orientation-requested.7" = "Ninguno"; "output-bin" = "Output Tray"; "output-bin.auto" = "Automático"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Cara abajo."; "output-bin.face-up" = "Cara arriba"; "output-bin.large-capacity" = "Gran capacidad"; "output-bin.left" = "Izquierda"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Medio ambiente"; "output-bin.my-mailbox" = "Mi buzón de correo"; "output-bin.rear" = "Rear"; "output-bin.right" = "Bien."; "output-bin.side" = "Lado"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Modo de impresión"; "print-color-mode.auto" = "Automático"; "print-color-mode.auto-monochrome" = "Auto monocromo"; "print-color-mode.bi-level" = "Texto"; "print-color-mode.color" = "Color"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monocromo"; "print-color-mode.process-bi-level" = "Texto del proceso"; "print-color-mode.process-monochrome" = "Proceso monocromo"; "print-content-optimize" = "Optimize For"; "print-content-optimize.auto" = "Automático"; "print-content-optimize.graphic" = "Gráficos"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Texto"; "print-content-optimize.text-and-graphic" = "Texto y gráficos"; "print-darkness" = "Imprimir Oscuridad"; "print-quality" = "Calidad de impresión"; "print-quality.3" = "Proyecto"; "print-quality.4" = "Normal"; "print-quality.5" = "Mejor"; "print-scaling" = "Escalada"; "print-scaling.auto" = "Automático"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Relleno"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "Ninguno"; "print-speed" = "Velocidad de impresión"; "printer-resolution" = "Resolución"; "printer-state-reasons.cover-open" = "Cubierta abierta."; "printer-state-reasons.door-open" = "Puerta abierta."; "printer-state-reasons.identify-printer-requested" = "Identifique la impresora."; "printer-state-reasons.input-tray-missing" = "Falta la bandeja de papel."; "printer-state-reasons.marker-supply-empty" = "De tinta."; "printer-state-reasons.marker-supply-low" = "Tinta baja."; "printer-state-reasons.marker-waste-almost-full" = "La basura casi llena."; "printer-state-reasons.marker-waste-full" = "basura llena."; "printer-state-reasons.media-empty" = "De papel."; "printer-state-reasons.media-jam" = "Mermelada de papel."; "printer-state-reasons.media-low" = "Reemplaza el papel pronto."; "printer-state-reasons.media-needed" = "Papel de carga."; "printer-state-reasons.none" = "Listo."; "printer-state-reasons.offline" = "Sin conexión."; "printer-state-reasons.other" = "Ver la impresora."; "printer-state-reasons.spool-area-full" = "Impresora ocupada."; "printer-state-reasons.toner-empty" = "Fuera de toner."; "printer-state-reasons.toner-low" = "Toner bajo."; "printer-state.3" = "Idle"; "printer-state.4" = "Procesamiento"; "printer-state.5" = "Detenido"; "sides" = "Impresión de 2 asientos"; "sides.one-sided" = "Fuera."; "sides.two-sided-long-edge" = "En (portrait)"; "sides.two-sided-short-edge" = "En (paisaje)"; "unable to join" = "incapaz de unirse"; "yesterday at %02d:%02d:%02d" = "ayer a las %02d:%02d:%02d"; "Åland Islands" = "Islas"; pappl-1.4.9/pappl/strings/es_strings.h000066400000000000000000001603101476704353100200120ustar00rootroot00000000000000static const char *es_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Cancelar todos los trabajos (cancelar).\";\n" "\" -c COPIES\" = \" -c COPIAS\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Especifique la impresora.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Especifique el ID de trabajo (cancel.)\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Especificar controlador (add/modify.)\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Especifique el número de copias (presente.)\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (por defecto)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=VALUE Especifique la opción (add,modify,server,submit.)\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 a 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 a 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-locations='LOCATION\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZACIÓN\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Especifique ipp: o ipps: impresora/servidor.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Especifique el socket: o usb: dispositivo (add/modify.)\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Añadir una impresora.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Agregue automáticamente impresoras compatibles.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Cancelar uno o más trabajos.\";\n" "\" default Set the default printer.\" = \" default Establecer la impresora predeterminada.\";\n" "\" delete Delete a printer.\" = \" delete Eliminar una impresora.\";\n" "\" devices List devices.\" = \" devices Dispositivos Listos.\";\n" "\" drivers List drivers.\" = \"conductores List drivers.\";\n" "\" jobs List jobs.\" = \" jobs Empleo Listos.\";\n" "\" modify Modify a printer.\" = \" modify Modifique una impresora.\";\n" "\" options List printer options.\" = \" options Listar opciones de impresora.\";\n" "\" pause Pause printing for a printer.\" = \" pause Impresión de pausa para una impresora.\";\n" "\" printers List printers.\" = \" printers Lista de impresoras.\";\n" "\" resume Resume printing for a printer.\" = \" resume Resumir la impresión para una impresora.\";\n" "\" server Run a server.\" = \" server Ejecute un servidor.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Apaga un servidor en funcionamiento.\";\n" "\" status Show server/printer/job status.\" = \" status Mostrar el estado del servidor/printer/job.\";\n" "\" submit Submit a file for printing.\" = \" submit Enviar un archivo para imprimir.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"hace %d días a las %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d pulgadas/sec\";\n" "\"%d job\" = \"%d trabajo\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%d dpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g \\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s ( %s %s )\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) de %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Media\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Mal valor de puerto de servidor.\";\n" "\"%s: Bad job ID.\" = \"Mala identificación de trabajo.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Bad printer URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: No se puede especificar más de un sub-command.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Archivo de impresión vacío recibido en la entrada estándar.\";\n" "\"%s: Failed to create a system.\" = \"%s: Failed to create a system.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"Desaparecido '-d PRINTER. '\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"Perdiendo mi ADN. '\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"- Perdiendo a la policía. '\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Una copia perdida cuenta después de -n.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Dispositivo perdido URI después de -v.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Falta el nombre del conductor después de -m.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Desapareciendo el nombre de archivo después de '--'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Desapareciendo el nombre de host después de -h.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Falta de identificación de trabajo después de -j.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: opción oscurecer después de -o.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Impresora desaparecida URI después de -u.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Falta el nombre de la impresora después de -d.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Falta espacio después de -o.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Perder el título después de -t.\";\n" "\"%s: No default printer available.\" = \"%s: No hay impresora predeterminada disponible.\";\n" "\"%s: No files to print.\" = \"%s: No hay archivos que imprimir.\";\n" "\"%s: Server is not running.\" = \"%s: El servidor no está funcionando.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Sub-command '%s' no acepta archivos.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Autoadd subcommand no es compatible.\";\n" "\"%s: Too many files.\" = \"%s: Demasiados archivos.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Incapaz de acceder a '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Incapaz de añadir la impresora: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Incapaz de cancelar el trabajo: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Incapaz de conectarse a la impresora en '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Incapaz de conectarse al servidor: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Incapaz de crear un archivo temporal: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Incapaz de eliminar la impresora: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: No se pueden obtener los dispositivos disponibles: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Incapaz de obtener información para '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Incapaz de obtener información para la impresora: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Incapaz de obtener opciones de impresora: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Incapaz de modificar la impresora: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Incapacidad para detener la impresora: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Incapaz de imprimir '%s': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Incapaz de reanudar la impresora: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Incapaz de configurar la impresora predeterminada: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Incapaz de apagar el servidor: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Incapaz de iniciar servidor: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Incapaz de escribir al archivo temporal: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Opción desconocida '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Opción desconocida '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Unknown sub-command '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Unsupported URI scheme '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Advertencia - las credenciales del usuario no son compatibles con URIs.\";\n" "\", Borderless\" = \", sin fronteras\";\n" "\"A printer with that name already exists.\" = \"Una impresora con ese nombre ya existe.\";\n" "\"Aborted %s\" = \"Abortado %s\";\n" "\"Add Printer\" = \"Añadir impresora\";\n" "\"Admin Group\" = \"Admin Group\";\n" "\"Afghanistan\" = \"Afganistán\";\n" "\"Albania\" = \"Albania\";\n" "\"Algeria\" = \"Argelia\";\n" "\"American Samoa\" = \"Samoa Americana\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguila\";\n" "\"Antarctica\" = \"Antártida\";\n" "\"Antigua and Barbuda\" = \"Antigua y Barbuda\";\n" "\"Argentina\" = \"Argentina\";\n" "\"Armenia\" = \"Armenia\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australia\";\n" "\"Austria\" = \"Austria\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Auto-Detect Driver\";\n" "\"Azerbaijan\" = \"Azerbaiyán\";\n" "\"Bad administration group.\" = \"Grupo de mala administración.\";\n" "\"Bad port number.\" = \"Mal número de puerto.\";\n" "\"Bad print group.\" = \"Grupo de impresión malo.\";\n" "\"Bad printer defaults.\" = \"Impresoras malas.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahrein\";\n" "\"Bangladesh\" = \"Bangladesh\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Belarús\";\n" "\"Belgium\" = \"Bélgica\";\n" "\"Belize\" = \"Belice\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermudas\";\n" "\"Bhutan\" = \"Bhután\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivia (Estado Plurinacional de)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius y Saba\";\n" "\"Borderless\" = \"Sin fronteras\";\n" "\"Bosnia and Herzegovina\" = \"Bosnia y Herzegovina\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Bouvet Island\";\n" "\"Brazil\" = \"Brasil\";\n" "\"British Indian Ocean Territory\" = \"British Indian Ocean Territory\";\n" "\"Brunei Darussalam\" = \"Brunei Darussalam\";\n" "\"Bulgaria\" = \"Bulgaria\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cabo Verde\";\n" "\"Cambodia\" = \"Camboya\";\n" "\"Cameroon\" = \"Camerún\";\n" "\"Canada\" = \"Canadá\";\n" "\"Cancel All Jobs\" = \"Cancelar Todos los trabajos\";\n" "\"Cancel Job\" = \"Cancelar trabajo\";\n" "\"Canceled %s\" = \"Cancelado %s\";\n" "\"Canceling\" = \"Cancelación\";\n" "\"Cayman Islands\" = \"Islas Caimán\";\n" "\"Central African Republic\" = \"República Centroafricana\";\n" "\"Certificate created.\" = \"Certificado creado.\";\n" "\"Certificate installed.\" = \"Certificado instalado.\";\n" "\"Certificate request created.\" = \"Solicitud de certificado creada.\";\n" "\"Chad\" = \"Chad\";\n" "\"Change Access Password\" = \"Cambiar contraseña\";\n" "\"Change Log Level\" = \"Nivel de registro de cambios\";\n" "\"Change Network Settings\" = \"Cambiar la configuración de la red\";\n" "\"Change Wi-Fi Network\" = \"Cambiar red Wi-Fi\";\n" "\"Changes Saved.\" = \"Cambios guardados.\";\n" "\"Changes saved.\" = \"Cambios salvados.\";\n" "\"Chile\" = \"Chile\";\n" "\"China\" = \"China\";\n" "\"Christmas Island\" = \"Isla de Navidad\";\n" "\"City/Locality\" = \"Ciudad/Localidad\";\n" "\"Cocos (Keeling) Islands\" = \"Islas Cocos (Keeling)\";\n" "\"Colombia\" = \"Colombia\";\n" "\"Comoros\" = \"Comoras\";\n" "\"Completed %s\" = \"Completado %s\";\n" "\"Configuration\" = \"Configuración\";\n" "\"Configure Media\" = \"Configure Media\";\n" "\"Confirm Cancel All\" = \"Confirmación Todos\";\n" "\"Confirm Delete Printer\" = \"Confirmar la impresora\";\n" "\"Congo\" = \"Congo\";\n" "\"Congo, Democratic Republic of the\" = \"Congo, República Democrática del Congo\";\n" "\"Contact\" = \"Contacto\";\n" "\"Cook Islands\" = \"Islas Cook\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Crear solicitud de registro de certificados\";\n" "\"Create New Certificate\" = \"Crear nuevo certificado\";\n" "\"Create New TLS Certificate\" = \"Crear nuevo certificado TLS\";\n" "\"Create TLS Certificate Request\" = \"Crear TLS Solicitud de certificado\";\n" "\"Croatia\" = \"Croacia\";\n" "\"Cuba\" = \"Cuba\";\n" "\"Curaçao\" = \"Curaao\";\n" "\"Current Password\" = \"Contraseña actual\";\n" "\"Custom Size\" = \"Tamaño personalizado\";\n" "\"Cyprus\" = \"Chipre\";\n" "\"Czechia\" = \"Czechia\";\n" "\"Côte d'Ivoire\" = \"Cte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP con dirección manual\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Nombre del servicio\";\n" "\"Debugging\" = \"Debugging\";\n" "\"Default printer set.\" = \"Juego de impresora predeterminado.\";\n" "\"Delete\" = \"Suprimir\";\n" "\"Delete Printer\" = \"Eliminar la impresora\";\n" "\"Denmark\" = \"Dinamarca\";\n" "\"Djibouti\" = \"Djibouti\";\n" "\"Domain Name\" = \"Nombre del dominio\";\n" "\"Dominica\" = \"Dominica\";\n" "\"Dominican Republic\" = \"República Dominicana\";\n" "\"Download Certificate Request File\" = \"Descargar certificado Solicitar archivo\";\n" "\"Ecuador\" = \"Ecuador\";\n" "\"Egypt\" = \"Egipto\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Guinea Ecuatorial\";\n" "\"Eritrea\" = \"Eritrea\";\n" "\"Errors\" = \"Errores\";\n" "\"Estonia\" = \"Estonia\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Etiopía\";\n" "\"Falkland Islands (Malvinas)\" = \"Islas Malvinas (Falkland Islands)\";\n" "\"Faroe Islands\" = \"Islas Feroe\";\n" "\"Fatal Errors/Conditions\" = \"Errores/Condiciones fatales\";\n" "\"Fiji\" = \"Fiji\";\n" "\"Finland\" = \"Finlandia\";\n" "\"France\" = \"Francia\";\n" "\"French Guiana\" = \"Guayana Francesa\";\n" "\"French Polynesia\" = \"Polinesia Francesa\";\n" "\"French Southern Territories\" = \"Territorios del Sur\";\n" "\"Gabon\" = \"Gabón\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Georgia\";\n" "\"Germany\" = \"Alemania\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Grecia\";\n" "\"Greenland\" = \"Groenlandia\";\n" "\"Grenada\" = \"Granada\";\n" "\"Group changes saved.\" = \"Cambios de grupo guardados.\";\n" "\"Guadeloupe\" = \"Guadalupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Guinea\";\n" "\"Guinea-Bissau\" = \"Guinea-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haití\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island y McDonald Islands\";\n" "\"Hidden SSID\" = \"SSID oculto\";\n" "\"Hold Job\" = \"Mantener el empleo\";\n" "\"Hold New Jobs\" = \"Mantener los nuevos empleos\";\n" "\"Holding new jobs.\" = \"Mantener nuevos puestos de trabajo.\";\n" "\"Holy See\" = \"Santa Sede\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Nombre de host\";\n" "\"Human-Readable Location\" = \"Ubicación legible por humanos\";\n" "\"Hungary\" = \"Hungría\";\n" "\"IPv4 Address\" = \"Dirección IPv4\";\n" "\"IPv4 Configuration\" = \"Configuración IPv4\";\n" "\"IPv4 Gateway\" = \"Puerta de enlace IPv4\";\n" "\"IPv4 Netmask\" = \"Máscara de red IPv4\";\n" "\"IPv6 Address\" = \"Direcciones IPv6\";\n" "\"IPv6 Configuration\" = \"Configuración IPv6\";\n" "\"IPv6 Link-Local\" = \"Enlace local IPv6\";\n" "\"IPv6 Prefix Length\" = \"Longitud del prefijo IPv6\";\n" "\"Iceland\" = \"Islandia\";\n" "\"Identify Printer\" = \"Identifique la impresora\";\n" "\"India\" = \"India\";\n" "\"Indonesia\" = \"Indonesia\";\n" "\"Informational\" = \"Información\";\n" "\"Install TLS Certificate\" = \"Instala TLS Certificado\";\n" "\"Invalid IPv4 address.\" = \"Dirección IPv4 incorrecta.\";\n" "\"Invalid IPv4 netmask.\" = \"Máscara de red IPv4 incorrecta.\";\n" "\"Invalid IPv6 address.\" = \"Dirección IPv6 incorrecta.\";\n" "\"Invalid IPv6 prefix length.\" = \"Longitud del prefijo IPv6 incorrecto.\";\n" "\"Invalid Job ID.\" = \"ID de trabajo inválido.\";\n" "\"Invalid certificate or private key.\" = \"Certificado inválido o clave privada.\";\n" "\"Invalid form data.\" = \"Datos de formulario inválidos.\";\n" "\"Invalid form submission.\" = \"Sumisión de formulario inválido.\";\n" "\"Invalid job ID.\" = \"ID de trabajo inválido.\";\n" "\"Invalid network configuration.\" = \"Configuración de red incorrecta.\";\n" "\"Iran (Islamic Republic of)\" = \"Irán (República Islámica del)\";\n" "\"Iraq\" = \"Iraq\";\n" "\"Ireland\" = \"Irlanda\";\n" "\"Isle of Man\" = \"Isla de Man\";\n" "\"Israel\" = \"Israel\";\n" "\"Italy\" = \"Italia\";\n" "\"Jamaica\" = \"Jamaica\";\n" "\"Japan\" = \"Japón\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Job\";\n" "\"Job canceled.\" = \"Trabajo cancelado.\";\n" "\"Job held.\" = \"Puesto ocupado.\";\n" "\"Job released.\" = \"Trabajo liberado.\";\n" "\"Jobs\" = \"Empleo\";\n" "\"Joining Wi-Fi Network\" = \"Unirse a la red Wi-Fi\";\n" "\"Jordan\" = \"Jordania\";\n" "\"Kazakhstan\" = \"Kazajstán\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Corea (República Popular Democrática de)\";\n" "\"Korea, Republic of\" = \"Corea, República de Corea\";\n" "\"Kuwait\" = \"Kuwait\";\n" "\"Kyrgyzstan\" = \"Kirguistán\";\n" "\"Landscape\" = \"Paisaje\";\n" "\"Lao People's Democratic Republic\" = \"República Democrática Popular Lao\";\n" "\"Latvia\" = \"Letonia\";\n" "\"Lebanon\" = \"Líbano\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Nivel\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libia\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Lituania\";\n" "\"Location\" = \"Ubicación\";\n" "\"Log Level\" = \"Nivel de registro\";\n" "\"Logging\" = \"Registro\";\n" "\"Logs\" = \"Logs\";\n" "\"Luxembourg\" = \"Luxemburgo\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagascar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malasia\";\n" "\"Maldives\" = \"Maldivas\";\n" "\"Mali\" = \"Malí\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Configuración manual\";\n" "\"Marshall Islands\" = \"Islas Marshall\";\n" "\"Martinique\" = \"Martinica\";\n" "\"Mauritania\" = \"Mauritania\";\n" "\"Mauritius\" = \"Mauricio\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Media\";\n" "\"Mexico\" = \"México\";\n" "\"Micronesia (Federated States of)\" = \"Micronesia (Estados Federados de)\";\n" "\"Missing action.\" = \"Falta de acción.\";\n" "\"Missing job ID.\" = \"Falta el identificador del trabajo.\";\n" "\"Missing network name.\" = \"Falta el nombre de la red.\";\n" "\"Missing private key.\" = \"Falta la llave privada.\";\n" "\"Moldova, Republic of\" = \"República de Moldova\";\n" "\"Monaco\" = \"Mónaco\";\n" "\"Mongolia\" = \"Mongolia\";\n" "\"Montenegro\" = \"Montenegro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Marruecos\";\n" "\"Mozambique\" = \"Mozambique\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Nombre\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Países Bajos\";\n" "\"Network\" = \"Red\";\n" "\"Network Printer\" = \"Impresora de red\";\n" "\"Networking\" = \"Redes\";\n" "\"New Caledonia\" = \"Nueva Caledonia\";\n" "\"New Zealand\" = \"Nueva Zelandia\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Níger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"No hay configuración de impresora predeterminada.\";\n" "\"No jobs in history.\" = \"No hay trabajos en la historia.\";\n" "\"Norfolk Island\" = \"Norfolk Island\";\n" "\"North Macedonia\" = \"North Macedonia\";\n" "\"Northern Mariana Islands\" = \"Islas Marianas del Norte\";\n" "\"Norway\" = \"Noruega\";\n" "\"Not set\" = \"No está listo.\";\n" "\"Off\" = \"Apagado\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Omán\";\n" "\"Options:\" = \"Opciones:\";\n" "\"Organization\" = \"Organización\";\n" "\"Organization Name\" = \"Nombre de la Organización\";\n" "\"Other Settings\" = \"Otras configuraciones\";\n" "\"Pakistan\" = \"Pakistán\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palestina, Estado de Palestina\";\n" "\"Panama\" = \"Panamá\";\n" "\"Papua New Guinea\" = \"Papua Nueva Guinea\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Contraseña\";\n" "\"Password changed.\" = \"La contraseña cambió.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"La contraseña debe tener al menos ocho caracteres de largo y contener al menos una letra mayúscula, una letra minúscula y un dígito.\";\n" "\"Passwords do not match.\" = \"Las contraseñas no coinciden.\";\n" "\"Pause Printing\" = \"Impresión de pausa\";\n" "\"Peru\" = \"Perú\";\n" "\"Philippines\" = \"Philippines\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Por favor introduzca un nombre de host o dirección IP para la impresora.\";\n" "\"Please enter a printer name.\" = \"Por favor, introduzca un nombre de impresora.\";\n" "\"Please select a device.\" = \"Por favor, seleccione un dispositivo.\";\n" "\"Please select a driver.\" = \"Por favor, seleccione un conductor.\";\n" "\"Please select a valid log level.\" = \"Seleccione un nivel de registro válido.\";\n" "\"Poland\" = \"Polonia\";\n" "\"Portrait\" = \"Retrato\";\n" "\"Portugal\" = \"Portugal\";\n" "\"Primary DNS\" = \"DNS principal\";\n" "\"Print Group\" = \"Print Group\";\n" "\"Print Test Page\" = \"Página de prueba de impresión\";\n" "\"Print job options:\" = \"Opciones de trabajo para imprimir:\";\n" "\"Printer identified.\" = \"Impresora identificada.\";\n" "\"Printer is currently active.\" = \"La impresora está activa.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Los nombres de las impresoras deben comenzar con una letra o subrayar y no pueden contener caracteres especiales.\";\n" "\"Printer options:\" = \"Opciones de impresión:\";\n" "\"Printer paused.\" = \"La impresora se detuvo.\";\n" "\"Printer pausing.\" = \"Impresora pausando.\";\n" "\"Printer resuming.\" = \"Reanuda la impresora.\";\n" "\"Printers\" = \"Impresoras\";\n" "\"Printing Defaults\" = \"Impresos\";\n" "\"Puerto Rico\" = \"Puerto Rico\";\n" "\"Qatar\" = \"Qatar\";\n" "\"Queued %s\" = \"En espera %s\";\n" "\"Release Held New Jobs\" = \"Liberación de nuevos puestos de trabajo\";\n" "\"Release Job\" = \"Liberar el trabajo\";\n" "\"Released held new jobs.\" = \"Se han reanudado los nuevos trabajos en pausa.\";\n" "\"Reprint Job\" = \"Reprint Job\";\n" "\"Reprinted job.\" = \"Trabajo reeditado.\";\n" "\"Resume Printing\" = \"Resume Printing\";\n" "\"Reverse Landscape\" = \"Paisaje inverso\";\n" "\"Reverse Portrait\" = \"Retrato inverso\";\n" "\"Romania\" = \"Rumania\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Corriendo, %s desde %s %s .\";\n" "\"Russian Federation\" = \"Russian Federation\";\n" "\"Rwanda\" = \"Rwanda\";\n" "\"Réunion\" = \"Corrección\";\n" "\"Saint Barthélemy\" = \"Saint Barthlemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Santa Elena, Ascensión y Tristán da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts y Nevis\";\n" "\"Saint Lucia\" = \"Santa Lucía\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (parte francesa)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre y Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"San Vicente y las Granadinas\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Santo Tomé y Príncipe\";\n" "\"Saudi Arabia\" = \"Arabia Saudita\";\n" "\"Save Changes\" = \"Guardar cambios\";\n" "\"Secondary DNS\" = \"DNS secundarias\";\n" "\"Security\" = \"Seguridad\";\n" "\"Select Driver\" = \"Select Driver\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbia\";\n" "\"Server is not running.\" = \"El servidor no está funcionando.\";\n" "\"Set Access Password\" = \"Establecer contraseña\";\n" "\"Set as Default\" = \"Set as Default\";\n" "\"Seychelles\" = \"Seychelles\";\n" "\"Sierra Leone\" = \"Sierra Leona\";\n" "\"Singapore\" = \"Singapur\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (parte holandesa)\";\n" "\"Slovakia\" = \"Eslovaquia\";\n" "\"Slovenia\" = \"Eslovenia\";\n" "\"Solomon Islands\" = \"Islas Salomón\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"Sudáfrica\";\n" "\"South Georgia and the South Sandwich Islands\" = \"South Georgia and the South Sandwich Islands\";\n" "\"South Sudan\" = \"Sudán del Sur\";\n" "\"Spain\" = \"España\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Empezó %s\";\n" "\"Status\" = \"Situación\";\n" "\"Sub-commands:\" = \"Subcomandantes:\";\n" "\"Sudan\" = \"Sudán\";\n" "\"Supplies\" = \"Suministros\";\n" "\"Suriname\" = \"Suriname\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard y Jan Mayen\";\n" "\"Sweden\" = \"Suecia\";\n" "\"Switzerland\" = \"Suiza\";\n" "\"Syrian Arab Republic\" = \"República Árabe Siria\";\n" "\"Taiwan, Province of China\" = \"Taiwán, Provincia de China\";\n" "\"Tajikistan\" = \"Tayikistán\";\n" "\"Tanzania, United Republic of\" = \"República Unida de Tanzanía\";\n" "\"Test page printed.\" = \"Ficha de prueba impresa.\";\n" "\"Thailand\" = \"Tailandia\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Este formulario crea una solicitud de firma de certificados (CSR) que puede enviar a una Autoridad de Certificados (CA) para obtener un certificado TLS de confianza. La clave privada se guarda por separado para su uso con el certificado que obtiene de la CA.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Este formulario crea un nuevo certificado TLS auto-firmado para impresión segura. Los navegadores web no confían automáticamente certificados auto-firmados.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Este formulario instalará un certificado TLS de confianza que haya obtenido de una Autoridad de Certificados (CA.) Una vez instalado, se utilizará inmediatamente.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad y Tabago\";\n" "\"Tunisia\" = \"Túnez\";\n" "\"Turkey\" = \"Turquía\";\n" "\"Turkmenistan\" = \"Turkmenistán\";\n" "\"Turks and Caicos Islands\" = \"Islas Turcas y Caicos\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ucrania\";\n" "\"Unable to access test print file.\" = \"Incapaz de acceder al archivo de impresión de prueba.\";\n" "\"Unable to copy print job.\" = \"Incapaz de copiar el trabajo de impresión.\";\n" "\"Unable to create certificate request.\" = \"Incapaz de crear solicitud de certificado.\";\n" "\"Unable to create certificate.\" = \"Incapaz de crear certificado.\";\n" "\"Unable to create test print job.\" = \"Incapaz de crear trabajo de impresión de prueba.\";\n" "\"Unable to identify printer.\" = \"Incapaz de identificar la impresora.\";\n" "\"Unable to lookup address.\" = \"Incapaz de buscar la dirección.\";\n" "\"Unable to use that driver.\" = \"Incapaz de usar ese conductor.\";\n" "\"United Arab Emirates\" = \"Emiratos Árabes Unidos\";\n" "\"United Kingdom\" = \"Reino Unido\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Reino Unido de Gran Bretaña e Irlanda del Norte\";\n" "\"United States Minor Outlying Islands\" = \"Islas Menores de los Estados Unidos\";\n" "\"United States of America\" = \"Estados Unidos de América\";\n" "\"Unknown\" = \"Desconocida\";\n" "\"Unknown action.\" = \"Acción desconocida.\";\n" "\"Unknown form action.\" = \"Acción de forma desconocida.\";\n" "\"Unknown form request.\" = \"Solicitud de formulario desconocido.\";\n" "\"Updating Network Configuration\" = \"Actualizar la configuración de red\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\";\n" "\"Use My Position\" = \"Usar mi posición\";\n" "\"Users\" = \"Usuarios\";\n" "\"Uzbekistan\" = \"Uzbekistán\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (República Bolivariana de)\";\n" "\"Version %s\" = \"Versión %s\";\n" "\"Viet Nam\" = \"Viet Nam\";\n" "\"View Logs\" = \"Ver los registros\";\n" "\"Virgin Islands (British)\" = \"Islas Vírgenes (British)\";\n" "\"Virgin Islands (U.S.)\" = \"Islas Vírgenes (U.S)\";\n" "\"Wallis and Futuna\" = \"Wallis y Futuna\";\n" "\"Warning\" = \"Advertencia\";\n" "\"Western Sahara\" = \"Sáhara Occidental\";\n" "\"Wi-Fi Configuration\" = \"Configuración Wi-Fi\";\n" "\"Wi-Fi Network\" = \"Wi-Fi Network\";\n" "\"Width\" = \"Width\";\n" "\"Wrong old password.\" = \"contraseña vieja incorrecta.\";\n" "\"Yemen\" = \"Yemen\";\n" "\"Zambia\" = \"Zambia\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"en %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Número de copias\";\n" "\"default printer\" = \"impresora predeterminada\";\n" "\"finishings\" = \"Acabado\";\n" "\"finishings.10\" = \"Fold\";\n" "\"finishings.100\" = \"Z plegable\";\n" "\"finishings.101\" = \"Ingeniería Z plegable\";\n" "\"finishings.11\" = \"Corte\";\n" "\"finishings.12\" = \"Bale\";\n" "\"finishings.13\" = \"Booklet maker\";\n" "\"finishings.15\" = \"Coat\";\n" "\"finishings.16\" = \"Laminate\";\n" "\"finishings.20\" = \"Parte superior izquierda\";\n" "\"finishings.21\" = \"Fondo básico izquierdo\";\n" "\"finishings.22\" = \"Parte superior derecha\";\n" "\"finishings.23\" = \"Parte inferior derecha\";\n" "\"finishings.24\" = \"Punto izquierdo\";\n" "\"finishings.25\" = \"Parte superior\";\n" "\"finishings.26\" = \"Sutura de borde derecha\";\n" "\"finishings.27\" = \"Parte inferior de la puntada\";\n" "\"finishings.28\" = \"2 grapas a la izquierda\";\n" "\"finishings.29\" = \"2 grapas en la parte superior\";\n" "\"finishings.3\" = \"Ninguno\";\n" "\"finishings.30\" = \"2 grapas a la derecha\";\n" "\"finishings.31\" = \"2 grapas en la parte inferior\";\n" "\"finishings.32\" = \"3 grapas a la izquierda\";\n" "\"finishings.33\" = \"3 grapas en la parte superior\";\n" "\"finishings.34\" = \"3 grapas a la derecha\";\n" "\"finishings.35\" = \"3 grapas en la parte inferior\";\n" "\"finishings.4\" = \"Grado\";\n" "\"finishings.5\" = \"Punch\";\n" "\"finishings.50\" = \"Bind izquierda\";\n" "\"finishings.51\" = \"Parte superior\";\n" "\"finishings.52\" = \"Apunta derecho\";\n" "\"finishings.53\" = \"Parte inferior\";\n" "\"finishings.6\" = \"Cubierta\";\n" "\"finishings.60\" = \"Cortar después de cada página\";\n" "\"finishings.61\" = \"Corte después de cada documento\";\n" "\"finishings.62\" = \"Corte después de cada set\";\n" "\"finishings.63\" = \"Cortar después del trabajo\";\n" "\"finishings.7\" = \"Bind\";\n" "\"finishings.70\" = \"Punch superior izquierdo\";\n" "\"finishings.71\" = \"Punch inferior izquierdo\";\n" "\"finishings.72\" = \"Punch superior derecho\";\n" "\"finishings.73\" = \"Punch fondo derecho\";\n" "\"finishings.74\" = \"2-hole punch left\";\n" "\"finishings.75\" = \"Top de 2 agujeros\";\n" "\"finishings.76\" = \"2 agujeros derecho\";\n" "\"finishings.77\" = \"Parte inferior de 2 agujeros\";\n" "\"finishings.78\" = \"3-hole punch left\";\n" "\"finishings.79\" = \"Top de 3 hoyos\";\n" "\"finishings.8\" = \"Sutura de asiento\";\n" "\"finishings.80\" = \"3 agujeros derecho\";\n" "\"finishings.81\" = \"3-hole punch bottom\";\n" "\"finishings.82\" = \"4-hole punch left\";\n" "\"finishings.83\" = \"Top de 4 agujeros\";\n" "\"finishings.84\" = \"4 agujeros derecho\";\n" "\"finishings.85\" = \"4 agujeros abajo\";\n" "\"finishings.86\" = \"Golpe de agujero múltiple izquierda\";\n" "\"finishings.87\" = \"Top de perforación de agujeros múltiples\";\n" "\"finishings.88\" = \"Multi-hole punch right\";\n" "\"finishings.89\" = \"Fondo de perforación de agujeros múltiples\";\n" "\"finishings.9\" = \"Sutura de borde\";\n" "\"finishings.90\" = \"Pliegue de acordeón\";\n" "\"finishings.91\" = \"Doble puerta\";\n" "\"finishings.92\" = \"Puerta plegable\";\n" "\"finishings.93\" = \"Media pliegue\";\n" "\"finishings.94\" = \"Media Z plegable\";\n" "\"finishings.95\" = \"Puerta izquierda\";\n" "\"finishings.96\" = \"Carta plegable\";\n" "\"finishings.97\" = \"Pliegue paralelo\";\n" "\"finishings.98\" = \"Cargador\";\n" "\"finishings.99\" = \"Puerta derecha\";\n" "\"holding new jobs\" = \"ocupar nuevos puestos\";\n" "\"job-state-reasons.aborted-by-system\" = \"Para.\";\n" "\"job-state-reasons.compression-error\" = \"Error de descompresión.\";\n" "\"job-state-reasons.document-format-error\" = \"Error de formato de documento.\";\n" "\"job-state-reasons.document-password-error\" = \"Error de contraseña de documento.\";\n" "\"job-state-reasons.document-permission-error\" = \"Error de permiso de documento.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Documente error imprimible.\";\n" "\"job-state-reasons.errors-detected\" = \"Errores detectados.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Cancelado en la impresora.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Cancelado por el usuario.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Impresión.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Imprimido con errores.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Imprimido con advertencias.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Datos insuficientes.\";\n" "\"job-state-reasons.job-fetchable\" = \"Increíble.\";\n" "\"job-state-reasons.job-incoming\" = \"Entrando.\";\n" "\"job-state-reasons.job-printing\" = \"Impresión.\";\n" "\"job-state-reasons.job-queued\" = \"Preparando para imprimir.\";\n" "\"job-state-reasons.job-spooling\" = \"Compartir.\";\n" "\"job-state-reasons.none\" = \"Esperando.\";\n" "\"job-state-reasons.printer-stopped\" = \"Impresora fuera de línea.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"La impresora paró parcialmente.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Para.\";\n" "\"job-state-reasons.queued-in-device\" = \"Listo.\";\n" "\"job-state-reasons.warnings-detected\" = \"Advertencias detectadas.\";\n" "\"job-state.3\" = \"Pendiente\";\n" "\"job-state.4\" = \"Soldado\";\n" "\"job-state.5\" = \"Procesamiento\";\n" "\"job-state.6\" = \"Detenido\";\n" "\"job-state.7\" = \"Cancelado\";\n" "\"job-state.8\" = \"Abortados\";\n" "\"job-state.9\" = \"Completado\";\n" "\"joining\" = \"unirse\";\n" "\"media\" = \"Media\";\n" "\"media-col\" = \"Media\";\n" "\"media-size\" = \"Tamaño de los medios\";\n" "\"media-size-name\" = \"Tamaño de los medios\";\n" "\"media-source\" = \"Input Tray\";\n" "\"media-source.alternate\" = \"Suplente\";\n" "\"media-source.alternate-roll\" = \"Rollo alternativo\";\n" "\"media-source.auto\" = \"Automático\";\n" "\"media-source.bottom\" = \"Bottom\";\n" "\"media-source.by-pass-tray\" = \"Bandera multiusos\";\n" "\"media-source.center\" = \"Center\";\n" "\"media-source.disc\" = \"Disco\";\n" "\"media-source.envelope\" = \"Envelope\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Gran capacidad\";\n" "\"media-source.left\" = \"Izquierda\";\n" "\"media-source.main\" = \"Main\";\n" "\"media-source.main-roll\" = \"Rollo principal\";\n" "\"media-source.manual\" = \"Manual\";\n" "\"media-source.middle\" = \"Medio ambiente\";\n" "\"media-source.photo\" = \"Foto\";\n" "\"media-source.rear\" = \"Rear\";\n" "\"media-source.right\" = \"Bien.\";\n" "\"media-source.roll-1\" = \"Rollo 1\";\n" "\"media-source.roll-10\" = \"Rollo 10\";\n" "\"media-source.roll-2\" = \"Rollo 2\";\n" "\"media-source.roll-3\" = \"Rollo 3\";\n" "\"media-source.roll-4\" = \"Rollo 4\";\n" "\"media-source.roll-5\" = \"Rollo 5\";\n" "\"media-source.roll-6\" = \"Rollo 6\";\n" "\"media-source.roll-7\" = \"Rollo 7\";\n" "\"media-source.roll-8\" = \"Rollo 8\";\n" "\"media-source.roll-9\" = \"Rollo 9\";\n" "\"media-source.side\" = \"Lado\";\n" "\"media-source.top\" = \"Top\";\n" "\"media-source.tray-1\" = \"Tray 1\";\n" "\"media-source.tray-10\" = \"Tray 10\";\n" "\"media-source.tray-11\" = \"Tray 11\";\n" "\"media-source.tray-12\" = \"Tray 12\";\n" "\"media-source.tray-13\" = \"Tray 13\";\n" "\"media-source.tray-14\" = \"Tray 14\";\n" "\"media-source.tray-15\" = \"Tray 15\";\n" "\"media-source.tray-16\" = \"Tray 16\";\n" "\"media-source.tray-17\" = \"Tray 17\";\n" "\"media-source.tray-18\" = \"Tray 18\";\n" "\"media-source.tray-19\" = \"Tray 19\";\n" "\"media-source.tray-2\" = \"Tray 2\";\n" "\"media-source.tray-20\" = \"Tray 20\";\n" "\"media-source.tray-3\" = \"Tray 3\";\n" "\"media-source.tray-4\" = \"Tray 4\";\n" "\"media-source.tray-5\" = \"Tray 5\";\n" "\"media-source.tray-6\" = \"Tray 6\";\n" "\"media-source.tray-7\" = \"Tray 7\";\n" "\"media-source.tray-8\" = \"Tray 8\";\n" "\"media-source.tray-9\" = \"Tray 9\";\n" "\"media-tracking\" = \"Seguimiento de medios\";\n" "\"media-tracking.continuous\" = \"Continua\";\n" "\"media-tracking.gap\" = \"Gap\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Tipo de medio\";\n" "\"media-type.aluminum\" = \"Aluminio\";\n" "\"media-type.auto\" = \"Automático\";\n" "\"media-type.back-print-film\" = \"Imágenes de impresión\";\n" "\"media-type.cardboard\" = \"Cartón\";\n" "\"media-type.cardstock\" = \"Cardstock\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Continua\";\n" "\"media-type.continuous-long\" = \"Extremo continuo\";\n" "\"media-type.continuous-short\" = \"corto continuo\";\n" "\"media-type.corrugated-board\" = \"Tablero ondulado\";\n" "\"media-type.disc\" = \"Disco óptico\";\n" "\"media-type.disc-glossy\" = \"Disco óptico brillante\";\n" "\"media-type.disc-high-gloss\" = \"Disco óptico de alto brillo\";\n" "\"media-type.disc-matte\" = \"Disco óptico mate\";\n" "\"media-type.disc-satin\" = \"Disco óptico Satin\";\n" "\"media-type.disc-semi-gloss\" = \"Disco óptico semi-gloss\";\n" "\"media-type.double-wall\" = \"Doble pared\";\n" "\"media-type.dry-film\" = \"Cine seco\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Incrustación de láminas\";\n" "\"media-type.end-board\" = \"Junta final\";\n" "\"media-type.envelope\" = \"Envelope\";\n" "\"media-type.envelope-archival\" = \"Sobre Archival\";\n" "\"media-type.envelope-bond\" = \"Envoltorio de huesos\";\n" "\"media-type.envelope-coated\" = \"Sobre coado\";\n" "\"media-type.envelope-cotton\" = \"Sobre de algodón\";\n" "\"media-type.envelope-fine\" = \"Envoltura fina\";\n" "\"media-type.envelope-heavyweight\" = \"Sobres pesados\";\n" "\"media-type.envelope-inkjet\" = \"Sobre de inyección de tinta\";\n" "\"media-type.envelope-lightweight\" = \"Sobre ligero\";\n" "\"media-type.envelope-plain\" = \"Envoltura plana\";\n" "\"media-type.envelope-preprinted\" = \"Sobre impreso\";\n" "\"media-type.envelope-window\" = \"Sobre ventana\";\n" "\"media-type.fabric\" = \"Tejido\";\n" "\"media-type.fabric-archival\" = \"Tejido de arquitectura\";\n" "\"media-type.fabric-glossy\" = \"Tela brillante\";\n" "\"media-type.fabric-high-gloss\" = \"Tejido alto brillo\";\n" "\"media-type.fabric-matte\" = \"Tejido mate\";\n" "\"media-type.fabric-semi-gloss\" = \"Tejido semi-gloss\";\n" "\"media-type.fabric-waterproof\" = \"Tejido impermeable\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Base flexible\";\n" "\"media-type.flexo-photo-polymer\" = \"Polómero de foto Flexo\";\n" "\"media-type.flute\" = \"Fluido\";\n" "\"media-type.foil\" = \"Foil\";\n" "\"media-type.full-cut-tabs\" = \"pestañas de corte completo\";\n" "\"media-type.glass\" = \"Cristal\";\n" "\"media-type.glass-colored\" = \"Color de vidrio\";\n" "\"media-type.glass-opaque\" = \"Opaque de vidrio\";\n" "\"media-type.glass-surfaced\" = \"Vidrio en superficie\";\n" "\"media-type.glass-textured\" = \"Textura de vidrio\";\n" "\"media-type.gravure-cylinder\" = \"Cilindro de gravure\";\n" "\"media-type.image-setter-paper\" = \"Papel de setter de imagen\";\n" "\"media-type.imaging-cylinder\" = \"Cilindro de imagen\";\n" "\"media-type.labels\" = \"Etiquetas\";\n" "\"media-type.labels-colored\" = \"Etiquetas de colores\";\n" "\"media-type.labels-glossy\" = \"Etiquetas brillantesy\";\n" "\"media-type.labels-high-gloss\" = \"Altas etiquetas de brillo\";\n" "\"media-type.labels-inkjet\" = \"Etiquetas de inyección de tinta\";\n" "\"media-type.labels-matte\" = \"Etiquetas de la materia\";\n" "\"media-type.labels-permanent\" = \"Etiquetas permanentes\";\n" "\"media-type.labels-satin\" = \"Etiquetas Satin\";\n" "\"media-type.labels-security\" = \"Etiquetas de seguridad\";\n" "\"media-type.labels-semi-gloss\" = \"Etiquetas semi-gloss\";\n" "\"media-type.laminating-foil\" = \"Laminating foil\";\n" "\"media-type.letterhead\" = \"Letterhead\";\n" "\"media-type.metal\" = \"Metal\";\n" "\"media-type.metal-glossy\" = \"Metal brillante\";\n" "\"media-type.metal-high-gloss\" = \"Metal alto brillo\";\n" "\"media-type.metal-matte\" = \"Matte de metal\";\n" "\"media-type.metal-satin\" = \"Metal satinado\";\n" "\"media-type.metal-semi-gloss\" = \"Metal semi brillo\";\n" "\"media-type.mounting-tape\" = \"Cinta de montaje\";\n" "\"media-type.multi-layer\" = \"Multi capa\";\n" "\"media-type.multi-part-form\" = \"Forma de múltiples piezas\";\n" "\"media-type.other\" = \"Otros\";\n" "\"media-type.paper\" = \"Documento\";\n" "\"media-type.photographic\" = \"Papel fotográfico\";\n" "\"media-type.photographic-archival\" = \"Archivo fotográfico\";\n" "\"media-type.photographic-film\" = \"Cine fotográfico\";\n" "\"media-type.photographic-glossy\" = \"Papel fotográfico brillante\";\n" "\"media-type.photographic-high-gloss\" = \"Papel fotográfico alto brillo\";\n" "\"media-type.photographic-matte\" = \"Papel fotográfico mate\";\n" "\"media-type.photographic-satin\" = \"Papel fotográfico Satin\";\n" "\"media-type.photographic-semi-gloss\" = \"Papel fotográfico semi-gloss\";\n" "\"media-type.plastic\" = \"Plástico\";\n" "\"media-type.plastic-archival\" = \"Archivo de plástico\";\n" "\"media-type.plastic-colored\" = \"Color de plástico\";\n" "\"media-type.plastic-glossy\" = \"Plástico brillante\";\n" "\"media-type.plastic-high-gloss\" = \"Plástico alto brillo\";\n" "\"media-type.plastic-matte\" = \"Aparato plástico\";\n" "\"media-type.plastic-satin\" = \"satinado plástico\";\n" "\"media-type.plastic-semi-gloss\" = \"Plástico semi brillante\";\n" "\"media-type.plate\" = \"Placa\";\n" "\"media-type.polyester\" = \"Poliéster\";\n" "\"media-type.pre-cut-tabs\" = \"pestañas de corte pre\";\n" "\"media-type.roll\" = \"Roll\";\n" "\"media-type.screen\" = \"Pantalla\";\n" "\"media-type.screen-paged\" = \"Paged\";\n" "\"media-type.self-adhesive\" = \"Auto adhesivo\";\n" "\"media-type.self-adhesive-film\" = \"Película autoadhesiva\";\n" "\"media-type.shrink-foil\" = \"Barbacoa\";\n" "\"media-type.single-face\" = \"Cara individual\";\n" "\"media-type.single-wall\" = \"Pared individual\";\n" "\"media-type.sleeve\" = \"Sleeve\";\n" "\"media-type.stationery\" = \"Papelería\";\n" "\"media-type.stationery-archival\" = \"Archivo de papelería\";\n" "\"media-type.stationery-coated\" = \"Papel coado\";\n" "\"media-type.stationery-cotton\" = \"Algodón de papelería\";\n" "\"media-type.stationery-fine\" = \"Papel de aluminio\";\n" "\"media-type.stationery-heavyweight\" = \"Papel pesado\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Papelería pesada recubierto\";\n" "\"media-type.stationery-inkjet\" = \"Papel de inyección de tinta\";\n" "\"media-type.stationery-letterhead\" = \"Letterhead\";\n" "\"media-type.stationery-lightweight\" = \"Papel ligero\";\n" "\"media-type.stationery-preprinted\" = \"Papel impreso\";\n" "\"media-type.stationery-prepunched\" = \"Papel picado\";\n" "\"media-type.tab-stock\" = \"Tab stock\";\n" "\"media-type.tractor\" = \"Tractor\";\n" "\"media-type.transfer\" = \"Transferencia\";\n" "\"media-type.transparency\" = \"Transparencia\";\n" "\"media-type.triple-wall\" = \"Triple pared\";\n" "\"media-type.wet-film\" = \"Película húmeda\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 o US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Envelope\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Envelope\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Envelope\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Envelope\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Envelope\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Envelope\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Envelope\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Envelope\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Envelope\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Envelope\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Envelope\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Envelope\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Envelope\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Envelope\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Envelope\";\n" "\"media.iso_dl_110x220mm\" = \"DL Envelope\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Executive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Envelope Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Envelope Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Envelope Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Envelope Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Envelope Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Envelope Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Responder Postcard\";\n" "\"media.jpn_you4_105x235mm\" = \"Envelope Tú 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Envelope A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Envelope C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Executive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"European Fanfold\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"US Fanfold\";\n" "\"media.na_foolscap_8.5x13in\" = \"Foolscap\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Estado\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"Carta de los Estados Unidos (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"Carta de los Estados Unidos (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"Carta de los Estados Unidos\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Envelope Monarch\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Envelope #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Envelope #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Envelope #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Envelope #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Envelope #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Envelope Personal\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (especial)\";\n" "\"media.om_invite_220x220mm\" = \"Invitación de Envelope\";\n" "\"media.om_italian_110x230mm\" = \"Envelope Italian\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275 mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180 mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389m m\";\n" "\"media.om_postfix_114x229mm\" = \"Envelope Postfix\";\n" "\"media.prc_10_324x458mm\" = \"Envelope chinese #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chino 16k\";\n" "\"media.prc_1_102x165mm\" = \"Envelope chinese #1\";\n" "\"media.prc_2_102x176mm\" = \"Envelope chinese #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chino 32k\";\n" "\"media.prc_3_125x176mm\" = \"Envelope chinese #3\";\n" "\"media.prc_4_110x208mm\" = \"Envelope chinese #4\";\n" "\"media.prc_5_110x220mm\" = \"Envelope chinese #5\";\n" "\"media.prc_6_120x320mm\" = \"Envelope chinese #6\";\n" "\"media.prc_7_160x230mm\" = \"Envelope chinese #7\";\n" "\"media.prc_8_120x309mm\" = \"Envelope chinese #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"no configurado\";\n" "\"not visible\" = \"no visible\";\n" "\"off\" = \"apagado\";\n" "\"on\" = \"on\";\n" "\"orientation-requested\" = \"Orientación\";\n" "\"orientation-requested.3\" = \"Retrato\";\n" "\"orientation-requested.4\" = \"Paisaje\";\n" "\"orientation-requested.5\" = \"Paisaje inverso\";\n" "\"orientation-requested.6\" = \"Retrato inverso\";\n" "\"orientation-requested.7\" = \"Ninguno\";\n" "\"output-bin\" = \"Output Tray\";\n" "\"output-bin.auto\" = \"Automático\";\n" "\"output-bin.bottom\" = \"Bottom\";\n" "\"output-bin.center\" = \"Center\";\n" "\"output-bin.face-down\" = \"Cara abajo.\";\n" "\"output-bin.face-up\" = \"Cara arriba\";\n" "\"output-bin.large-capacity\" = \"Gran capacidad\";\n" "\"output-bin.left\" = \"Izquierda\";\n" "\"output-bin.mailbox-1\" = \"Mailbox 1\";\n" "\"output-bin.mailbox-10\" = \"Mailbox 10\";\n" "\"output-bin.mailbox-2\" = \"Mailbox 2\";\n" "\"output-bin.mailbox-3\" = \"Mailbox 3\";\n" "\"output-bin.mailbox-4\" = \"Mailbox 4\";\n" "\"output-bin.mailbox-5\" = \"Mailbox 5\";\n" "\"output-bin.mailbox-6\" = \"Mailbox 6\";\n" "\"output-bin.mailbox-7\" = \"Mailbox 7\";\n" "\"output-bin.mailbox-8\" = \"Mailbox 8\";\n" "\"output-bin.mailbox-9\" = \"Mailbox 9\";\n" "\"output-bin.middle\" = \"Medio ambiente\";\n" "\"output-bin.my-mailbox\" = \"Mi buzón de correo\";\n" "\"output-bin.rear\" = \"Rear\";\n" "\"output-bin.right\" = \"Bien.\";\n" "\"output-bin.side\" = \"Lado\";\n" "\"output-bin.stacker-1\" = \"Stacker 1\";\n" "\"output-bin.stacker-10\" = \"Stacker 10\";\n" "\"output-bin.stacker-2\" = \"Stacker 2\";\n" "\"output-bin.stacker-3\" = \"Stacker 3\";\n" "\"output-bin.stacker-4\" = \"Stacker 4\";\n" "\"output-bin.stacker-5\" = \"Stacker 5\";\n" "\"output-bin.stacker-6\" = \"Stacker 6\";\n" "\"output-bin.stacker-7\" = \"Stacker 7\";\n" "\"output-bin.stacker-8\" = \"Stacker 8\";\n" "\"output-bin.stacker-9\" = \"Stacker 9\";\n" "\"output-bin.top\" = \"Top\";\n" "\"output-bin.tray-1\" = \"Tray 1\";\n" "\"output-bin.tray-10\" = \"Tray 10\";\n" "\"output-bin.tray-2\" = \"Tray 2\";\n" "\"output-bin.tray-3\" = \"Tray 3\";\n" "\"output-bin.tray-4\" = \"Tray 4\";\n" "\"output-bin.tray-5\" = \"Tray 5\";\n" "\"output-bin.tray-6\" = \"Tray 6\";\n" "\"output-bin.tray-7\" = \"Tray 7\";\n" "\"output-bin.tray-8\" = \"Tray 8\";\n" "\"output-bin.tray-9\" = \"Tray 9\";\n" "\"print-color-mode\" = \"Modo de impresión\";\n" "\"print-color-mode.auto\" = \"Automático\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monocromo\";\n" "\"print-color-mode.bi-level\" = \"Texto\";\n" "\"print-color-mode.color\" = \"Color\";\n" "\"print-color-mode.highlight\" = \"Highlight\";\n" "\"print-color-mode.monochrome\" = \"Monocromo\";\n" "\"print-color-mode.process-bi-level\" = \"Texto del proceso\";\n" "\"print-color-mode.process-monochrome\" = \"Proceso monocromo\";\n" "\"print-content-optimize\" = \"Optimize For\";\n" "\"print-content-optimize.auto\" = \"Automático\";\n" "\"print-content-optimize.graphic\" = \"Gráficos\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Texto\";\n" "\"print-content-optimize.text-and-graphic\" = \"Texto y gráficos\";\n" "\"print-darkness\" = \"Imprimir Oscuridad\";\n" "\"print-quality\" = \"Calidad de impresión\";\n" "\"print-quality.3\" = \"Proyecto\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Mejor\";\n" "\"print-scaling\" = \"Escalada\";\n" "\"print-scaling.auto\" = \"Automático\";\n" "\"print-scaling.auto-fit\" = \"Auto-fit\";\n" "\"print-scaling.fill\" = \"Relleno\";\n" "\"print-scaling.fit\" = \"Fit\";\n" "\"print-scaling.none\" = \"Ninguno\";\n" "\"print-speed\" = \"Velocidad de impresión\";\n" "\"printer-resolution\" = \"Resolución\";\n" "\"printer-state-reasons.cover-open\" = \"Cubierta abierta.\";\n" "\"printer-state-reasons.door-open\" = \"Puerta abierta.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Identifique la impresora.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Falta la bandeja de papel.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"De tinta.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Tinta baja.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"La basura casi llena.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"basura llena.\";\n" "\"printer-state-reasons.media-empty\" = \"De papel.\";\n" "\"printer-state-reasons.media-jam\" = \"Mermelada de papel.\";\n" "\"printer-state-reasons.media-low\" = \"Reemplaza el papel pronto.\";\n" "\"printer-state-reasons.media-needed\" = \"Papel de carga.\";\n" "\"printer-state-reasons.none\" = \"Listo.\";\n" "\"printer-state-reasons.offline\" = \"Sin conexión.\";\n" "\"printer-state-reasons.other\" = \"Ver la impresora.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Impresora ocupada.\";\n" "\"printer-state-reasons.toner-empty\" = \"Fuera de toner.\";\n" "\"printer-state-reasons.toner-low\" = \"Toner bajo.\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Procesamiento\";\n" "\"printer-state.5\" = \"Detenido\";\n" "\"sides\" = \"Impresión de 2 asientos\";\n" "\"sides.one-sided\" = \"Fuera.\";\n" "\"sides.two-sided-long-edge\" = \"En (portrait)\";\n" "\"sides.two-sided-short-edge\" = \"En (paisaje)\";\n" "\"unable to join\" = \"incapaz de unirse\";\n" "\"yesterday at %02d:%02d:%02d\" = \"ayer a las %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Islas\";\n"; pappl-1.4.9/pappl/strings/fi.strings000066400000000000000000000000001476704353100174570ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/fr.strings000066400000000000000000001365431476704353100175160ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Annuler tous les emplois (cancel.)"; " -c COPIES" = "-c COPIES"; " -d PRINTER Specify printer." = " -d PRINTER Indiquez l'imprimante."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Spécifier l'identité d'emploi (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Indiquer le conducteur (ajouter/modifier.)"; " -n COPIES Specify number of copies (submit)." = " -n COPIES Préciser le nombre d'exemplaires (soumis.)"; " -o %s=%s (default)" = "-o %s = %s (par défaut)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Option de spécification (add,modify,server,submit.)"; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 à 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 à 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZATION"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Specify ipp: or ipps: printer/server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Spécifier la socket: ou usb: périphérique (add/modify.)"; " add PRINTER Add a printer." = " add PRINTER Ajouter une imprimante."; " autoadd Automatically add supported printers." = " autoadd Ajoutez automatiquement les imprimantes supportées."; " cancel Cancel one or more jobs." = " cancel Annuler un ou plusieurs emplois."; " default Set the default printer." = " default Réglez l'imprimante par défaut."; " delete Delete a printer." = " delete Supprimer une imprimante."; " devices List devices." = " devices Liste des appareils."; " drivers List drivers." = " drivers Listez les pilotes."; " jobs List jobs." = " jobs Lister des emplois."; " modify Modify a printer." = " modify Modifier une imprimante."; " options List printer options." = " options Liste des options d'imprimante."; " pause Pause printing for a printer." = " pause Impression à la Pause pour une imprimante."; " printers List printers." = " printers Liste des imprimantes."; " resume Resume printing for a printer." = " resume Reprendre l'impression pour une imprimante."; " server Run a server." = " server Exécutez un serveur."; " shutdown Shutdown a running server." = " shutdown Fermer un serveur."; " status Show server/printer/job status." = " status Afficher le statut serveur/imprimante/job."; " submit Submit a file for printing." = " submit Soumettre un fichier pour l'impression."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d pouces/sec"; "%d job" = "Travail de F0"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%d dpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g \""; /* size (type+borderless) */ "%s (%s%s)" = "%s ( %s %s )"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) de %s"; /* Source/Tray Media */ "%s Media" = "%s Médias"; "%s: Bad 'server-port' value." = "%s: Bad server-port value."; "%s: Bad job ID." = "%s: Bad job ID."; "%s: Bad printer URI '%s'." = "%s: Bad printer URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Ne pas spécifier plus d'un sous-commande."; "%s: Empty print file received on the standard input." = "%s: Fichier imprimé vide reçu sur l'entrée standard."; "%s: Failed to create a system." = "%s: Failed to create a system."; "%s: Missing '-d PRINTER'." = "%s: Missing '-d PRINTER. '"; "%s: Missing '-m DRIVER-NAME'." = "%s: Missing '-m DRIVER-NAME. '"; "%s: Missing '-v DEVICE-URI'." = "%s: Missing '-v DEVICE-URI. '"; "%s: Missing copy count after '-n'." = "%s: Compte de copie manquante après -n."; "%s: Missing device URI after '-v'." = "%s: Dispositif manquant URI après -v."; "%s: Missing driver name after '-m'." = "%s: Nom du conducteur manquant après -m."; "%s: Missing filename after '--'." = "%s: Nom de fichier manquant après '-'."; "%s: Missing hostname after '-h'." = "%s: Nom d'hôte manquant après -h."; "%s: Missing job ID after '-j'." = "%s: Perte d'identité après -j."; "%s: Missing option(s) after '-o'." = "%s: Option(s) manquante après -o."; "%s: Missing printer URI after '-u'." = "%s: Imprimante manquante URI après -u."; "%s: Missing printer name after '-d'." = "%s: Nom d'imprimante manquant après -d."; "%s: Missing space after '-o'." = "%s: Espace manquant après -o."; "%s: Missing title after '-t'." = "%s: Titre manquant après -t."; "%s: No default printer available." = "%s: Pas d'imprimante par défaut disponible."; "%s: No files to print." = "%s: Aucun fichier à imprimer."; "%s: Server is not running." = "%s: Le serveur ne fonctionne pas."; "%s: Sub-command '%s' does not accept files." = "%s: Sous-commande '%s' n'accepte pas les fichiers."; "%s: Sub-command 'autoadd' is not supported." = "%s: Sub-command autoadd n'est pas pris en charge."; "%s: Too many files." = "%s: Trop de fichiers."; "%s: Unable to access '%s': %s" = "%s: Impossible d'accéder à '%s': %s"; "%s: Unable to add printer: %s" = "%s: Impossible d'ajouter l'imprimante: %s"; "%s: Unable to cancel job: %s" = "%s: Impossible d'annuler: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Impossible de se connecter à l'imprimante chez '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Impossible de se connecter au serveur: %s"; "%s: Unable to create temporary file: %s" = "%s: Impossible de créer un fichier temporaire: %s"; "%s: Unable to delete printer: %s" = "%s: Impossible de supprimer l'imprimante: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Impossible d'obtenir des informations pour '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Impossible d'obtenir des informations pour l'imprimante: %s"; "%s: Unable to get printer options: %s" = "%s: Impossible d'obtenir des options d'imprimante: %s"; "%s: Unable to modify printer: %s" = "%s: Impossible de modifier l'imprimante: %s"; "%s: Unable to pause printer: %s" = "%s: Impossible de faire une pause imprimante: %s"; "%s: Unable to print '%s': %s" = "%s: Impossible d'imprimer '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Impossible de reprendre l'imprimante: %s"; "%s: Unable to set default printer: %s" = "%s: Impossible de définir l'imprimante par défaut: %s"; "%s: Unable to shutdown server: %s" = "%s: Impossible de fermer le serveur: %s"; "%s: Unable to start server: %s" = "%s: Impossible de démarrer le serveur: %s"; "%s: Unable to write to temporary file: %s" = "%s: Impossible d'écrire au fichier temporaire: %s"; "%s: Unknown option '%s'." = "%s: Option inconnue '%s'."; "%s: Unknown option '-%c'." = "%s: Option inconnue '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Sous-commande inconnue '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Système URI non soutenu '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Warning - user credentials are not supported in URIs."; ", Borderless" = ", Borderless"; "A printer with that name already exists." = "Une imprimante avec ce nom existe déjà."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Add Printer"; "Admin Group" = "Groupe Admin"; "Afghanistan" = "Afghanistan"; "Albania" = "Albanie"; "Algeria" = "Algérie"; "American Samoa" = "Samoa américaines"; "Andorra" = "Andorre"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarctique"; "Antigua and Barbuda" = "Antigua-et-Barbuda"; "Argentina" = "Argentine"; "Armenia" = "Arménie"; "Aruba" = "Aruba"; "Australia" = "Australie"; "Austria" = "Autriche"; "Auto" = "Auto"; "Auto-Detect Driver" = "Auto-Detect Driver"; "Azerbaijan" = "Azerbaïdjan"; "Bad administration group." = "Bad administration group."; "Bad port number." = "Bad port number."; "Bad print group." = "Bad print group."; "Bad printer defaults." = "Bad printer defaults."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahreïn"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbade"; "Belarus" = "Bélarus"; "Belgium" = "Belgique"; "Belize" = "Belize"; "Benin" = "Bénin"; "Bermuda" = "Bermudes"; "Bhutan" = "Bhoutan"; "Bolivia (Plurinational State of)" = "Bolivie (État plurinational de)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius et Saba"; "Borderless" = "Borderless"; "Bosnia and Herzegovina" = "Bosnie-Herzégovine"; "Botswana" = "Botswana"; "Bouvet Island" = "Bouvet Island"; "Brazil" = "Brésil"; "British Indian Ocean Territory" = "British Indian Ocean Territory"; "Brunei Darussalam" = "Brunéi Darussalam"; "Bulgaria" = "Bulgarie"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Cambodge"; "Cameroon" = "Cameroun"; "Canada" = "Canada"; "Cancel All Jobs" = "Annuler tous les emplois"; "Cancel Job" = "Annuler Job"; "Canceled %s" = "Canceled %s"; "Canceling" = "Anniversaire"; "Cayman Islands" = "Îles Caïmanes"; "Central African Republic" = "République centrafricaine"; "Certificate created." = "Certificat créé."; "Certificate installed." = "Certificat installé."; "Certificate request created." = "Demande de certificat créée."; "Chad" = "Tchad"; "Change Access Password" = "Change Access Password"; "Change Log Level" = "Change Log Level"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Change Wi-Fi Network"; "Changes Saved." = "Changements enregistrés."; "Changes saved." = "Changements enregistrés."; "Chile" = "Chili"; "China" = "Chine"; "Christmas Island" = "Christmas Island"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Îles de Coco (Keeling)"; "Colombia" = "Colombie"; "Comoros" = "Comores"; "Completed %s" = "Completed %s"; "Configuration" = "Configuration"; "Configure Media" = "Configurer Media"; "Confirm Cancel All" = "Confirmer Annuler Tout"; "Confirm Delete Printer" = "Confirmer Supprimer l'imprimante"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, République démocratique du Congo"; "Contact" = "Contact"; "Cook Islands" = "Îles Cook"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Créer une demande de signature de certificat"; "Create New Certificate" = "Créer un nouveau certificat"; "Create New TLS Certificate" = "Créer un nouveau certificat TLS"; "Create TLS Certificate Request" = "Créer TLS Demande de certificat"; "Croatia" = "Croatie"; "Cuba" = "Cuba"; "Curaçao" = "Curaao"; "Current Password" = "Mot de passe actuel"; "Custom Size" = "Taille personnalisée"; "Cyprus" = "Chypre"; "Czechia" = "Czechia"; "Côte d'Ivoire" = "Cte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SD Nom de service"; "Debugging" = "Debugging"; "Default printer set." = "Imprimante par défaut."; "Delete" = "Supprimer"; "Delete Printer" = "Supprimer Printer"; "Denmark" = "Danemark"; "Djibouti" = "Djibouti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominique"; "Dominican Republic" = "République dominicaine"; "Download Certificate Request File" = "Télécharger le fichier Demande de certificat"; "Ecuador" = "Équateur"; "Egypt" = "Égypte"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Guinée équatoriale"; "Eritrea" = "Érythrée"; "Errors" = "Erreurs"; "Estonia" = "Estonie"; "Eswatini" = "Eswatini"; "Ethiopia" = "Éthiopie"; "Falkland Islands (Malvinas)" = "Îles Falkland (Malvinas)"; "Faroe Islands" = "Îles Féroé"; "Fatal Errors/Conditions" = "Erreurs/Conditions Fatales"; "Fiji" = "Fidji"; "Finland" = "Finlande"; "France" = "France"; "French Guiana" = "Guyane française"; "French Polynesia" = "Polynésie française"; "French Southern Territories" = "Territoires du Sud"; "Gabon" = "Gabon"; "Gambia" = "Gambie"; "Georgia" = "Géorgie"; "Germany" = "Allemagne"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Grèce"; "Greenland" = "Groenland"; "Grenada" = "Grenade"; "Group changes saved." = "Changements de groupe enregistrés."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernesey"; "Guinea" = "Guinée"; "Guinea-Bissau" = "Guinée-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haïti"; "Heard Island and McDonald Islands" = "Heard Island et McDonald Islands"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Saint-Siège"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Hostname"; "Human-Readable Location" = "Emplacement lisible"; "Hungary" = "Hongrie"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Islande"; "Identify Printer" = "Identifier l'imprimante"; "India" = "Inde"; "Indonesia" = "Indonésie"; "Informational" = "Informational"; "Install TLS Certificate" = "Installez TLS Certificat"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Invalid Job ID."; "Invalid certificate or private key." = "Certificat invalide ou clé privée."; "Invalid form data." = "Données de forme incorrectes."; "Invalid form submission." = "Demande de formulaire non valide."; "Invalid job ID." = "Invalide."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (République islamique d ' )"; "Iraq" = "Iraq"; "Ireland" = "Irlande"; "Isle of Man" = "Isle of Man"; "Israel" = "Israël"; "Italy" = "Italie"; "Jamaica" = "Jamaïque"; "Japan" = "Japon"; "Jersey" = "Jersey"; "Job #" = "Job"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Jobs"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Jordanie"; "Kazakhstan" = "Kazakhstan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Corée (République populaire démocratique de)"; "Korea, Republic of" = "République de Corée"; "Kuwait" = "Koweït"; "Kyrgyzstan" = "Kirghizistan"; "Landscape" = "Paysage"; "Lao People's Democratic Republic" = "République démocratique populaire lao"; "Latvia" = "Lettonie"; "Lebanon" = "Liban"; "Lesotho" = "Lesotho"; "Level" = "Niveau"; "Liberia" = "Libéria"; "Libya" = "Libye"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lituanie"; "Location" = "Lieu"; "Log Level" = "Niveau de référence"; "Logging" = "Logging"; "Logs" = "Logs"; "Luxembourg" = "Luxembourg"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malaisie"; "Maldives" = "Maldives"; "Mali" = "Mali"; "Malta" = "Malte"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Îles Marshall"; "Martinique" = "Martinique"; "Mauritania" = "Mauritanie"; "Mauritius" = "Maurice"; "Mayotte" = "Mayotte"; "Media" = "Médias"; "Mexico" = "Mexique"; "Micronesia (Federated States of)" = "Micronésie (États fédérés de)"; "Missing action." = "Manque d'action."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "La clé privée manquante."; "Moldova, Republic of" = "République de Moldova"; "Monaco" = "Monaco"; "Mongolia" = "Mongolie"; "Montenegro" = "Monténégro"; "Montserrat" = "Montserrat"; "Morocco" = "Maroc"; "Mozambique" = "Mozambique"; "Myanmar" = "Myanmar"; "Name" = "Nom"; "Namibia" = "Namibie"; "Nauru" = "Nauru"; "Nepal" = "Népal"; "Netherlands" = "Pays-Bas"; "Network" = "Network"; "Network Printer" = "Imprimeur réseau"; "Networking" = "Networking"; "New Caledonia" = "Nouvelle-Calédonie"; "New Zealand" = "Nouvelle-Zélande"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigéria"; "Niue" = "Nioué"; "No default printer set." = "Aucun jeu d'imprimante par défaut."; "No jobs in history." = "Pas de travail dans l'histoire."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "Macédoine"; "Northern Mariana Islands" = "Îles Mariannes du Nord"; "Norway" = "Norvège"; "Not set" = "Pas réglé"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Options:"; "Organization" = "Organisation"; "Organization Name" = "Nom de l ' Organisation"; "Other Settings" = "Autres paramètres"; "Pakistan" = "Pakistan"; "Palau" = "Palaos"; "Palestine, State of" = "Palestine, État"; "Panama" = "Panama"; "Papua New Guinea" = "Papouasie-Nouvelle-Guinée"; "Paraguay" = "Paraguay"; "Password" = "Mot de passe"; "Password changed." = "Le mot de passe a changé."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Le mot de passe doit avoir au moins huit caractères de long et contenir au moins une lettre majuscule, une lettre minuscule et un chiffre."; "Passwords do not match." = "Les mots de passe ne correspondent pas."; "Pause Printing" = "Impression sur la douleur"; "Peru" = "Pérou"; "Philippines" = "Philippines"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Veuillez saisir un nom d'hôte ou une adresse IP pour l'imprimante."; "Please enter a printer name." = "Veuillez entrer un nom d'imprimante."; "Please select a device." = "Veuillez sélectionner un appareil."; "Please select a driver." = "Veuillez sélectionner un pilote."; "Please select a valid log level." = "Veuillez sélectionner un niveau de journal valide."; "Poland" = "Pologne"; "Portrait" = "Portrait"; "Portugal" = "Portugal"; "Primary DNS" = "Primary DNS"; "Print Group" = "Groupe d ' impression"; "Print Test Page" = "Page d ' essai"; "Print job options:" = "Imprimer les options d'emploi:"; "Printer identified." = "Imprimante identifiée."; "Printer is currently active." = "L'imprimante est actuellement active."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Les noms d'imprimante doivent commencer par une lettre ou un soulignement et ne peuvent contenir des caractères spéciaux."; "Printer options:" = "Options d'impression:"; "Printer paused." = "Imprimante pause."; "Printer pausing." = "Imprimante."; "Printer resuming." = "L'imprimante reprend."; "Printers" = "Imprimantes"; "Printing Defaults" = "Défauts d'impression"; "Puerto Rico" = "Porto Rico"; "Qatar" = "Qatar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Reprint Job"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Récupérer l'impression"; "Reverse Landscape" = "Paysage"; "Reverse Portrait" = "Portrait"; "Romania" = "Roumanie"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Courant, %s depuis %s %s ."; "Russian Federation" = "Fédération de Russie"; "Rwanda" = "Rwanda"; "Réunion" = "Runion"; "Saint Barthélemy" = "Saint-Barthlemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Sainte-Hélène, Ascension et Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint-Kitts-et-Nevis"; "Saint Lucia" = "Sainte-Lucie"; "Saint Martin (French part)" = "Saint Martin (partie française)"; "Saint Pierre and Miquelon" = "Saint Pierre et Miquelon"; "Saint Vincent and the Grenadines" = "Saint-Vincent-et-les Grenadines"; "Samoa" = "Samoa"; "San Marino" = "Saint-Marin"; "Sao Tome and Principe" = "Sao Tomé-et-Principe"; "Saudi Arabia" = "Saudi Arabia"; "Save Changes" = "Save Changes"; "Secondary DNS" = "Secondary DNS"; "Security" = "Sécurité"; "Select Driver" = "Sélectionnez le pilote"; "Senegal" = "Sénégal"; "Serbia" = "Serbie"; "Server is not running." = "Le serveur ne fonctionne pas."; "Set Access Password" = "Set Access Password"; "Set as Default" = "Par défaut"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapour"; "Sint Maarten (Dutch part)" = "Sint Maarten (partie néerlandaise)"; "Slovakia" = "Slovaquie"; "Slovenia" = "Slovénie"; "Solomon Islands" = "Îles Salomon"; "Somalia" = "Somalie"; "South Africa" = "Afrique du Sud"; "South Georgia and the South Sandwich Islands" = "Géorgie du Sud et îles Sandwich du Sud"; "South Sudan" = "Soudan du Sud"; "Spain" = "Espagne"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "État"; "Sub-commands:" = "Sous-commandes :"; "Sudan" = "Soudan"; "Supplies" = "Fournitures"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard et Jan Mayen"; "Sweden" = "Suède"; "Switzerland" = "Suisse"; "Syrian Arab Republic" = "République arabe syrienne"; "Taiwan, Province of China" = "Taiwan, Province de Chine"; "Tajikistan" = "Tadjikistan"; "Tanzania, United Republic of" = "République-Unie de Tanzanie"; "Test page printed." = "Page d'essai imprimée."; "Thailand" = "Thaïlande"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Ce formulaire crée une demande de signature de certificat (SRC) que vous pouvez envoyer à une autorité de certification (CA) pour obtenir un certificat de SDF fiable. La clé privée est sauvegardée séparément pour utilisation avec le certificat que vous obtenez de l'AC."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Ce formulaire crée un nouveau certificat TLS autosigné pour l'impression sécurisée. Les certificats autosignés ne sont pas automatiquement fiables par les navigateurs Web."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Ce formulaire installera un certificat TLS de confiance que vous avez obtenu auprès d'une autorité de certification (CA). Une fois installé, il sera utilisé immédiatement."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokélaou"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinité-et-Tobago"; "Tunisia" = "Tunisie"; "Turkey" = "Turquie"; "Turkmenistan" = "Turkménistan"; "Turks and Caicos Islands" = "Îles Turques et Caïques"; "Tuvalu" = "Tuvalu"; "Uganda" = "Ouganda"; "Ukraine" = "Ukraine"; "Unable to access test print file." = "Impossible d'accéder au fichier d'impression de test."; "Unable to copy print job." = "Incapable de copier le travail."; "Unable to create certificate request." = "Impossible de créer une demande de certificat."; "Unable to create certificate." = "Impossible de créer un certificat."; "Unable to create test print job." = "Impossible de créer un travail d'impression test."; "Unable to identify printer." = "Incapable d'identifier l'imprimante."; "Unable to lookup address." = "Incapable de regarder l'adresse."; "Unable to use that driver." = "Incapable d'utiliser ce conducteur."; "United Arab Emirates" = "Émirats arabes unis"; "United Kingdom" = "Royaume-Uni"; "United Kingdom of Great Britain and Northern Ireland" = "Royaume-Uni de Grande-Bretagne et d ' Irlande du Nord"; "United States Minor Outlying Islands" = "United States Minor Outlying Islands"; "United States of America" = "États-Unis d ' Amérique"; "Unknown" = "Inconnu"; "Unknown action." = "Action inconnue."; "Unknown form action." = "Inconnue."; "Unknown form request." = "Demande de formulaire inconnue."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Utilisation: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Utiliser ma position"; "Users" = "Utilisateurs"; "Uzbekistan" = "Ouzbékistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (République bolivarienne du)"; "Version %s" = "Version %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "Voir les logos"; "Virgin Islands (British)" = "Îles Vierges britanniques"; "Virgin Islands (U.S.)" = "Îles Vierges américaines"; "Wallis and Futuna" = "Wallis et Futuna"; "Warning" = "Avertissement"; "Western Sahara" = "Sahara occidental"; "Wi-Fi Configuration" = "Configuration Wi-Fi"; "Wi-Fi Network" = "Wi-Fi Network"; "Width" = "Largeur"; "Wrong old password." = "Un vieux mot de passe."; "Yemen" = "Yémen"; "Zambia" = "Zambie"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Nombre de copies"; "default printer" = "imprimante par défaut"; "finishings" = "Finisher"; "finishings.10" = "Fold"; "finishings.100" = "Z pli"; "finishings.101" = "Ingénierie pli Z"; "finishings.11" = "Coupe"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Staple top gauche"; "finishings.21" = "En bas gauche"; "finishings.22" = "Staple top right"; "finishings.23" = "En bas droit"; "finishings.24" = "Couture gauche"; "finishings.25" = "Point de bord"; "finishings.26" = "Couture droite"; "finishings.27" = "Point inférieur"; "finishings.28" = "2 agrafes à gauche"; "finishings.29" = "2 agrafes sur le dessus"; "finishings.3" = "None"; "finishings.30" = "2 agrafes à droite"; "finishings.31" = "2 agrafes en bas"; "finishings.32" = "3 agrafes à gauche"; "finishings.33" = "3 agrafes sur le dessus"; "finishings.34" = "3 agrafes à droite"; "finishings.35" = "3 agrafes en bas"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind gauche"; "finishings.51" = "Bind top"; "finishings.52" = "Bind right"; "finishings.53" = "Bind bottom"; "finishings.6" = "Couverture"; "finishings.60" = "Couper après chaque page"; "finishings.61" = "Couper après chaque document"; "finishings.62" = "Couper après chaque set"; "finishings.63" = "Couper après le travail"; "finishings.7" = "Bind"; "finishings.70" = "Punch top left"; "finishings.71" = "Punch bottom left"; "finishings.72" = "Punch top right"; "finishings.73" = "Poinçon bas droit"; "finishings.74" = "2 trous à gauche"; "finishings.75" = "Top 2 trous"; "finishings.76" = "2 trous à droite"; "finishings.77" = "2 trous en bas"; "finishings.78" = "3 trous à gauche"; "finishings.79" = "Poinçon 3 trous"; "finishings.8" = "Triste couture"; "finishings.80" = "3 trous à droite"; "finishings.81" = "3 trous en bas"; "finishings.82" = "4 trous à gauche"; "finishings.83" = "Top 4 trous"; "finishings.84" = "4 trous à droite"; "finishings.85" = "4 trous en bas"; "finishings.86" = "Poinçon multi trous à gauche"; "finishings.87" = "Poinçon multi trous"; "finishings.88" = "Poinçon multifonctions à droite"; "finishings.89" = "Poinçon multi-trouilles"; "finishings.9" = "Bordure"; "finishings.90" = "Repli d ' accord"; "finishings.91" = "Double porte pliant"; "finishings.92" = "Porte pliant"; "finishings.93" = "Demi pli"; "finishings.94" = "Half Z"; "finishings.95" = "Repli de la porte gauche"; "finishings.96" = "Lit pli"; "finishings.97" = "Repli parallèle"; "finishings.98" = "Tableau pli"; "finishings.99" = "Tour droit"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Arrête."; "job-state-reasons.compression-error" = "Erreur de décompression."; "job-state-reasons.document-format-error" = "Erreur de format de document."; "job-state-reasons.document-password-error" = "Erreur de mot de passe."; "job-state-reasons.document-permission-error" = "Erreur de permission de document."; "job-state-reasons.document-unprintable-error" = "Document erreur imprimable."; "job-state-reasons.errors-detected" = "Erreurs détectées."; "job-state-reasons.job-canceled-at-device" = "Annulé à l'imprimante."; "job-state-reasons.job-canceled-by-user" = "Annulé par l'utilisateur."; "job-state-reasons.job-completed-successfully" = "Imprimé."; "job-state-reasons.job-completed-with-errors" = "Imprimé avec des erreurs."; "job-state-reasons.job-completed-with-warnings" = "Imprimé avec des avertissements."; "job-state-reasons.job-data-insufficient" = "Données insuffisantes."; "job-state-reasons.job-fetchable" = "Incroyable."; "job-state-reasons.job-incoming" = "J'arrive."; "job-state-reasons.job-printing" = "Impression."; "job-state-reasons.job-queued" = "Préparer à imprimer."; "job-state-reasons.job-spooling" = "Covoiturage."; "job-state-reasons.none" = "En attente."; "job-state-reasons.printer-stopped" = "Imprimante hors ligne."; "job-state-reasons.printer-stopped-partly" = "Imprimante partiellement arrêtée."; "job-state-reasons.processing-to-stop-point" = "Arrête."; "job-state-reasons.queued-in-device" = "Prêt."; "job-state-reasons.warnings-detected" = "Avertissements détectés."; "job-state.3" = "En attente"; "job-state.4" = "tenue"; "job-state.5" = "Traitement"; "job-state.6" = "Arrêté"; "job-state.7" = "Annulé"; "job-state.8" = "Avortée"; "job-state.9" = "Complété"; "joining" = "rejoindre"; "media" = "Médias"; "media-col" = "Médias"; "media-size" = "Taille des médias"; "media-size-name" = "Taille des médias"; "media-source" = "Input Tray"; "media-source.alternate" = "Alternate"; "media-source.alternate-roll" = "Roulement alternatif"; "media-source.auto" = "Automatique"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Plateau polyvalent"; "media-source.center" = "Center"; "media-source.disc" = "Disc"; "media-source.envelope" = "Enveloppe"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Grande capacité"; "media-source.left" = "Gauche"; "media-source.main" = "Main"; "media-source.main-roll" = "Roulement principal"; "media-source.manual" = "Manuel"; "media-source.middle" = "Moyen-Orient"; "media-source.photo" = "Photo"; "media-source.rear" = "Arrière"; "media-source.right" = "Droit"; "media-source.roll-1" = "Roll 1"; "media-source.roll-10" = "Roll 10"; "media-source.roll-2" = "Roll 2"; "media-source.roll-3" = "Roll 3"; "media-source.roll-4" = "Roll 4"; "media-source.roll-5" = "Roll 5"; "media-source.roll-6" = "Roll 6"; "media-source.roll-7" = "Roll 7"; "media-source.roll-8" = "Roll 8"; "media-source.roll-9" = "Roll 9"; "media-source.side" = "Side"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Suivi des médias"; "media-tracking.continuous" = "Continuous"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Type de média"; "media-type.aluminum" = "Aluminium"; "media-type.auto" = "Automatique"; "media-type.back-print-film" = "Film de retour"; "media-type.cardboard" = "Cardboard"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuous"; "media-type.continuous-long" = "Longtemps continu"; "media-type.continuous-short" = "Short continu"; "media-type.corrugated-board" = "Plan d ' action"; "media-type.disc" = "Disque optique"; "media-type.disc-glossy" = "Disque optique brillant"; "media-type.disc-high-gloss" = "Disque optique à haute brillance"; "media-type.disc-matte" = "Disque optique Matte"; "media-type.disc-satin" = "Disque optique satin"; "media-type.disc-semi-gloss" = "Disque optique semi-brillant"; "media-type.double-wall" = "Double mur"; "media-type.dry-film" = "Film sec"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Feuille d ' emballage"; "media-type.end-board" = "End board"; "media-type.envelope" = "Enveloppe"; "media-type.envelope-archival" = "Enveloppe d ' archivage"; "media-type.envelope-bond" = "Enveloppe d ' obligations"; "media-type.envelope-coated" = "Enveloppe revêtue"; "media-type.envelope-cotton" = "Enveloppe de coton"; "media-type.envelope-fine" = "Enveloppe fine"; "media-type.envelope-heavyweight" = "Enveloppe lourde"; "media-type.envelope-inkjet" = "Enveloppe de jet d ' encre"; "media-type.envelope-lightweight" = "Enveloppe légère"; "media-type.envelope-plain" = "Enveloppe plaine"; "media-type.envelope-preprinted" = "Enveloppe préimprimée"; "media-type.envelope-window" = "Enveloppe de fenêtre"; "media-type.fabric" = "Tissu"; "media-type.fabric-archival" = "Tissu d ' archivage"; "media-type.fabric-glossy" = "Tissu brillant"; "media-type.fabric-high-gloss" = "Tissu brillant"; "media-type.fabric-matte" = "Tissu mat"; "media-type.fabric-semi-gloss" = "Tissu semi-gloss"; "media-type.fabric-waterproof" = "Tissu étanche"; "media-type.film" = "Film"; "media-type.flexo-base" = "Base Flexo"; "media-type.flexo-photo-polymer" = "Flexo photo polymère"; "media-type.flute" = "Flute"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "onglets de coupe complète"; "media-type.glass" = "Verre"; "media-type.glass-colored" = "Verre coloré"; "media-type.glass-opaque" = "Verre opaque"; "media-type.glass-surfaced" = "Verre en surface"; "media-type.glass-textured" = "Verre texturé"; "media-type.gravure-cylinder" = "Boutet d ' échappement"; "media-type.image-setter-paper" = "Image setter paper"; "media-type.imaging-cylinder" = "Cylindre d ' image"; "media-type.labels" = "Étiquettes"; "media-type.labels-colored" = "Étiquettes colorées"; "media-type.labels-glossy" = "Étiquettes brillantes"; "media-type.labels-high-gloss" = "Étiquettes haute brillance"; "media-type.labels-inkjet" = "Étiquettes à jet d ' encre"; "media-type.labels-matte" = "Étiquettes Matte"; "media-type.labels-permanent" = "Étiquettes permanentes"; "media-type.labels-satin" = "labels satins"; "media-type.labels-security" = "Étiquettes de sécurité"; "media-type.labels-semi-gloss" = "Étiquettes semi-brillantes"; "media-type.laminating-foil" = "Feuille de plastification"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Métal"; "media-type.metal-glossy" = "Metal glossy"; "media-type.metal-high-gloss" = "Metal high gloss"; "media-type.metal-matte" = "Métal mat"; "media-type.metal-satin" = "Metal satin"; "media-type.metal-semi-gloss" = "Metal semi gloss"; "media-type.mounting-tape" = "Bande de montage"; "media-type.multi-layer" = "Multi calque"; "media-type.multi-part-form" = "Forme multipartite"; "media-type.other" = "Autres"; "media-type.paper" = "Paper"; "media-type.photographic" = "Photo paper"; "media-type.photographic-archival" = "Archival photographique"; "media-type.photographic-film" = "Photo film"; "media-type.photographic-glossy" = "Papier photo Glossy"; "media-type.photographic-high-gloss" = "Papier photo de haute brillance"; "media-type.photographic-matte" = "Matte photo paper"; "media-type.photographic-satin" = "Papier photo satin"; "media-type.photographic-semi-gloss" = "Papier photo semi-gloss"; "media-type.plastic" = "Plastique"; "media-type.plastic-archival" = "Archival plastique"; "media-type.plastic-colored" = "Couleur plastique"; "media-type.plastic-glossy" = "Matière plastique brillante"; "media-type.plastic-high-gloss" = "Plastique haute brillance"; "media-type.plastic-matte" = "mat plastique"; "media-type.plastic-satin" = "Satin plastique"; "media-type.plastic-semi-gloss" = "Plastique semi brillant"; "media-type.plate" = "Plate-forme"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "onglets pré-coupés"; "media-type.roll" = "Roll"; "media-type.screen" = "Écran"; "media-type.screen-paged" = "Écran paged"; "media-type.self-adhesive" = "Autocollant"; "media-type.self-adhesive-film" = "Film adhésif auto-adhésif"; "media-type.shrink-foil" = "Feuille de film"; "media-type.single-face" = "Face unique"; "media-type.single-wall" = "Mur unique"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Papeterie"; "media-type.stationery-archival" = "Arche de papeterie"; "media-type.stationery-coated" = "Coated paper"; "media-type.stationery-cotton" = "Coton papeterie"; "media-type.stationery-fine" = "Vellum paper"; "media-type.stationery-heavyweight" = "Papier lourd"; "media-type.stationery-heavyweight-coated" = "Stationnement lourd enduit"; "media-type.stationery-inkjet" = "Papier à jet d'encre papeterie"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Papier léger"; "media-type.stationery-preprinted" = "Document préimprimé"; "media-type.stationery-prepunched" = "Papier poinçonné"; "media-type.tab-stock" = "Stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transfert"; "media-type.transparency" = "Transparence"; "media-type.triple-wall" = "Mur triple"; "media-type.wet-film" = "Film humide"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 ou US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Enveloppe"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Enveloppe"; "media.iso_c10_28x40mm" = "C10 Enveloppe"; "media.iso_c1_648x917mm" = "C1 Enveloppe"; "media.iso_c2_458x648mm" = "C2 Enveloppe"; "media.iso_c3_324x458mm" = "C3 Enveloppe"; "media.iso_c4_229x324mm" = "C4 Enveloppe"; "media.iso_c5_162x229mm" = "C5 Enveloppe"; "media.iso_c6_114x162mm" = "C6 Enveloppe"; "media.iso_c6c5_114x229mm" = "C6/C5 Enveloppe"; "media.iso_c7_81x114mm" = "C7 Enveloppe"; "media.iso_c7c6_81x162mm" = "C7/C6 Enveloppe"; "media.iso_c8_57x81mm" = "C8 Enveloppe"; "media.iso_c9_40x57mm" = "C9 Enveloppe"; "media.iso_dl_110x220mm" = "DL Enveloppe"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Enveloppe Chou 2"; "media.jpn_chou3_120x235mm" = "Enveloppe Chou 3"; "media.jpn_chou40_90x225mm" = "Enveloppe Chou 40"; "media.jpn_chou4_90x205mm" = "Enveloppe Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Enveloppe Kahu"; "media.jpn_kaku2_240x332mm" = "Enveloppe Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Répondre Postcard"; "media.jpn_you4_105x235mm" = "Enveloppe Vous 4"; "media.na_a2_4.375x5.75in" = "Enveloppe A2"; "media.na_c5_6.5x9.5in" = "Enveloppe C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "État"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "Lettre américaine (Extra)"; "media.na_letter-plus_8.5x12.69in" = "Lettre américaine (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Monarque d ' enveloppe"; "media.na_number-10_4.125x9.5in" = "Enveloppe #10"; "media.na_number-11_4.5x10.375in" = "Enveloppe #11"; "media.na_number-12_4.75x11in" = "Enveloppe #12"; "media.na_number-14_5x11.5in" = "Enveloppe #14"; "media.na_number-9_3.875x8.875in" = "Enveloppe #9"; "media.na_personal_3.625x6.5in" = "Enveloppe personnelle"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Invitation d ' enveloppe"; "media.om_italian_110x230mm" = "Enveloppe italienne"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389m m"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Enveloppe chinoise #10"; "media.prc_16k_146x215mm" = "Chinois 16k"; "media.prc_1_102x165mm" = "Enveloppe chinoise #1"; "media.prc_2_102x176mm" = "Enveloppe chinoise #2"; "media.prc_32k_97x151mm" = "Chinois 32k"; "media.prc_3_125x176mm" = "Enveloppe chinoise #3"; "media.prc_4_110x208mm" = "Enveloppe chinoise #4"; "media.prc_5_110x220mm" = "Enveloppe chinoise #5"; "media.prc_6_120x320mm" = "Enveloppe chinoise #6"; "media.prc_7_160x230mm" = "Enveloppe chinoise #7"; "media.prc_8_120x309mm" = "Enveloppe chinoise #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "non configuré"; "not visible" = "non visible"; "off" = "Dégage."; "on" = "on"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Paysage"; "orientation-requested.5" = "Paysage inversé"; "orientation-requested.6" = "Portrait inversé"; "orientation-requested.7" = "None"; "output-bin" = "Sortie Tray"; "output-bin.auto" = "Automatique"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Face à terre"; "output-bin.face-up" = "Face à face"; "output-bin.large-capacity" = "Grande capacité"; "output-bin.left" = "Gauche"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Moyen-Orient"; "output-bin.my-mailbox" = "Ma boîte aux lettres"; "output-bin.rear" = "Arrière"; "output-bin.right" = "Droit"; "output-bin.side" = "Side"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Mode d ' impression"; "print-color-mode.auto" = "Automatique"; "print-color-mode.auto-monochrome" = "Auto monochrome"; "print-color-mode.bi-level" = "Texte"; "print-color-mode.color" = "Couleur"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monochrome"; "print-color-mode.process-bi-level" = "Texte du processus"; "print-color-mode.process-monochrome" = "Processus monochrome"; "print-content-optimize" = "Optimiser pour"; "print-content-optimize.auto" = "Automatique"; "print-content-optimize.graphic" = "Graphiques"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Texte"; "print-content-optimize.text-and-graphic" = "Texte et graphiques"; "print-darkness" = "Imprimer Darkness"; "print-quality" = "Qualité de l ' impression"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Meilleur"; "print-scaling" = "Scaling"; "print-scaling.auto" = "Automatique"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Rempli"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "None"; "print-speed" = "Vitesse d ' impression"; "printer-resolution" = "Résolution"; "printer-state-reasons.cover-open" = "Couverture ouverte."; "printer-state-reasons.door-open" = "Porte ouverte."; "printer-state-reasons.identify-printer-requested" = "Identifiez l'imprimante."; "printer-state-reasons.input-tray-missing" = "Le papier manquant."; "printer-state-reasons.marker-supply-empty" = "De l'encre."; "printer-state-reasons.marker-supply-low" = "Faible encre."; "printer-state-reasons.marker-waste-almost-full" = "La poubelle est presque pleine."; "printer-state-reasons.marker-waste-full" = "La poubelle est pleine."; "printer-state-reasons.media-empty" = "Hors de papier."; "printer-state-reasons.media-jam" = "La confiture de papier."; "printer-state-reasons.media-low" = "Remplacez le papier bientôt."; "printer-state-reasons.media-needed" = "Le papier de charge."; "printer-state-reasons.none" = "Prêt."; "printer-state-reasons.offline" = "Hors ligne."; "printer-state-reasons.other" = "Voir l'imprimante."; "printer-state-reasons.spool-area-full" = "Imprimante occupée."; "printer-state-reasons.toner-empty" = "Hors de tonner."; "printer-state-reasons.toner-low" = "Plus bas."; "printer-state.3" = "Idle"; "printer-state.4" = "Traitement"; "printer-state.5" = "Arrêté"; "sides" = "Impression 2-Sided"; "sides.one-sided" = "Officier"; "sides.two-sided-long-edge" = "Sur (portrait)"; "sides.two-sided-short-edge" = "On (landscape)"; "unable to join" = "incapable de se joindre"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Îles Salomon"; pappl-1.4.9/pappl/strings/fr_strings.h000066400000000000000000001572321476704353100200230ustar00rootroot00000000000000static const char *fr_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Annuler tous les emplois (cancel.)\";\n" "\" -c COPIES\" = \"-c COPIES\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Indiquez l'imprimante.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Spécifier l'identité d'emploi (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Indiquer le conducteur (ajouter/modifier.)\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Préciser le nombre d'exemplaires (soumis.)\";\n" "\" -o %s=%s (default)\" = \"-o %s = %s (par défaut)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=VALUE Option de spécification (add,modify,server,submit.)\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 à 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 à 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOCATION\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZATION\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Specify ipp: or ipps: printer/server.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Spécifier la socket: ou usb: périphérique (add/modify.)\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Ajouter une imprimante.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Ajoutez automatiquement les imprimantes supportées.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Annuler un ou plusieurs emplois.\";\n" "\" default Set the default printer.\" = \" default Réglez l'imprimante par défaut.\";\n" "\" delete Delete a printer.\" = \" delete Supprimer une imprimante.\";\n" "\" devices List devices.\" = \" devices Liste des appareils.\";\n" "\" drivers List drivers.\" = \" drivers Listez les pilotes.\";\n" "\" jobs List jobs.\" = \" jobs Lister des emplois.\";\n" "\" modify Modify a printer.\" = \" modify Modifier une imprimante.\";\n" "\" options List printer options.\" = \" options Liste des options d'imprimante.\";\n" "\" pause Pause printing for a printer.\" = \" pause Impression à la Pause pour une imprimante.\";\n" "\" printers List printers.\" = \" printers Liste des imprimantes.\";\n" "\" resume Resume printing for a printer.\" = \" resume Reprendre l'impression pour une imprimante.\";\n" "\" server Run a server.\" = \" server Exécutez un serveur.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Fermer un serveur.\";\n" "\" status Show server/printer/job status.\" = \" status Afficher le statut serveur/imprimante/job.\";\n" "\" submit Submit a file for printing.\" = \" submit Soumettre un fichier pour l'impression.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d pouces/sec\";\n" "\"%d job\" = \"Travail de F0\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%d dpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g \\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s ( %s %s )\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) de %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Médias\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Bad server-port value.\";\n" "\"%s: Bad job ID.\" = \"%s: Bad job ID.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Bad printer URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Ne pas spécifier plus d'un sous-commande.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Fichier imprimé vide reçu sur l'entrée standard.\";\n" "\"%s: Failed to create a system.\" = \"%s: Failed to create a system.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Missing '-d PRINTER. '\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Missing '-m DRIVER-NAME. '\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Missing '-v DEVICE-URI. '\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Compte de copie manquante après -n.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Dispositif manquant URI après -v.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Nom du conducteur manquant après -m.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Nom de fichier manquant après '-'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Nom d'hôte manquant après -h.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Perte d'identité après -j.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: Option(s) manquante après -o.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Imprimante manquante URI après -u.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Nom d'imprimante manquant après -d.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Espace manquant après -o.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Titre manquant après -t.\";\n" "\"%s: No default printer available.\" = \"%s: Pas d'imprimante par défaut disponible.\";\n" "\"%s: No files to print.\" = \"%s: Aucun fichier à imprimer.\";\n" "\"%s: Server is not running.\" = \"%s: Le serveur ne fonctionne pas.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Sous-commande '%s' n'accepte pas les fichiers.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Sub-command autoadd n'est pas pris en charge.\";\n" "\"%s: Too many files.\" = \"%s: Trop de fichiers.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Impossible d'accéder à '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Impossible d'ajouter l'imprimante: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Impossible d'annuler: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Impossible de se connecter à l'imprimante chez '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Impossible de se connecter au serveur: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Impossible de créer un fichier temporaire: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Impossible de supprimer l'imprimante: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Impossible d'obtenir des informations pour '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Impossible d'obtenir des informations pour l'imprimante: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Impossible d'obtenir des options d'imprimante: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Impossible de modifier l'imprimante: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Impossible de faire une pause imprimante: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Impossible d'imprimer '%s': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Impossible de reprendre l'imprimante: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Impossible de définir l'imprimante par défaut: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Impossible de fermer le serveur: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Impossible de démarrer le serveur: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Impossible d'écrire au fichier temporaire: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Option inconnue '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Option inconnue '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Sous-commande inconnue '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Système URI non soutenu '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Warning - user credentials are not supported in URIs.\";\n" "\", Borderless\" = \", Borderless\";\n" "\"A printer with that name already exists.\" = \"Une imprimante avec ce nom existe déjà.\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"Add Printer\";\n" "\"Admin Group\" = \"Groupe Admin\";\n" "\"Afghanistan\" = \"Afghanistan\";\n" "\"Albania\" = \"Albanie\";\n" "\"Algeria\" = \"Algérie\";\n" "\"American Samoa\" = \"Samoa américaines\";\n" "\"Andorra\" = \"Andorre\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarctique\";\n" "\"Antigua and Barbuda\" = \"Antigua-et-Barbuda\";\n" "\"Argentina\" = \"Argentine\";\n" "\"Armenia\" = \"Arménie\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australie\";\n" "\"Austria\" = \"Autriche\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Auto-Detect Driver\";\n" "\"Azerbaijan\" = \"Azerbaïdjan\";\n" "\"Bad administration group.\" = \"Bad administration group.\";\n" "\"Bad port number.\" = \"Bad port number.\";\n" "\"Bad print group.\" = \"Bad print group.\";\n" "\"Bad printer defaults.\" = \"Bad printer defaults.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahreïn\";\n" "\"Bangladesh\" = \"Bangladesh\";\n" "\"Barbados\" = \"Barbade\";\n" "\"Belarus\" = \"Bélarus\";\n" "\"Belgium\" = \"Belgique\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Bénin\";\n" "\"Bermuda\" = \"Bermudes\";\n" "\"Bhutan\" = \"Bhoutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivie (État plurinational de)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius et Saba\";\n" "\"Borderless\" = \"Borderless\";\n" "\"Bosnia and Herzegovina\" = \"Bosnie-Herzégovine\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Bouvet Island\";\n" "\"Brazil\" = \"Brésil\";\n" "\"British Indian Ocean Territory\" = \"British Indian Ocean Territory\";\n" "\"Brunei Darussalam\" = \"Brunéi Darussalam\";\n" "\"Bulgaria\" = \"Bulgarie\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cabo Verde\";\n" "\"Cambodia\" = \"Cambodge\";\n" "\"Cameroon\" = \"Cameroun\";\n" "\"Canada\" = \"Canada\";\n" "\"Cancel All Jobs\" = \"Annuler tous les emplois\";\n" "\"Cancel Job\" = \"Annuler Job\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"Anniversaire\";\n" "\"Cayman Islands\" = \"Îles Caïmanes\";\n" "\"Central African Republic\" = \"République centrafricaine\";\n" "\"Certificate created.\" = \"Certificat créé.\";\n" "\"Certificate installed.\" = \"Certificat installé.\";\n" "\"Certificate request created.\" = \"Demande de certificat créée.\";\n" "\"Chad\" = \"Tchad\";\n" "\"Change Access Password\" = \"Change Access Password\";\n" "\"Change Log Level\" = \"Change Log Level\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"Change Wi-Fi Network\";\n" "\"Changes Saved.\" = \"Changements enregistrés.\";\n" "\"Changes saved.\" = \"Changements enregistrés.\";\n" "\"Chile\" = \"Chili\";\n" "\"China\" = \"Chine\";\n" "\"Christmas Island\" = \"Christmas Island\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"Îles de Coco (Keeling)\";\n" "\"Colombia\" = \"Colombie\";\n" "\"Comoros\" = \"Comores\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"Configuration\";\n" "\"Configure Media\" = \"Configurer Media\";\n" "\"Confirm Cancel All\" = \"Confirmer Annuler Tout\";\n" "\"Confirm Delete Printer\" = \"Confirmer Supprimer l'imprimante\";\n" "\"Congo\" = \"Congo\";\n" "\"Congo, Democratic Republic of the\" = \"Congo, République démocratique du Congo\";\n" "\"Contact\" = \"Contact\";\n" "\"Cook Islands\" = \"Îles Cook\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Créer une demande de signature de certificat\";\n" "\"Create New Certificate\" = \"Créer un nouveau certificat\";\n" "\"Create New TLS Certificate\" = \"Créer un nouveau certificat TLS\";\n" "\"Create TLS Certificate Request\" = \"Créer TLS Demande de certificat\";\n" "\"Croatia\" = \"Croatie\";\n" "\"Cuba\" = \"Cuba\";\n" "\"Curaçao\" = \"Curaao\";\n" "\"Current Password\" = \"Mot de passe actuel\";\n" "\"Custom Size\" = \"Taille personnalisée\";\n" "\"Cyprus\" = \"Chypre\";\n" "\"Czechia\" = \"Czechia\";\n" "\"Côte d'Ivoire\" = \"Cte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Nom de service\";\n" "\"Debugging\" = \"Debugging\";\n" "\"Default printer set.\" = \"Imprimante par défaut.\";\n" "\"Delete\" = \"Supprimer\";\n" "\"Delete Printer\" = \"Supprimer Printer\";\n" "\"Denmark\" = \"Danemark\";\n" "\"Djibouti\" = \"Djibouti\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"Dominique\";\n" "\"Dominican Republic\" = \"République dominicaine\";\n" "\"Download Certificate Request File\" = \"Télécharger le fichier Demande de certificat\";\n" "\"Ecuador\" = \"Équateur\";\n" "\"Egypt\" = \"Égypte\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Guinée équatoriale\";\n" "\"Eritrea\" = \"Érythrée\";\n" "\"Errors\" = \"Erreurs\";\n" "\"Estonia\" = \"Estonie\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Éthiopie\";\n" "\"Falkland Islands (Malvinas)\" = \"Îles Falkland (Malvinas)\";\n" "\"Faroe Islands\" = \"Îles Féroé\";\n" "\"Fatal Errors/Conditions\" = \"Erreurs/Conditions Fatales\";\n" "\"Fiji\" = \"Fidji\";\n" "\"Finland\" = \"Finlande\";\n" "\"France\" = \"France\";\n" "\"French Guiana\" = \"Guyane française\";\n" "\"French Polynesia\" = \"Polynésie française\";\n" "\"French Southern Territories\" = \"Territoires du Sud\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambie\";\n" "\"Georgia\" = \"Géorgie\";\n" "\"Germany\" = \"Allemagne\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Grèce\";\n" "\"Greenland\" = \"Groenland\";\n" "\"Grenada\" = \"Grenade\";\n" "\"Group changes saved.\" = \"Changements de groupe enregistrés.\";\n" "\"Guadeloupe\" = \"Guadeloupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernesey\";\n" "\"Guinea\" = \"Guinée\";\n" "\"Guinea-Bissau\" = \"Guinée-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haïti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island et McDonald Islands\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"Saint-Siège\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Hostname\";\n" "\"Human-Readable Location\" = \"Emplacement lisible\";\n" "\"Hungary\" = \"Hongrie\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"Islande\";\n" "\"Identify Printer\" = \"Identifier l'imprimante\";\n" "\"India\" = \"Inde\";\n" "\"Indonesia\" = \"Indonésie\";\n" "\"Informational\" = \"Informational\";\n" "\"Install TLS Certificate\" = \"Installez TLS Certificat\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"Invalid Job ID.\";\n" "\"Invalid certificate or private key.\" = \"Certificat invalide ou clé privée.\";\n" "\"Invalid form data.\" = \"Données de forme incorrectes.\";\n" "\"Invalid form submission.\" = \"Demande de formulaire non valide.\";\n" "\"Invalid job ID.\" = \"Invalide.\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (République islamique d ' )\";\n" "\"Iraq\" = \"Iraq\";\n" "\"Ireland\" = \"Irlande\";\n" "\"Isle of Man\" = \"Isle of Man\";\n" "\"Israel\" = \"Israël\";\n" "\"Italy\" = \"Italie\";\n" "\"Jamaica\" = \"Jamaïque\";\n" "\"Japan\" = \"Japon\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Job\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"Jobs\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"Jordanie\";\n" "\"Kazakhstan\" = \"Kazakhstan\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Corée (République populaire démocratique de)\";\n" "\"Korea, Republic of\" = \"République de Corée\";\n" "\"Kuwait\" = \"Koweït\";\n" "\"Kyrgyzstan\" = \"Kirghizistan\";\n" "\"Landscape\" = \"Paysage\";\n" "\"Lao People's Democratic Republic\" = \"République démocratique populaire lao\";\n" "\"Latvia\" = \"Lettonie\";\n" "\"Lebanon\" = \"Liban\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Niveau\";\n" "\"Liberia\" = \"Libéria\";\n" "\"Libya\" = \"Libye\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Lituanie\";\n" "\"Location\" = \"Lieu\";\n" "\"Log Level\" = \"Niveau de référence\";\n" "\"Logging\" = \"Logging\";\n" "\"Logs\" = \"Logs\";\n" "\"Luxembourg\" = \"Luxembourg\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagascar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malaisie\";\n" "\"Maldives\" = \"Maldives\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malte\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"Îles Marshall\";\n" "\"Martinique\" = \"Martinique\";\n" "\"Mauritania\" = \"Mauritanie\";\n" "\"Mauritius\" = \"Maurice\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Médias\";\n" "\"Mexico\" = \"Mexique\";\n" "\"Micronesia (Federated States of)\" = \"Micronésie (États fédérés de)\";\n" "\"Missing action.\" = \"Manque d'action.\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"La clé privée manquante.\";\n" "\"Moldova, Republic of\" = \"République de Moldova\";\n" "\"Monaco\" = \"Monaco\";\n" "\"Mongolia\" = \"Mongolie\";\n" "\"Montenegro\" = \"Monténégro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Maroc\";\n" "\"Mozambique\" = \"Mozambique\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Nom\";\n" "\"Namibia\" = \"Namibie\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Népal\";\n" "\"Netherlands\" = \"Pays-Bas\";\n" "\"Network\" = \"Network\";\n" "\"Network Printer\" = \"Imprimeur réseau\";\n" "\"Networking\" = \"Networking\";\n" "\"New Caledonia\" = \"Nouvelle-Calédonie\";\n" "\"New Zealand\" = \"Nouvelle-Zélande\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigéria\";\n" "\"Niue\" = \"Nioué\";\n" "\"No default printer set.\" = \"Aucun jeu d'imprimante par défaut.\";\n" "\"No jobs in history.\" = \"Pas de travail dans l'histoire.\";\n" "\"Norfolk Island\" = \"Norfolk Island\";\n" "\"North Macedonia\" = \"Macédoine\";\n" "\"Northern Mariana Islands\" = \"Îles Mariannes du Nord\";\n" "\"Norway\" = \"Norvège\";\n" "\"Not set\" = \"Pas réglé\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Options:\";\n" "\"Organization\" = \"Organisation\";\n" "\"Organization Name\" = \"Nom de l ' Organisation\";\n" "\"Other Settings\" = \"Autres paramètres\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palaos\";\n" "\"Palestine, State of\" = \"Palestine, État\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papouasie-Nouvelle-Guinée\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Mot de passe\";\n" "\"Password changed.\" = \"Le mot de passe a changé.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Le mot de passe doit avoir au moins huit caractères de long et contenir au moins une lettre majuscule, une lettre minuscule et un chiffre.\";\n" "\"Passwords do not match.\" = \"Les mots de passe ne correspondent pas.\";\n" "\"Pause Printing\" = \"Impression sur la douleur\";\n" "\"Peru\" = \"Pérou\";\n" "\"Philippines\" = \"Philippines\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Veuillez saisir un nom d'hôte ou une adresse IP pour l'imprimante.\";\n" "\"Please enter a printer name.\" = \"Veuillez entrer un nom d'imprimante.\";\n" "\"Please select a device.\" = \"Veuillez sélectionner un appareil.\";\n" "\"Please select a driver.\" = \"Veuillez sélectionner un pilote.\";\n" "\"Please select a valid log level.\" = \"Veuillez sélectionner un niveau de journal valide.\";\n" "\"Poland\" = \"Pologne\";\n" "\"Portrait\" = \"Portrait\";\n" "\"Portugal\" = \"Portugal\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"Groupe d ' impression\";\n" "\"Print Test Page\" = \"Page d ' essai\";\n" "\"Print job options:\" = \"Imprimer les options d'emploi:\";\n" "\"Printer identified.\" = \"Imprimante identifiée.\";\n" "\"Printer is currently active.\" = \"L'imprimante est actuellement active.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Les noms d'imprimante doivent commencer par une lettre ou un soulignement et ne peuvent contenir des caractères spéciaux.\";\n" "\"Printer options:\" = \"Options d'impression:\";\n" "\"Printer paused.\" = \"Imprimante pause.\";\n" "\"Printer pausing.\" = \"Imprimante.\";\n" "\"Printer resuming.\" = \"L'imprimante reprend.\";\n" "\"Printers\" = \"Imprimantes\";\n" "\"Printing Defaults\" = \"Défauts d'impression\";\n" "\"Puerto Rico\" = \"Porto Rico\";\n" "\"Qatar\" = \"Qatar\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"Reprint Job\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"Récupérer l'impression\";\n" "\"Reverse Landscape\" = \"Paysage\";\n" "\"Reverse Portrait\" = \"Portrait\";\n" "\"Romania\" = \"Roumanie\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Courant, %s depuis %s %s .\";\n" "\"Russian Federation\" = \"Fédération de Russie\";\n" "\"Rwanda\" = \"Rwanda\";\n" "\"Réunion\" = \"Runion\";\n" "\"Saint Barthélemy\" = \"Saint-Barthlemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Sainte-Hélène, Ascension et Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint-Kitts-et-Nevis\";\n" "\"Saint Lucia\" = \"Sainte-Lucie\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (partie française)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre et Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint-Vincent-et-les Grenadines\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"Saint-Marin\";\n" "\"Sao Tome and Principe\" = \"Sao Tomé-et-Principe\";\n" "\"Saudi Arabia\" = \"Saudi Arabia\";\n" "\"Save Changes\" = \"Save Changes\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"Sécurité\";\n" "\"Select Driver\" = \"Sélectionnez le pilote\";\n" "\"Senegal\" = \"Sénégal\";\n" "\"Serbia\" = \"Serbie\";\n" "\"Server is not running.\" = \"Le serveur ne fonctionne pas.\";\n" "\"Set Access Password\" = \"Set Access Password\";\n" "\"Set as Default\" = \"Par défaut\";\n" "\"Seychelles\" = \"Seychelles\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapour\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (partie néerlandaise)\";\n" "\"Slovakia\" = \"Slovaquie\";\n" "\"Slovenia\" = \"Slovénie\";\n" "\"Solomon Islands\" = \"Îles Salomon\";\n" "\"Somalia\" = \"Somalie\";\n" "\"South Africa\" = \"Afrique du Sud\";\n" "\"South Georgia and the South Sandwich Islands\" = \"Géorgie du Sud et îles Sandwich du Sud\";\n" "\"South Sudan\" = \"Soudan du Sud\";\n" "\"Spain\" = \"Espagne\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"État\";\n" "\"Sub-commands:\" = \"Sous-commandes :\";\n" "\"Sudan\" = \"Soudan\";\n" "\"Supplies\" = \"Fournitures\";\n" "\"Suriname\" = \"Suriname\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard et Jan Mayen\";\n" "\"Sweden\" = \"Suède\";\n" "\"Switzerland\" = \"Suisse\";\n" "\"Syrian Arab Republic\" = \"République arabe syrienne\";\n" "\"Taiwan, Province of China\" = \"Taiwan, Province de Chine\";\n" "\"Tajikistan\" = \"Tadjikistan\";\n" "\"Tanzania, United Republic of\" = \"République-Unie de Tanzanie\";\n" "\"Test page printed.\" = \"Page d'essai imprimée.\";\n" "\"Thailand\" = \"Thaïlande\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Ce formulaire crée une demande de signature de certificat (SRC) que vous pouvez envoyer à une autorité de certification (CA) pour obtenir un certificat de SDF fiable. La clé privée est sauvegardée séparément pour utilisation avec le certificat que vous obtenez de l'AC.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Ce formulaire crée un nouveau certificat TLS autosigné pour l'impression sécurisée. Les certificats autosignés ne sont pas automatiquement fiables par les navigateurs Web.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Ce formulaire installera un certificat TLS de confiance que vous avez obtenu auprès d'une autorité de certification (CA). Une fois installé, il sera utilisé immédiatement.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokélaou\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinité-et-Tobago\";\n" "\"Tunisia\" = \"Tunisie\";\n" "\"Turkey\" = \"Turquie\";\n" "\"Turkmenistan\" = \"Turkménistan\";\n" "\"Turks and Caicos Islands\" = \"Îles Turques et Caïques\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Ouganda\";\n" "\"Ukraine\" = \"Ukraine\";\n" "\"Unable to access test print file.\" = \"Impossible d'accéder au fichier d'impression de test.\";\n" "\"Unable to copy print job.\" = \"Incapable de copier le travail.\";\n" "\"Unable to create certificate request.\" = \"Impossible de créer une demande de certificat.\";\n" "\"Unable to create certificate.\" = \"Impossible de créer un certificat.\";\n" "\"Unable to create test print job.\" = \"Impossible de créer un travail d'impression test.\";\n" "\"Unable to identify printer.\" = \"Incapable d'identifier l'imprimante.\";\n" "\"Unable to lookup address.\" = \"Incapable de regarder l'adresse.\";\n" "\"Unable to use that driver.\" = \"Incapable d'utiliser ce conducteur.\";\n" "\"United Arab Emirates\" = \"Émirats arabes unis\";\n" "\"United Kingdom\" = \"Royaume-Uni\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Royaume-Uni de Grande-Bretagne et d ' Irlande du Nord\";\n" "\"United States Minor Outlying Islands\" = \"United States Minor Outlying Islands\";\n" "\"United States of America\" = \"États-Unis d ' Amérique\";\n" "\"Unknown\" = \"Inconnu\";\n" "\"Unknown action.\" = \"Action inconnue.\";\n" "\"Unknown form action.\" = \"Inconnue.\";\n" "\"Unknown form request.\" = \"Demande de formulaire inconnue.\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Utilisation: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\";\n" "\"Use My Position\" = \"Utiliser ma position\";\n" "\"Users\" = \"Utilisateurs\";\n" "\"Uzbekistan\" = \"Ouzbékistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (République bolivarienne du)\";\n" "\"Version %s\" = \"Version %s\";\n" "\"Viet Nam\" = \"Viet Nam\";\n" "\"View Logs\" = \"Voir les logos\";\n" "\"Virgin Islands (British)\" = \"Îles Vierges britanniques\";\n" "\"Virgin Islands (U.S.)\" = \"Îles Vierges américaines\";\n" "\"Wallis and Futuna\" = \"Wallis et Futuna\";\n" "\"Warning\" = \"Avertissement\";\n" "\"Western Sahara\" = \"Sahara occidental\";\n" "\"Wi-Fi Configuration\" = \"Configuration Wi-Fi\";\n" "\"Wi-Fi Network\" = \"Wi-Fi Network\";\n" "\"Width\" = \"Largeur\";\n" "\"Wrong old password.\" = \"Un vieux mot de passe.\";\n" "\"Yemen\" = \"Yémen\";\n" "\"Zambia\" = \"Zambie\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Nombre de copies\";\n" "\"default printer\" = \"imprimante par défaut\";\n" "\"finishings\" = \"Finisher\";\n" "\"finishings.10\" = \"Fold\";\n" "\"finishings.100\" = \"Z pli\";\n" "\"finishings.101\" = \"Ingénierie pli Z\";\n" "\"finishings.11\" = \"Coupe\";\n" "\"finishings.12\" = \"Bale\";\n" "\"finishings.13\" = \"Booklet maker\";\n" "\"finishings.15\" = \"Coat\";\n" "\"finishings.16\" = \"Laminate\";\n" "\"finishings.20\" = \"Staple top gauche\";\n" "\"finishings.21\" = \"En bas gauche\";\n" "\"finishings.22\" = \"Staple top right\";\n" "\"finishings.23\" = \"En bas droit\";\n" "\"finishings.24\" = \"Couture gauche\";\n" "\"finishings.25\" = \"Point de bord\";\n" "\"finishings.26\" = \"Couture droite\";\n" "\"finishings.27\" = \"Point inférieur\";\n" "\"finishings.28\" = \"2 agrafes à gauche\";\n" "\"finishings.29\" = \"2 agrafes sur le dessus\";\n" "\"finishings.3\" = \"None\";\n" "\"finishings.30\" = \"2 agrafes à droite\";\n" "\"finishings.31\" = \"2 agrafes en bas\";\n" "\"finishings.32\" = \"3 agrafes à gauche\";\n" "\"finishings.33\" = \"3 agrafes sur le dessus\";\n" "\"finishings.34\" = \"3 agrafes à droite\";\n" "\"finishings.35\" = \"3 agrafes en bas\";\n" "\"finishings.4\" = \"Staple\";\n" "\"finishings.5\" = \"Punch\";\n" "\"finishings.50\" = \"Bind gauche\";\n" "\"finishings.51\" = \"Bind top\";\n" "\"finishings.52\" = \"Bind right\";\n" "\"finishings.53\" = \"Bind bottom\";\n" "\"finishings.6\" = \"Couverture\";\n" "\"finishings.60\" = \"Couper après chaque page\";\n" "\"finishings.61\" = \"Couper après chaque document\";\n" "\"finishings.62\" = \"Couper après chaque set\";\n" "\"finishings.63\" = \"Couper après le travail\";\n" "\"finishings.7\" = \"Bind\";\n" "\"finishings.70\" = \"Punch top left\";\n" "\"finishings.71\" = \"Punch bottom left\";\n" "\"finishings.72\" = \"Punch top right\";\n" "\"finishings.73\" = \"Poinçon bas droit\";\n" "\"finishings.74\" = \"2 trous à gauche\";\n" "\"finishings.75\" = \"Top 2 trous\";\n" "\"finishings.76\" = \"2 trous à droite\";\n" "\"finishings.77\" = \"2 trous en bas\";\n" "\"finishings.78\" = \"3 trous à gauche\";\n" "\"finishings.79\" = \"Poinçon 3 trous\";\n" "\"finishings.8\" = \"Triste couture\";\n" "\"finishings.80\" = \"3 trous à droite\";\n" "\"finishings.81\" = \"3 trous en bas\";\n" "\"finishings.82\" = \"4 trous à gauche\";\n" "\"finishings.83\" = \"Top 4 trous\";\n" "\"finishings.84\" = \"4 trous à droite\";\n" "\"finishings.85\" = \"4 trous en bas\";\n" "\"finishings.86\" = \"Poinçon multi trous à gauche\";\n" "\"finishings.87\" = \"Poinçon multi trous\";\n" "\"finishings.88\" = \"Poinçon multifonctions à droite\";\n" "\"finishings.89\" = \"Poinçon multi-trouilles\";\n" "\"finishings.9\" = \"Bordure\";\n" "\"finishings.90\" = \"Repli d ' accord\";\n" "\"finishings.91\" = \"Double porte pliant\";\n" "\"finishings.92\" = \"Porte pliant\";\n" "\"finishings.93\" = \"Demi pli\";\n" "\"finishings.94\" = \"Half Z\";\n" "\"finishings.95\" = \"Repli de la porte gauche\";\n" "\"finishings.96\" = \"Lit pli\";\n" "\"finishings.97\" = \"Repli parallèle\";\n" "\"finishings.98\" = \"Tableau pli\";\n" "\"finishings.99\" = \"Tour droit\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"Arrête.\";\n" "\"job-state-reasons.compression-error\" = \"Erreur de décompression.\";\n" "\"job-state-reasons.document-format-error\" = \"Erreur de format de document.\";\n" "\"job-state-reasons.document-password-error\" = \"Erreur de mot de passe.\";\n" "\"job-state-reasons.document-permission-error\" = \"Erreur de permission de document.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Document erreur imprimable.\";\n" "\"job-state-reasons.errors-detected\" = \"Erreurs détectées.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Annulé à l'imprimante.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Annulé par l'utilisateur.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Imprimé.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Imprimé avec des erreurs.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Imprimé avec des avertissements.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Données insuffisantes.\";\n" "\"job-state-reasons.job-fetchable\" = \"Incroyable.\";\n" "\"job-state-reasons.job-incoming\" = \"J'arrive.\";\n" "\"job-state-reasons.job-printing\" = \"Impression.\";\n" "\"job-state-reasons.job-queued\" = \"Préparer à imprimer.\";\n" "\"job-state-reasons.job-spooling\" = \"Covoiturage.\";\n" "\"job-state-reasons.none\" = \"En attente.\";\n" "\"job-state-reasons.printer-stopped\" = \"Imprimante hors ligne.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Imprimante partiellement arrêtée.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Arrête.\";\n" "\"job-state-reasons.queued-in-device\" = \"Prêt.\";\n" "\"job-state-reasons.warnings-detected\" = \"Avertissements détectés.\";\n" "\"job-state.3\" = \"En attente\";\n" "\"job-state.4\" = \"tenue\";\n" "\"job-state.5\" = \"Traitement\";\n" "\"job-state.6\" = \"Arrêté\";\n" "\"job-state.7\" = \"Annulé\";\n" "\"job-state.8\" = \"Avortée\";\n" "\"job-state.9\" = \"Complété\";\n" "\"joining\" = \"rejoindre\";\n" "\"media\" = \"Médias\";\n" "\"media-col\" = \"Médias\";\n" "\"media-size\" = \"Taille des médias\";\n" "\"media-size-name\" = \"Taille des médias\";\n" "\"media-source\" = \"Input Tray\";\n" "\"media-source.alternate\" = \"Alternate\";\n" "\"media-source.alternate-roll\" = \"Roulement alternatif\";\n" "\"media-source.auto\" = \"Automatique\";\n" "\"media-source.bottom\" = \"Bottom\";\n" "\"media-source.by-pass-tray\" = \"Plateau polyvalent\";\n" "\"media-source.center\" = \"Center\";\n" "\"media-source.disc\" = \"Disc\";\n" "\"media-source.envelope\" = \"Enveloppe\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Grande capacité\";\n" "\"media-source.left\" = \"Gauche\";\n" "\"media-source.main\" = \"Main\";\n" "\"media-source.main-roll\" = \"Roulement principal\";\n" "\"media-source.manual\" = \"Manuel\";\n" "\"media-source.middle\" = \"Moyen-Orient\";\n" "\"media-source.photo\" = \"Photo\";\n" "\"media-source.rear\" = \"Arrière\";\n" "\"media-source.right\" = \"Droit\";\n" "\"media-source.roll-1\" = \"Roll 1\";\n" "\"media-source.roll-10\" = \"Roll 10\";\n" "\"media-source.roll-2\" = \"Roll 2\";\n" "\"media-source.roll-3\" = \"Roll 3\";\n" "\"media-source.roll-4\" = \"Roll 4\";\n" "\"media-source.roll-5\" = \"Roll 5\";\n" "\"media-source.roll-6\" = \"Roll 6\";\n" "\"media-source.roll-7\" = \"Roll 7\";\n" "\"media-source.roll-8\" = \"Roll 8\";\n" "\"media-source.roll-9\" = \"Roll 9\";\n" "\"media-source.side\" = \"Side\";\n" "\"media-source.top\" = \"Top\";\n" "\"media-source.tray-1\" = \"Tray 1\";\n" "\"media-source.tray-10\" = \"Tray 10\";\n" "\"media-source.tray-11\" = \"Tray 11\";\n" "\"media-source.tray-12\" = \"Tray 12\";\n" "\"media-source.tray-13\" = \"Tray 13\";\n" "\"media-source.tray-14\" = \"Tray 14\";\n" "\"media-source.tray-15\" = \"Tray 15\";\n" "\"media-source.tray-16\" = \"Tray 16\";\n" "\"media-source.tray-17\" = \"Tray 17\";\n" "\"media-source.tray-18\" = \"Tray 18\";\n" "\"media-source.tray-19\" = \"Tray 19\";\n" "\"media-source.tray-2\" = \"Tray 2\";\n" "\"media-source.tray-20\" = \"Tray 20\";\n" "\"media-source.tray-3\" = \"Tray 3\";\n" "\"media-source.tray-4\" = \"Tray 4\";\n" "\"media-source.tray-5\" = \"Tray 5\";\n" "\"media-source.tray-6\" = \"Tray 6\";\n" "\"media-source.tray-7\" = \"Tray 7\";\n" "\"media-source.tray-8\" = \"Tray 8\";\n" "\"media-source.tray-9\" = \"Tray 9\";\n" "\"media-tracking\" = \"Suivi des médias\";\n" "\"media-tracking.continuous\" = \"Continuous\";\n" "\"media-tracking.gap\" = \"Gap\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Type de média\";\n" "\"media-type.aluminum\" = \"Aluminium\";\n" "\"media-type.auto\" = \"Automatique\";\n" "\"media-type.back-print-film\" = \"Film de retour\";\n" "\"media-type.cardboard\" = \"Cardboard\";\n" "\"media-type.cardstock\" = \"Cardstock\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Continuous\";\n" "\"media-type.continuous-long\" = \"Longtemps continu\";\n" "\"media-type.continuous-short\" = \"Short continu\";\n" "\"media-type.corrugated-board\" = \"Plan d ' action\";\n" "\"media-type.disc\" = \"Disque optique\";\n" "\"media-type.disc-glossy\" = \"Disque optique brillant\";\n" "\"media-type.disc-high-gloss\" = \"Disque optique à haute brillance\";\n" "\"media-type.disc-matte\" = \"Disque optique Matte\";\n" "\"media-type.disc-satin\" = \"Disque optique satin\";\n" "\"media-type.disc-semi-gloss\" = \"Disque optique semi-brillant\";\n" "\"media-type.double-wall\" = \"Double mur\";\n" "\"media-type.dry-film\" = \"Film sec\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Feuille d ' emballage\";\n" "\"media-type.end-board\" = \"End board\";\n" "\"media-type.envelope\" = \"Enveloppe\";\n" "\"media-type.envelope-archival\" = \"Enveloppe d ' archivage\";\n" "\"media-type.envelope-bond\" = \"Enveloppe d ' obligations\";\n" "\"media-type.envelope-coated\" = \"Enveloppe revêtue\";\n" "\"media-type.envelope-cotton\" = \"Enveloppe de coton\";\n" "\"media-type.envelope-fine\" = \"Enveloppe fine\";\n" "\"media-type.envelope-heavyweight\" = \"Enveloppe lourde\";\n" "\"media-type.envelope-inkjet\" = \"Enveloppe de jet d ' encre\";\n" "\"media-type.envelope-lightweight\" = \"Enveloppe légère\";\n" "\"media-type.envelope-plain\" = \"Enveloppe plaine\";\n" "\"media-type.envelope-preprinted\" = \"Enveloppe préimprimée\";\n" "\"media-type.envelope-window\" = \"Enveloppe de fenêtre\";\n" "\"media-type.fabric\" = \"Tissu\";\n" "\"media-type.fabric-archival\" = \"Tissu d ' archivage\";\n" "\"media-type.fabric-glossy\" = \"Tissu brillant\";\n" "\"media-type.fabric-high-gloss\" = \"Tissu brillant\";\n" "\"media-type.fabric-matte\" = \"Tissu mat\";\n" "\"media-type.fabric-semi-gloss\" = \"Tissu semi-gloss\";\n" "\"media-type.fabric-waterproof\" = \"Tissu étanche\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Base Flexo\";\n" "\"media-type.flexo-photo-polymer\" = \"Flexo photo polymère\";\n" "\"media-type.flute\" = \"Flute\";\n" "\"media-type.foil\" = \"Foil\";\n" "\"media-type.full-cut-tabs\" = \"onglets de coupe complète\";\n" "\"media-type.glass\" = \"Verre\";\n" "\"media-type.glass-colored\" = \"Verre coloré\";\n" "\"media-type.glass-opaque\" = \"Verre opaque\";\n" "\"media-type.glass-surfaced\" = \"Verre en surface\";\n" "\"media-type.glass-textured\" = \"Verre texturé\";\n" "\"media-type.gravure-cylinder\" = \"Boutet d ' échappement\";\n" "\"media-type.image-setter-paper\" = \"Image setter paper\";\n" "\"media-type.imaging-cylinder\" = \"Cylindre d ' image\";\n" "\"media-type.labels\" = \"Étiquettes\";\n" "\"media-type.labels-colored\" = \"Étiquettes colorées\";\n" "\"media-type.labels-glossy\" = \"Étiquettes brillantes\";\n" "\"media-type.labels-high-gloss\" = \"Étiquettes haute brillance\";\n" "\"media-type.labels-inkjet\" = \"Étiquettes à jet d ' encre\";\n" "\"media-type.labels-matte\" = \"Étiquettes Matte\";\n" "\"media-type.labels-permanent\" = \"Étiquettes permanentes\";\n" "\"media-type.labels-satin\" = \"labels satins\";\n" "\"media-type.labels-security\" = \"Étiquettes de sécurité\";\n" "\"media-type.labels-semi-gloss\" = \"Étiquettes semi-brillantes\";\n" "\"media-type.laminating-foil\" = \"Feuille de plastification\";\n" "\"media-type.letterhead\" = \"Letterhead\";\n" "\"media-type.metal\" = \"Métal\";\n" "\"media-type.metal-glossy\" = \"Metal glossy\";\n" "\"media-type.metal-high-gloss\" = \"Metal high gloss\";\n" "\"media-type.metal-matte\" = \"Métal mat\";\n" "\"media-type.metal-satin\" = \"Metal satin\";\n" "\"media-type.metal-semi-gloss\" = \"Metal semi gloss\";\n" "\"media-type.mounting-tape\" = \"Bande de montage\";\n" "\"media-type.multi-layer\" = \"Multi calque\";\n" "\"media-type.multi-part-form\" = \"Forme multipartite\";\n" "\"media-type.other\" = \"Autres\";\n" "\"media-type.paper\" = \"Paper\";\n" "\"media-type.photographic\" = \"Photo paper\";\n" "\"media-type.photographic-archival\" = \"Archival photographique\";\n" "\"media-type.photographic-film\" = \"Photo film\";\n" "\"media-type.photographic-glossy\" = \"Papier photo Glossy\";\n" "\"media-type.photographic-high-gloss\" = \"Papier photo de haute brillance\";\n" "\"media-type.photographic-matte\" = \"Matte photo paper\";\n" "\"media-type.photographic-satin\" = \"Papier photo satin\";\n" "\"media-type.photographic-semi-gloss\" = \"Papier photo semi-gloss\";\n" "\"media-type.plastic\" = \"Plastique\";\n" "\"media-type.plastic-archival\" = \"Archival plastique\";\n" "\"media-type.plastic-colored\" = \"Couleur plastique\";\n" "\"media-type.plastic-glossy\" = \"Matière plastique brillante\";\n" "\"media-type.plastic-high-gloss\" = \"Plastique haute brillance\";\n" "\"media-type.plastic-matte\" = \"mat plastique\";\n" "\"media-type.plastic-satin\" = \"Satin plastique\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastique semi brillant\";\n" "\"media-type.plate\" = \"Plate-forme\";\n" "\"media-type.polyester\" = \"Polyester\";\n" "\"media-type.pre-cut-tabs\" = \"onglets pré-coupés\";\n" "\"media-type.roll\" = \"Roll\";\n" "\"media-type.screen\" = \"Écran\";\n" "\"media-type.screen-paged\" = \"Écran paged\";\n" "\"media-type.self-adhesive\" = \"Autocollant\";\n" "\"media-type.self-adhesive-film\" = \"Film adhésif auto-adhésif\";\n" "\"media-type.shrink-foil\" = \"Feuille de film\";\n" "\"media-type.single-face\" = \"Face unique\";\n" "\"media-type.single-wall\" = \"Mur unique\";\n" "\"media-type.sleeve\" = \"Sleeve\";\n" "\"media-type.stationery\" = \"Papeterie\";\n" "\"media-type.stationery-archival\" = \"Arche de papeterie\";\n" "\"media-type.stationery-coated\" = \"Coated paper\";\n" "\"media-type.stationery-cotton\" = \"Coton papeterie\";\n" "\"media-type.stationery-fine\" = \"Vellum paper\";\n" "\"media-type.stationery-heavyweight\" = \"Papier lourd\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Stationnement lourd enduit\";\n" "\"media-type.stationery-inkjet\" = \"Papier à jet d'encre papeterie\";\n" "\"media-type.stationery-letterhead\" = \"Letterhead\";\n" "\"media-type.stationery-lightweight\" = \"Papier léger\";\n" "\"media-type.stationery-preprinted\" = \"Document préimprimé\";\n" "\"media-type.stationery-prepunched\" = \"Papier poinçonné\";\n" "\"media-type.tab-stock\" = \"Stock\";\n" "\"media-type.tractor\" = \"Tractor\";\n" "\"media-type.transfer\" = \"Transfert\";\n" "\"media-type.transparency\" = \"Transparence\";\n" "\"media-type.triple-wall\" = \"Mur triple\";\n" "\"media-type.wet-film\" = \"Film humide\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 ou US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Enveloppe\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Envelope\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Enveloppe\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Enveloppe\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Enveloppe\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Enveloppe\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Enveloppe\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Enveloppe\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Enveloppe\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Enveloppe\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Enveloppe\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Enveloppe\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Enveloppe\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Enveloppe\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Enveloppe\";\n" "\"media.iso_dl_110x220mm\" = \"DL Enveloppe\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Executive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Enveloppe Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Enveloppe Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Enveloppe Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Enveloppe Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Enveloppe Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Enveloppe Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Répondre Postcard\";\n" "\"media.jpn_you4_105x235mm\" = \"Enveloppe Vous 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Enveloppe A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Enveloppe C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Executive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"European Fanfold\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"Fanfold\";\n" "\"media.na_foolscap_8.5x13in\" = \"Foolscap\";\n" "\"media.na_invoice_5.5x8.5in\" = \"État\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"Lettre américaine (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"Lettre américaine (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"US Letter\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Monarque d ' enveloppe\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Enveloppe #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Enveloppe #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Enveloppe #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Enveloppe #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Enveloppe #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Enveloppe personnelle\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (Special)\";\n" "\"media.om_invite_220x220mm\" = \"Invitation d ' enveloppe\";\n" "\"media.om_italian_110x230mm\" = \"Enveloppe italienne\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389m m\";\n" "\"media.om_postfix_114x229mm\" = \"Envelope Postfix\";\n" "\"media.prc_10_324x458mm\" = \"Enveloppe chinoise #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chinois 16k\";\n" "\"media.prc_1_102x165mm\" = \"Enveloppe chinoise #1\";\n" "\"media.prc_2_102x176mm\" = \"Enveloppe chinoise #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chinois 32k\";\n" "\"media.prc_3_125x176mm\" = \"Enveloppe chinoise #3\";\n" "\"media.prc_4_110x208mm\" = \"Enveloppe chinoise #4\";\n" "\"media.prc_5_110x220mm\" = \"Enveloppe chinoise #5\";\n" "\"media.prc_6_120x320mm\" = \"Enveloppe chinoise #6\";\n" "\"media.prc_7_160x230mm\" = \"Enveloppe chinoise #7\";\n" "\"media.prc_8_120x309mm\" = \"Enveloppe chinoise #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"non configuré\";\n" "\"not visible\" = \"non visible\";\n" "\"off\" = \"Dégage.\";\n" "\"on\" = \"on\";\n" "\"orientation-requested\" = \"Orientation\";\n" "\"orientation-requested.3\" = \"Portrait\";\n" "\"orientation-requested.4\" = \"Paysage\";\n" "\"orientation-requested.5\" = \"Paysage inversé\";\n" "\"orientation-requested.6\" = \"Portrait inversé\";\n" "\"orientation-requested.7\" = \"None\";\n" "\"output-bin\" = \"Sortie Tray\";\n" "\"output-bin.auto\" = \"Automatique\";\n" "\"output-bin.bottom\" = \"Bottom\";\n" "\"output-bin.center\" = \"Center\";\n" "\"output-bin.face-down\" = \"Face à terre\";\n" "\"output-bin.face-up\" = \"Face à face\";\n" "\"output-bin.large-capacity\" = \"Grande capacité\";\n" "\"output-bin.left\" = \"Gauche\";\n" "\"output-bin.mailbox-1\" = \"Mailbox 1\";\n" "\"output-bin.mailbox-10\" = \"Mailbox 10\";\n" "\"output-bin.mailbox-2\" = \"Mailbox 2\";\n" "\"output-bin.mailbox-3\" = \"Mailbox 3\";\n" "\"output-bin.mailbox-4\" = \"Mailbox 4\";\n" "\"output-bin.mailbox-5\" = \"Mailbox 5\";\n" "\"output-bin.mailbox-6\" = \"Mailbox 6\";\n" "\"output-bin.mailbox-7\" = \"Mailbox 7\";\n" "\"output-bin.mailbox-8\" = \"Mailbox 8\";\n" "\"output-bin.mailbox-9\" = \"Mailbox 9\";\n" "\"output-bin.middle\" = \"Moyen-Orient\";\n" "\"output-bin.my-mailbox\" = \"Ma boîte aux lettres\";\n" "\"output-bin.rear\" = \"Arrière\";\n" "\"output-bin.right\" = \"Droit\";\n" "\"output-bin.side\" = \"Side\";\n" "\"output-bin.stacker-1\" = \"Stacker 1\";\n" "\"output-bin.stacker-10\" = \"Stacker 10\";\n" "\"output-bin.stacker-2\" = \"Stacker 2\";\n" "\"output-bin.stacker-3\" = \"Stacker 3\";\n" "\"output-bin.stacker-4\" = \"Stacker 4\";\n" "\"output-bin.stacker-5\" = \"Stacker 5\";\n" "\"output-bin.stacker-6\" = \"Stacker 6\";\n" "\"output-bin.stacker-7\" = \"Stacker 7\";\n" "\"output-bin.stacker-8\" = \"Stacker 8\";\n" "\"output-bin.stacker-9\" = \"Stacker 9\";\n" "\"output-bin.top\" = \"Top\";\n" "\"output-bin.tray-1\" = \"Tray 1\";\n" "\"output-bin.tray-10\" = \"Tray 10\";\n" "\"output-bin.tray-2\" = \"Tray 2\";\n" "\"output-bin.tray-3\" = \"Tray 3\";\n" "\"output-bin.tray-4\" = \"Tray 4\";\n" "\"output-bin.tray-5\" = \"Tray 5\";\n" "\"output-bin.tray-6\" = \"Tray 6\";\n" "\"output-bin.tray-7\" = \"Tray 7\";\n" "\"output-bin.tray-8\" = \"Tray 8\";\n" "\"output-bin.tray-9\" = \"Tray 9\";\n" "\"print-color-mode\" = \"Mode d ' impression\";\n" "\"print-color-mode.auto\" = \"Automatique\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monochrome\";\n" "\"print-color-mode.bi-level\" = \"Texte\";\n" "\"print-color-mode.color\" = \"Couleur\";\n" "\"print-color-mode.highlight\" = \"Highlight\";\n" "\"print-color-mode.monochrome\" = \"Monochrome\";\n" "\"print-color-mode.process-bi-level\" = \"Texte du processus\";\n" "\"print-color-mode.process-monochrome\" = \"Processus monochrome\";\n" "\"print-content-optimize\" = \"Optimiser pour\";\n" "\"print-content-optimize.auto\" = \"Automatique\";\n" "\"print-content-optimize.graphic\" = \"Graphiques\";\n" "\"print-content-optimize.photo\" = \"Photo\";\n" "\"print-content-optimize.text\" = \"Texte\";\n" "\"print-content-optimize.text-and-graphic\" = \"Texte et graphiques\";\n" "\"print-darkness\" = \"Imprimer Darkness\";\n" "\"print-quality\" = \"Qualité de l ' impression\";\n" "\"print-quality.3\" = \"Draft\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Meilleur\";\n" "\"print-scaling\" = \"Scaling\";\n" "\"print-scaling.auto\" = \"Automatique\";\n" "\"print-scaling.auto-fit\" = \"Auto-fit\";\n" "\"print-scaling.fill\" = \"Rempli\";\n" "\"print-scaling.fit\" = \"Fit\";\n" "\"print-scaling.none\" = \"None\";\n" "\"print-speed\" = \"Vitesse d ' impression\";\n" "\"printer-resolution\" = \"Résolution\";\n" "\"printer-state-reasons.cover-open\" = \"Couverture ouverte.\";\n" "\"printer-state-reasons.door-open\" = \"Porte ouverte.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Identifiez l'imprimante.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Le papier manquant.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"De l'encre.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Faible encre.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"La poubelle est presque pleine.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"La poubelle est pleine.\";\n" "\"printer-state-reasons.media-empty\" = \"Hors de papier.\";\n" "\"printer-state-reasons.media-jam\" = \"La confiture de papier.\";\n" "\"printer-state-reasons.media-low\" = \"Remplacez le papier bientôt.\";\n" "\"printer-state-reasons.media-needed\" = \"Le papier de charge.\";\n" "\"printer-state-reasons.none\" = \"Prêt.\";\n" "\"printer-state-reasons.offline\" = \"Hors ligne.\";\n" "\"printer-state-reasons.other\" = \"Voir l'imprimante.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Imprimante occupée.\";\n" "\"printer-state-reasons.toner-empty\" = \"Hors de tonner.\";\n" "\"printer-state-reasons.toner-low\" = \"Plus bas.\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Traitement\";\n" "\"printer-state.5\" = \"Arrêté\";\n" "\"sides\" = \"Impression 2-Sided\";\n" "\"sides.one-sided\" = \"Officier\";\n" "\"sides.two-sided-long-edge\" = \"Sur (portrait)\";\n" "\"sides.two-sided-short-edge\" = \"On (landscape)\";\n" "\"unable to join\" = \"incapable de se joindre\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Îles Salomon\";\n"; pappl-1.4.9/pappl/strings/he.strings000066400000000000000000001354741476704353100175050ustar00rootroot00000000000000"output-bin.tray-1" = "מגש 1"; "media.om_large-photo_200x300" = "‎200 x 300"; "finishings.25" = "תפירת שוליים עליונים"; "media.prc_3_125x176mm" = "מעטפה סינית מס׳ 3"; "output-bin.tray-6" = "מגש 6"; " -a Cancel all jobs (cancel)." = " ‎-a ביטול כל המשימות (ביטול)."; " -c COPIES" = " ‎-c עותקים"; " autoadd Automatically add supported printers." = " autoadd הוספת מדפסות נתמכות אוטומטית."; " devices List devices." = " devices הצגת מכשירים."; "%s: No files to print." = "%s: אין קבצים להדפסה."; "%s: No default printer available." = "%s: אין מדפסת ברירת מחדל זמינה."; "%s: Server is not running." = "%s: שרת לא פעיל."; "%s: Too many files." = "%s: יותר מדי קבצים."; "%s: Unable to connect to server: %s" = "%s: לא ניתן להתחבר לשרת: %s"; "Afghanistan" = "אפגניסטן"; "Albania" = "אלבניה"; "Bad administration group." = "קבוצת ניהול שגויה."; "Bad port number." = "מספר פתחה שגוי."; "Bad print group." = "קבוצת הדפסה שגויה."; "Borderless" = "ללא מסגרת"; "Bosnia and Herzegovina" = "בוסניה והרצגובינה"; "Botswana" = "בוטסואנה"; "Bouvet Island" = "האי בובה"; "Certificate request created." = "נוצרה בקשת אישור."; "Chad" = "צ׳אד"; "Change Access Password" = "החלפת סיסמת גישה"; "Change Log Level" = "החלפת רמת תיעוד ביומן"; "Change Wi-Fi Network" = "החלפת רשת אלחוטית"; "Changes Saved." = "השינויים נשמרו."; "Changes saved." = "השינויים נשמרו."; "Chile" = "צ׳ילה"; "Create Certificate Signing Request" = "יצירת בקשת חתימה על אישור"; "Custom Size" = "גודל מותאם אישית"; "Cyprus" = "קפריסין"; "Denmark" = "דנמרק"; "Guinea-Bissau" = "גינאה ביסאו"; "Iran (Islamic Republic of)" = "איראן (הרפובליקה האסלאמית של)"; "Iraq" = "עיראק"; "Ireland" = "אירלנד"; "Isle of Man" = "האי מאן"; "Israel" = "ישראל"; "Italy" = "איטליה"; "Luxembourg" = "לוקסמבורג"; "Macao" = "מקאו"; "Name" = "שם"; "Pitcairn" = "פיטקרן"; "Please select a device." = "נא לבחור מכשיר."; "Printer resuming." = "המדפסת ממשיכה."; "Printers" = "מדפסות"; "Printing Defaults" = "ברירות מחדל של הדפסה"; "Puerto Rico" = "פוארטו ריקו"; "Qatar" = "קטאר"; "Reprint Job" = "הדפסת משימה מחדש"; "Test page printed." = "עמוד הבדיקה הודפס."; "Thailand" = "תאילנד"; "Uzbekistan" = "אוזבקיסטן"; "Vanuatu" = "ונואטו"; "Version %s" = "גרסה %s"; "View Logs" = "הצגת יומנים"; "finishings.13" = "יצרן חוברות"; "finishings.15" = "ציפוי"; "finishings.16" = "למינציה"; "finishings.20" = "שידוך שמאל למעלה"; "finishings.7" = "איגוד"; "finishings.70" = "ניקוב משמאל למעלה"; "job-state-reasons.printer-stopped" = "המדפסת לא מקוונת."; "job-state-reasons.printer-stopped-partly" = "המדפסת נעצרה חלקית."; "job-state.7" = "בוטלה"; "job-state.8" = "הופסקה"; "media-type.transparency" = "שקיפות"; "media.na_quarto_8.5x10.83in" = "קוורטו"; "media.prc_16k_146x215mm" = "סינית 16k"; "media.prc_1_102x165mm" = "מעטפה סינית מס׳ 1"; "output-bin.rear" = "מאחור"; "output-bin.stacker-10" = "עורם 10"; "output-bin.stacker-2" = "עורם 2"; "output-bin.tray-4" = "מגש 4"; "output-bin.tray-5" = "מגש 5"; "printer-state-reasons.media-jam" = "נייר נתקע."; " -d PRINTER Specify printer." = " ‎-d מדפסת ציון מדפסת."; " -j JOB-ID Specify job ID (cancel)." = " ‎-j מזהה-משימה ציון מזהה משימה (ביטול)."; "print-speed" = "מהירות הדפסה"; "printer-resolution" = "רזולוציה"; "printer-state-reasons.marker-supply-low" = "נשאר מעט דיו."; "printer-state.5" = "נעצר"; "sides" = "הדפסה דו־צדדית"; "sides.two-sided-short-edge" = "פעילה (לרוחב)"; "output-bin.stacker-4" = "עורם 4"; "output-bin.tray-7" = "מגש 7"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "מספר העותקים"; "Kiribati" = "קיריבטי"; "print-scaling.none" = "בלי"; "printer-state-reasons.cover-open" = "המכסה פתוח."; "printer-state-reasons.door-open" = "הדלת פתוחה."; "printer-state-reasons.identify-printer-requested" = "זיהוי מדפסת."; "printer-state-reasons.none" = "מוכן."; "printer-state-reasons.toner-empty" = "נגמר הטונר."; "printer-state.4" = "בעיבוד"; "output-bin.tray-2" = "מגש 2"; "output-bin.tray-8" = "מגש 8"; "print-color-mode.bi-level" = "כתב"; "printer-state-reasons.input-tray-missing" = "מגש הנייר חסר."; "printer-state-reasons.marker-supply-empty" = "נגמר הדיו."; "printer-state-reasons.marker-waste-almost-full" = "פח האשפה כמעט מלא."; "printer-state-reasons.marker-waste-full" = "פח האשפה מלא."; "printer-state-reasons.media-empty" = "נגמר הנייר."; "printer-state-reasons.media-low" = "נא להחליף את הנייר בהקדם."; "printer-state-reasons.media-needed" = "לטעון נייר."; "printer-state-reasons.spool-area-full" = "המדפסת עסוקה."; "Åland Islands" = "איי אולנד"; "printer-state-reasons.offline" = "לא מקוון."; "print-scaling.auto" = "אוטומטי"; "Lao People's Democratic Republic" = "לאוס (הרפובליקה הדמוקרטית העממית של)"; "printer-state-reasons.other" = "יש לקרוא במדפסת."; "printer-state-reasons.toner-low" = "נותר מעט בטונר."; "sides.one-sided" = "כבויה"; "sides.two-sided-long-edge" = "פעילה (לאורך)"; "unable to join" = "לא ניתן לצרף"; "printer-state.3" = "בהמתנה"; "output-bin.my-mailbox" = "תיבת הדואר שלי"; "output-bin.right" = "ימין"; "output-bin.stacker-1" = "עורם 1"; "output-bin.stacker-6" = "עורם 6"; "output-bin.stacker-7" = "עורם 7"; "output-bin.side" = "צד"; "output-bin.stacker-3" = "עורם 3"; "output-bin.stacker-5" = "עורם 5"; "output-bin.stacker-9" = "עורם 9"; "output-bin.top" = "למעלה"; "output-bin.tray-3" = "מגש 3"; "output-bin.tray-9" = "מגש 9"; "print-color-mode" = "מצב הדפסה"; "print-color-mode.highlight" = "הדגשה"; "print-content-optimize" = "מיטוב לטובת"; "print-content-optimize.graphic" = "גרפיקה"; "output-bin.stacker-8" = "עורם 8"; "output-bin.tray-10" = "מגש 10"; "print-color-mode.auto" = "אוטומטי"; "print-color-mode.monochrome" = "צבע אחיד"; "print-content-optimize.photo" = "תמונה"; "print-quality" = "איכות הדפסה"; "print-scaling.fill" = "מילוי"; "print-scaling.fit" = "התאמה"; "media.na_personal_3.625x6.5in" = "מעטפה אישית"; "print-color-mode.auto-monochrome" = "צבע אחיד אוטומטי"; "print-color-mode.color" = "צבע"; "print-color-mode.process-bi-level" = "עיבוד כתב"; "print-color-mode.process-monochrome" = "עיבוד צבע אחיד"; "print-content-optimize.auto" = "אוטומטי"; "print-content-optimize.text" = "כתב"; "print-content-optimize.text-and-graphic" = "כתב וגרפיקה"; "print-quality.4" = "רגיל"; "print-quality.5" = "מיטבי"; "print-scaling" = "שינוי גודל"; "media.om_invite_220x220mm" = "מעטפת הזמנה"; "media.om_folio-sp_215x315mm" = "פוליו"; "print-darkness" = "כהות הדפסה"; "print-quality.3" = "טיוטה"; "print-scaling.auto-fit" = "התאמה אוטומטית"; "orientation-requested.6" = "לאורך הפוך"; "output-bin.mailbox-10" = "תיבת דואר 10"; "output-bin.mailbox-9" = "תיבת דואר 9"; "media-type.stationery-prepunched" = "נייר מנוקב"; "Yemen" = "תימן"; "media.om_folio_210x330mm" = "פוליו (מיוחד)"; "media.om_italian_110x230mm" = "מעטפה איטלקית"; "media.om_juuro-ku-kai_198x275mm" = "198‎ x 275 מ״מ"; "media.om_pa-kai_267x389mm" = "‎267 x 389 מ״מ"; "media.om_medium-photo_130x180mm" = "130‎ x 180 מ״מ"; "media.prc_10_324x458mm" = "מעטפה סינית מס׳ 10"; "media.om_postfix_114x229mm" = "מעטפת פוסטפיקס"; "media.prc_2_102x176mm" = "מעטפה סינית מס׳ 2"; "media.prc_6_120x320mm" = "מעטפה סינית מס׳ 6"; "media.prc_7_160x230mm" = "מעטפה סינית מס׳ 7"; "orientation-requested.7" = "ללא"; "output-bin.face-up" = "פנים כלפי מעלה"; "output-bin.mailbox-5" = "תיבת דואר 5"; "output-bin.mailbox-7" = "תיבת דואר 7"; "output-bin.mailbox-8" = "תיבת דואר 8"; "output-bin.middle" = "אמצעי"; "Zambia" = "זמביה"; "media.prc_8_120x309mm" = "מעטפה סינית מס׳ 8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "not visible" = "לא גלוי"; "off" = "כבוי"; "media.prc_32k_97x151mm" = "סינית 32k"; "media.prc_4_110x208mm" = "מעטפה סינית מס׳ 4"; "media.prc_5_110x220mm" = "מעטפה סינית מס׳ 5"; "media.roc_8k_10.75x15.5in" = "ROCK 8k"; "not configured" = "לא מוגדר"; "on" = "פעיל"; "orientation-requested" = "כיוון"; "orientation-requested.3" = "לאורך"; "orientation-requested.4" = "לרוחב"; "output-bin.auto" = "אוטומטי"; "output-bin.center" = "מרכזי"; "output-bin.left" = "שמאל"; "output-bin.mailbox-1" = "תיבת דואר 1"; "output-bin.mailbox-3" = "תיבת דואר 3"; "finishings.101" = "קיפול Z הנדסי"; "Landscape" = "לרוחב"; "orientation-requested.5" = "לרוחב הפוך"; "output-bin" = "מגש פלט"; "output-bin.bottom" = "תחתון"; "output-bin.face-down" = "פנים כלפי מטה"; "output-bin.large-capacity" = "קיבולת גבוהה"; "output-bin.mailbox-4" = "תיבת דואר 4"; "output-bin.mailbox-6" = "תיבת דואר 6"; "finishings.100" = "קיפול Z"; "finishings.21" = "שידוך שמאל למטה"; "finishings.26" = "תפירת שוליים ימניים"; "finishings.34" = "3 שידוכים מימין"; "output-bin.mailbox-2" = "תיבת דואר 2"; "Zimbabwe" = "זימבבואה"; "finishings.10" = "קיפול"; "finishings.23" = "שידוך ימין למטה"; "finishings.32" = "3 שידוכים משמאל"; "finishings.35" = "3 שידוכים מלמטה"; "finishings.29" = "שני שידוכים מלמעלה"; "finishings.73" = "ניקוב מימין למטה"; "Korea (Democratic People's Republic of)" = "קוריאה (הרפובליקה הדמוקרטית העממית של)"; "default printer" = "מדפסת ברירת מחדל"; "finishings.22" = "שידוך ימין למעלה"; "finishings.27" = "תפירת שוליים תחתונים"; "finishings.3" = "בלי"; "finishings.11" = "גזירה"; "finishings.24" = "תפירת שוליים שמאליים"; "finishings.28" = "שני שידוכים משמאל"; "finishings.33" = "3 שידוכים מלמעלה"; "finishings.51" = "איגוד מלמעלה"; "finishings.52" = "איגוד מימין"; "finishings.30" = "שני שידוכים מימין"; "finishings.31" = "שני שידוכים מלמטה"; "finishings.4" = "שידוך"; "finishings.5" = "ניקוב"; "finishings.50" = "איגוד משמאל"; "finishings.60" = "לחתוך אחרי כל עמוד"; "finishings.61" = "לחתוך אחרי כל מסמך"; "finishings.74" = "ניקוב שני חורים משמאל"; "finishings.53" = "איגוד מלמטה"; "finishings.6" = "כריכה"; "finishings.72" = "ניקוב מימין למעלה"; "finishings.78" = "ניקוב 3 חורים משמאל"; "Missing action." = "חסרה פעולה."; "Netherlands" = "הולנד"; "Unable to use that driver." = "לא ניתן להשתמש במנהל ההתקן הזה."; "Anguilla" = "אנגווילה"; "finishings.62" = "לחתוך אחרי כל סדרה"; "finishings.63" = "לחתוך אחרי משימה"; "finishings.71" = "ניקוד משמאל למטה"; "finishings.75" = "ניקוב שני חורים מלמעלה"; "finishings.76" = "ניקוב שני חורים מימין"; "finishings.77" = "ניקוב שני חורים מלמטה"; "finishings.79" = "ניקוב 3 חורים מלמעלה"; "finishings" = "גימור"; "Job #" = "משימה מס׳"; "Maldives" = "האיים המלדיביים"; "Marshall Islands" = "איי מרשל"; "Mauritius" = "מאוריציוס"; "Media" = "אמצעי דפוס"; "Mongolia" = "מונגוליה"; "No default printer set." = "לא הוגדרה מדפסת ברירת מחדל."; "Pakistan" = "פקיסטן"; "Palau" = "פלאו"; "Réunion" = "ראוניון"; "Kyrgyzstan" = "קירגיזסטן"; "Jamaica" = "ג׳מייקה"; "Japan" = "יפן"; "Jobs" = "משימות"; "Kenya" = "קניה"; "Latvia" = "לטביה"; "Jersey" = "ג׳רזי"; "Jordan" = "ירדן"; "Kazakhstan" = "קזחסטן"; "Korea, Republic of" = "קוריאה, הרפובליקה של"; "Kuwait" = "כווית"; "Lebanon" = "לבנון"; "Level" = "רמה"; "Log Level" = "רמת תיעוד ביומן"; "Logging" = "תיעוד ביומן"; "Logs" = "יומנים"; "Madagascar" = "מדגסקר"; "Mexico" = "מקסיקו"; "Libya" = "לוב"; "Liechtenstein" = "ליכטנשטיין"; "Lithuania" = "ליטא"; "Location" = "מיקום"; "Malawi" = "מלאווי"; "Malaysia" = "מלזיה"; "Mali" = "מאלי"; "Martinique" = "מרטיניק"; "Mayotte" = "מיוט"; "Missing private key." = "המפתח הפרטי חסר."; "Moldova, Republic of" = "מולדובה, רפובליקת"; "Monaco" = "מונקו"; "Morocco" = "מרוקו"; "Lesotho" = "לסוטו"; "Liberia" = "ליבריה"; "Offset" = "היסט"; "Network" = "רשת"; "Networking" = "קישוריות רשת"; "Niger" = "ניז׳ר"; "Norfolk Island" = "נורפוק, האי"; "Not set" = "לא הוגדר"; "Password" = "סיסמה"; "Philippines" = "הפיליפינים"; "Malta" = "מלטה"; "Mauritania" = "מאוריטניה"; "Montenegro" = "מונטנגרו"; "Mozambique" = "מוזמביק"; "Namibia" = "נמיביה"; "Nauru" = "נאורו"; "Myanmar" = "מיאנמר"; "Nepal" = "נפאל"; "New Zealand" = "ניו זילנד"; "No jobs in history." = "אין משימות בהיסטוריה."; "Network Printer" = "מדפסת רשת"; "New Caledonia" = "קלדוניה החדשה"; "Nicaragua" = "ניקרגואה"; "Nigeria" = "ניגריה"; "North Macedonia" = "צפון מקדוניה"; "Oman" = "עומאן"; "Options:" = "אפשרויות:"; "Organization" = "ארגון"; "Northern Mariana Islands" = "איי מריאנה הצפוניים"; "Portrait" = "לאורך"; "Norway" = "נורווגיה"; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "אורך הסיסמה חייב להיות שמונה תווים לפחות ועליה להכין לפחות אות גדולה אחת, אות קטנה אחת וספרה אחת."; "Portugal" = "פורטוגל"; "Print Test Page" = "הדפסת עמוד בדיקה"; "Print job options:" = "אפשרויות משימת הדפסה:"; "Printer is currently active." = "המדפסת פעילה כרגע."; "Saint Barthélemy" = "סן ברתלמי"; "Organization Name" = "שם הארגון"; "Other Settings" = "הגדרות אחרות"; "Palestine, State of" = "פלסטין, רשות"; "Panama" = "פנמה"; "Papua New Guinea" = "פפואה גינאה החדשה"; "Paraguay" = "פרגוואי"; "Password changed." = "הסיסמה הוחלפה."; "Please enter a printer name." = "נא למלא את שם המדפסת."; "Please select a driver." = "נא לבחור מנהל התקן."; "Poland" = "פולין"; "Print Group" = "קבוצת הדפסה"; "Printer identified." = "המדפסת זוהתה."; "Passwords do not match." = "הסיסמאות אינן תואמות."; "Pause Printing" = "השהיית הדפסה"; "Peru" = "פרו"; "Please enter a hostname or IP address for the printer." = "נא למלא את שם המארח או את כתובת ה־IP של המדפסת."; "Please select a valid log level." = "נא לבחור רמת תיעוד תקפה."; "Printer paused." = "המדפסת הושהתה."; "Russian Federation" = "הפדרציה הרוסית"; "Rwanda" = "רואנדה"; "Ukraine" = "אוקראינה"; "Printer pausing." = "המדפסת מושהית."; "Printer names must start with a letter or underscore and cannot contain special characters." = "שמות המדפסות חייבים להתחיל באות או בקו תחתון ולא יכולים להכיל תווים מיוחדים."; "Resume Printing" = "להמשיך הדפסה"; "Reverse Landscape" = "לרוחב הפוך"; "Printer options:" = "אפשרויות מדפסת:"; "Reverse Portrait" = "לאורך הפוך"; "Romania" = "רומניה"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "רץ, %s מאז %s%s."; "Sao Tome and Principe" = "סאו טומה ופרינסיפה"; "Saudi Arabia" = "ערב הסעודית"; "Save Changes" = "שמירת השינויים"; "Serbia" = "סרביה"; "Server is not running." = "השרת לא פעיל."; "Set Access Password" = "הגדרת סיסמת גישה"; "Slovakia" = "סלובקיה"; "Solomon Islands" = "איי שלמה"; "San Marino" = "סן מרינו"; "Security" = "אבטחה"; "Select Driver" = "בחירת מנהל התקן"; "Senegal" = "סנגל"; "Set as Default" = "הגדרה כברירת מחדל"; "Samoa" = "סמואה"; "Singapore" = "סינגפור"; "South Africa" = "דרום אפריקה"; "Unable to create test print job." = "לא ניתן ליצור משימת בדיקת הדפסה."; "United States of America" = "ארצות הברית"; "Sub-commands:" = "תת־פקודות:"; "Sudan" = "סודאן"; "Supplies" = "מתכלים"; "Tokelau" = "טוקלאו"; "Unknown" = "לא ידוע"; "Unknown form action." = "פעולה לא ידועה בטופס."; "Slovenia" = "סלובניה"; "Somalia" = "סומליה"; "Status" = "מצב"; "Georgia" = "גאורגיה"; "South Sudan" = "דרום סודאן"; "Spain" = "ספרד"; "Sri Lanka" = "סרי לנקה"; "Trinidad and Tobago" = "טרינידד וטובגו"; "Togo" = "טוגו"; "Tonga" = "טונגה"; "Uganda" = "אוגנדה"; "Unable to copy print job." = "לא ניתן להעתיק את משימת ההדפסה."; "Unable to create certificate request." = "לא ניתן ליצור בקשת אישור."; "Unable to identify printer." = "לא ניתן לזהות מדפסת."; "Unable to access test print file." = "לא ניתן לגשת לקובץ בדיקת ההדפסה."; "Warning" = "אזהרה"; "Wi-Fi Configuration" = "הגדרות רשת אלחוטית"; "Eritrea" = "אריתריאה"; "France" = "צרפת"; "Gabon" = "גבון"; "Unable to create certificate." = "לא ניתן ליצור אישור."; "Unable to lookup address." = "לא ניתן לאתר כתובת."; "United Arab Emirates" = "איחוד האמירויות"; "Unknown action." = "פעולה לא ידועה."; "Users" = "משתמשים"; "Western Sahara" = "סהרה המערבית"; "Wi-Fi Network" = "רשת אלחוטית"; "Unknown form request." = "בקשת טופס לא ידועה."; "Estonia" = "אסטוניה"; "Use My Position" = "להשתמש במיקום שלי"; "Width" = "רוחב"; "Wrong old password." = "סיסמה ישנה שגויה."; "Errors" = "שגיאה"; "Ethiopia" = "אתיופיה"; "Fatal Errors/Conditions" = "שגיאות/תנאים מכריעים"; "Fiji" = "פיג׳י"; "French Guiana" = "גיאנה הצרפתית"; "French Polynesia" = "פולינזיה הצרפתית"; "Gambia" = "גמביה"; ", Borderless" = ", ללא מסגרת"; "A printer with that name already exists." = "כבר קיימת מדפסת בשם הזה."; "Algeria" = "אלג׳יריה"; "Finland" = "פינלנד"; "French Southern Territories" = "הטריטוריות הדרומיות של צרפת"; "Germany" = "גרמניה"; "Ghana" = "גאנה"; "Gibraltar" = "גיברלטר"; "Greenland" = "גרינלנד"; "Grenada" = "גרנדה"; "Guadeloupe" = "גוואדלופ"; "Heard Island and McDonald Islands" = "האי הרד ואיי מקדונלד"; "Honduras" = "הונדורס"; "Identify Printer" = "זיהוי מדפסת"; "Invalid job ID." = "מזהה משימה שגוי."; "Greece" = "יוון"; "Hong Kong" = "הונג קונג"; "Hostname" = "שם מארח"; "Invalid form submission." = "הגשת טופס שגויה."; " default Set the default printer." = " default הגדרת מדפסת ברירת המחדל."; " shutdown Shutdown a running server." = " shutdown כיבוי שרת פעיל."; /* Source/Tray Media */ "%s Media" = "אמצעי הדפסה ב%s"; "Group changes saved." = "השינויים בקבוצה נשמרו."; "Guam" = "גואם"; "Guatemala" = "גואטמלה"; "Guernsey" = "גרנזי"; "Guinea" = "גינאה"; "Guyana" = "גיאנה"; "Haiti" = "האיטי"; "Human-Readable Location" = "מיקום בשפה אנושית"; "Hungary" = "הונגריה"; "Iceland" = "איסלנד"; "India" = "הודו"; "Indonesia" = "אינדונזיה"; "Install TLS Certificate" = "התקנת אישור TLS"; "Invalid certificate or private key." = "אישור או מפתח פרטי שגויים."; "Invalid form data." = "נתוני הטופס שגויים."; "Saint Martin (French part)" = "סנט מרטין (החלק הצרפתי)"; " -o %s=%s (default)" = " ‎-o %s=%s (ברירת מחדל)"; " delete Delete a printer." = " delete מחיקת מדפסת."; " drivers List drivers." = " drivers הצגת מנהלי התקנים."; " modify Modify a printer." = " modify שינוי מדפסת."; " printers List printers." = " printers הצגת מדפסות."; "%d inches/sec" = "%d אינצ׳ים/שנייה"; /* Media size in millimeters */ "%d x %dmm" = "‎%d x %d מ״מ"; "Invalid Job ID." = "מזהה משימה שגוי."; " resume Resume printing for a printer." = " resume להמשיך להדפיס במדפסת."; "Saint Vincent and the Grenadines" = "סנט וינסנט והגרנדינים"; "Saint Kitts and Nevis" = "סנט קיטס ונוויס"; "Saint Lucia" = "סנט לוסיה"; "Saint Pierre and Miquelon" = "סנט פייר ומיקלון"; " cancel Cancel one or more jobs." = " cancel ביטול משימה אחת או יותר."; " jobs List jobs." = " jobs הצגת משימות."; " options List printer options." = " options הצגת אפשרויות מדפסת."; " pause Pause printing for a printer." = " pause השהיית הדפסה במדפסת."; " status Show server/printer/job status." = " status הצגת מצב שרת/מדפסת/משימה."; " submit Submit a file for printing." = " submit הגשת קובץ להדפסה."; "Admin Group" = "קבוצת ניהול"; "Australia" = "אוסטרליה"; "Azerbaijan" = "אזרבייג׳ן"; "Barbados" = "ברבדוס"; "Belgium" = "בלגיה"; "Benin" = "בנין"; " server Run a server." = " server הפעלת שרת."; "Antarctica" = "אנטארקטיקה"; "Bhutan" = "בהוטן"; "Canada" = "קנדה"; "Cancel Job" = "ביטול משימה"; "%s: Failed to create a system." = "%s: יצירת מערכת נכשלה."; "Add Printer" = "הוספת מדפסת"; "Andorra" = "אנדורה"; "Angola" = "אנגולה"; "Argentina" = "ארגנטינה"; "Armenia" = "ארמניה"; "Aruba" = "ארובה"; "Austria" = "אוסטריה"; "Auto" = "אוטומטי"; "American Samoa" = "סמואה האמריקנית"; "Antigua and Barbuda" = "אנטיגואה וברבודה"; "Auto-Detect Driver" = "זיהוי אוטומטי של מנהל התקן"; "Bahamas" = "איי בהאמה"; "Bahrain" = "בחריין"; "Belarus" = "בלארוס"; "Bad printer defaults." = "ברירות מחדל שגויות למדפסת."; "Bangladesh" = "בנגלדש"; "Belize" = "בליז"; "Bermuda" = "ברמודה"; "Brazil" = "ברזיל"; "Burkina Faso" = "בורקינה פאסו"; "Cancel All Jobs" = "ביטול כל המשימות"; "Canceling" = "מתבצע ביטול"; "Certificate created." = "נוצר אישור."; "British Indian Ocean Territory" = "הטריטוריה הבריטית באוקיינוס ההודי"; "Bulgaria" = "בולגריה"; "Burundi" = "בורונדי"; "Cabo Verde" = "קאבו ורדה"; "Cameroon" = "קמרון"; "Cambodia" = "קמבודיה"; "Colombia" = "קולומביה"; "Congo, Democratic Republic of the" = "קונגו, הרפובליקה הדמוקרטית של"; "Cook Islands" = "איי קוק"; "Configure Media" = "הגדרת אמצעי הדפסה"; "Cayman Islands" = "איי קיימן"; "Central African Republic" = "הרפובליקה המרכז אפריקאית"; "China" = "סין"; "Cocos (Keeling) Islands" = "איי קוקוס (קילינג)"; "Comoros" = "קומורו"; "Confirm Delete Printer" = "אישור מחיקת מדפסת"; "Configuration" = "הגדרות"; "Certificate installed." = "אישור הותקן."; "Christmas Island" = "קיריטימטי"; "Confirm Cancel All" = "אישור ביטול הכול"; "Costa Rica" = "קוסטה ריקה"; "Create New Certificate" = "יצירת אישור חדש"; "Create New TLS Certificate" = "יצירת אישור TLS חדש"; "Congo" = "קונגו"; "Create TLS Certificate Request" = "יצירת בקשה לאישור TLS"; "Cuba" = "קובה"; "Bolivia (Plurinational State of)" = "בוליביה (המדינה הרב־לאומית של)"; "job-state.4" = "מוחזקת"; "media-size" = "גודל אמצעי הדפסה"; "Croatia" = "קרואטיה"; "Curaçao" = "קוראסאו"; "Czechia" = "צ׳כיה"; "DNS-SD Service Name" = "שם שירות ב־DNS-SD"; "Delete" = "מחיקה"; "Delete Printer" = "מחיקת מדפסת"; "Current Password" = "הסיסמה הנוכחית"; "Debugging" = "ניפוי שגיאות"; "Dominica" = "דומיניקה"; "El Salvador" = "אל סלבדור"; "job-state.6" = "נעצרה"; "media-source.hagaki" = "הגאקי/Hagaki"; "Default printer set." = "הוגדרה מדפסת ברירת מחדל."; "Djibouti" = "ג׳יבוטי"; "Dominican Republic" = "הרפובליקה הדומיניקנית"; "Equatorial Guinea" = "גינאה המשוונית"; "job-state-reasons.warnings-detected" = "התגלתה אזהרה."; "job-state.5" = "מעובדת"; "Download Certificate Request File" = "הורדת קובץ בקשת אישור"; "Ecuador" = "אקוודור"; "Egypt" = "מצרים"; "Bonaire, Sint Eustatius and Saba" = "בונייר, סנט אוסטטיוס וסאבא"; "job-state-reasons.processing-to-stop-point" = "נעצרת."; "job-state-reasons.queued-in-device" = "מוכנה."; "job-state.3" = "בהמתנה"; "job-state.9" = "הושלמה"; "media" = "אמצעי הדפסה"; "media-col" = "אמצעי הדפסה"; "media-size-name" = "גודל אמצעי הדפסה"; "media-source" = "מגש קלט"; "media-source.left" = "שמאל"; "media-source.right" = "ימני"; "media-source.by-pass-tray" = "מגש רב־תכליתי"; "media-source.center" = "מרכז"; "media-source.disc" = "דיסק"; "media-source.large-capacity" = "קיבולת גבוהה"; "media-source.main" = "ראשי"; "media-source.manual" = "ידני"; "media-source.envelope" = "מעטפה"; "media-source.middle" = "אמצעי"; "media-source.photo" = "תמונה"; "media-source.rear" = "אחורי"; " -m DRIVER-NAME Specify driver (add/modify)." = " ‎-m שם-מנהל-התקן בחירת מנהל התקן (הוספה/עריכה)."; "media.na_number-12_4.75x11in" = "מעטפה מס׳ 12"; "media.na_number-14_5x11.5in" = "מעטפה מס׳ 14"; "media.na_number-10_4.125x9.5in" = "מעטפה מס׳ 10"; "media.na_number-11_4.5x10.375in" = "מעטפה מס׳ 11"; "media.na_invoice_5.5x8.5in" = "הצהרה"; "media.na_number-9_3.875x8.875in" = "מעטפה מס׳ 9"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " ‎-o שם=ערך ציון אפשרות (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " ‎-o print-darkness=-100 עד 100"; " -o printer-darkness=0 to 100" = " ‎-o printer-darkness=0 עד 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " ‎-o printer-geo-location='geo:LATITUDE,LONGITUDE'‎"; " -o printer-location='LOCATION'" = " ‎-o printer-location='מיקום'‎"; "%s: Unable to add printer: %s" = "%s: לא ניתן להוסיף מדפסת: %s"; "%s: Unable to cancel job: %s" = "%s: לא ניתן לבטל משימה: %s"; "%s: Unable to create temporary file: %s" = "%s: לא ניתן ליצור קובץ זמני: %s"; "%s: Unable to delete printer: %s" = "%s: לא ניתן למחוק מדפסת: %s"; "%s: Unable to get information for '%s': %s" = "%s: לא ניתן לקבל מידע על ‚%s’:‏ %s"; "%s: Unable to get information for printer: %s" = "%s: לא ניתן לקבל מידע על המדפסת: %s"; "%s: Unable to get printer options: %s" = "%s: לא ניתן למשוך אפשרויות מדפסת: %s"; "%s: Unable to modify printer: %s" = "%s: לא ניתן לשנות מדפסת: %s"; "%s: Unable to pause printer: %s" = "%s: לא ניתן לשנות מדפסת: %s"; "%s: Unable to print '%s': %s" = "%s: לא ניתן להדפיס את ‚%s’:‏ %s"; "%s: Unable to resume printer: %s" = "%s: לא ניתן להמשיך את פעולת המדפסת: %s"; "%s: Unable to set default printer: %s" = "%s: לא ניתן להגדיר את מדפסת ברירת המחדל: %s"; "%s: Unable to shutdown server: %s" = "%s: לא ניתן לכבות את השרת: %s"; "%s: Unable to start server: %s" = "%s: לא ניתן להפעיל את השרת: %s"; "%s: Unable to write to temporary file: %s" = "%s: לא ניתן לכתוב לקובץ זמני: %s"; "%s: Unknown option '%s'." = "%s: האפשרות ‚%s’ לא ידועה."; "%s: Unknown option '-%c'." = "%s: האפשרות ‚-%c’ לא ידועה."; "%s: Unknown sub-command '%s'." = "%s: תת־הפקודה ‚%s’ לא ידועה."; "%s: Unsupported URI scheme '%s'." = "%s: סכמת הכתובת ‚%s’ לא נתמכת."; "%s: Warning - user credentials are not supported in URIs." = "%s: אזהרה - אין תמיכה בפרטי גישה כחלק מהכתובת."; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: לא ניתן להתחבר למדפסת במיקום ‚%s:%d’:‏ %s"; " -o printer-organization='ORGANIZATION'" = " ‎-o printer-organization='ארגון'"; " -o printer-organizational-unit='UNIT/SECTION'" = " ‎-o printer-organizational-unit='יחידה/מחלקה'"; " -n COPIES Specify number of copies (submit)." = " ‎ -n עותקים ציון מספר העותקים (submit)."; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) מתוך %s"; "%s: Bad printer URI '%s'." = "%s: כתובת מדפסת שגויה ‚%s’."; "%s: Cannot specify more than one sub-command." = "%s: לא ניתן לציין יותר מתת־פקודה אחת."; "%s: Empty print file received on the standard input." = "%s: התקבל קובץ ריק להדפסה דרך הקלט התקני (stdin)."; " add PRINTER Add a printer." = " add PRINTER הוספת מדפסת."; "media-source.bottom" = "תחתון"; "media-source.auto" = "אוטומטי"; "media-source.alternate-roll" = "גליל חלופי"; "media-source.alternate" = "חלופי"; "media-source.main-roll" = "גליל ראשי"; "media-source.roll-8" = "גליל 8"; "media-source.roll-7" = "גליל 7"; "media-source.roll-6" = "גליל 6"; "media-source.roll-5" = "גליל 5"; "media-source.roll-4" = "גליל 4"; "media-source.roll-3" = "גליל 3"; "media-source.roll-2" = "גליל 2"; "media-source.roll-10" = "גליל 10"; "media-source.roll-1" = "גליל 1"; "media-source.tray-12" = "מגש 12"; "media-source.tray-13" = "מגש 13"; "media-source.tray-2" = "מגש 2"; "media-source.tray-20" = "מגש 20"; "media-source.tray-3" = "מגש 3"; "media-source.tray-4" = "מגש 4"; "media-tracking.gap" = "ריווח"; "media-tracking.mark" = "סימון"; "media-tracking.web" = "אתר אינטרנט"; "media-type" = "סוג מדיה"; "media-source.roll-9" = "גליל 9"; "media-source.tray-11" = "מגש 11"; "media-source.tray-10" = "מגש 10"; "media-source.tray-1" = "מגש 1"; "media-source.tray-19" = "מגש 19"; "media-source.side" = "צד"; "media-source.top" = "עליון"; "media-source.tray-18" = "מגש 18"; "media-source.tray-9" = "מגש 9"; "media-source.tray-15" = "מגש 15"; "media-source.tray-17" = "מגש 17"; "media-source.tray-14" = "מגש 14"; "media-source.tray-16" = "מגש 16"; "media-tracking.continuous" = "רציפה"; "media-tracking" = "רצף מדיה"; "media-type.aluminum" = "אלומיניום"; "media-source.tray-5" = "מגש 5"; "media-source.tray-6" = "מגש 6"; "media-source.tray-7" = "מגש 7"; "media-source.tray-8" = "מגש 8"; "media-type.auto" = "אוטומטי"; "media-type.cardboard" = "קרטון"; "media-type.double-wall" = "דופן כפולה"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "רדיד להטבעה"; "media-type.cd" = "תקליטור"; "media-type.continuous" = "רציף"; "media-type.continuous-long" = "רציף ארוך"; "media-type.continuous-short" = "רציף קצר"; "media-type.corrugated-board" = "קרטון גלי"; "media-type.disc" = "תקליטור אופטי"; "media-type.disc-glossy" = "תקליטור אופטי מבריק"; "media-type.disc-high-gloss" = "כונן אופטי בוהק מאוד"; "media-type.disc-matte" = "תקליטור אופטי מחוספס"; "media-type.disc-satin" = "תקליטור אופטי סאטן"; "media-type.disc-semi-gloss" = "תקליטור אופטי בוהק למחצה"; "media-type.envelope" = "מעטפה"; "media-type.envelope-archival" = "מעטפה לארכיון"; "media.iso_c3_324x458mm" = "מעטפה C3"; "%d job" = "משימה %d"; "media.iso_c6c5_114x229mm" = "מעטפה C6/C5"; "media.iso_c5_162x229mm" = "מעטפה C5"; "media.iso_c4_229x324mm" = "מעטפה C4"; " -u URI Specify ipp: or ipps: printer/server." = " ‎-u‪ כתובת‬ יש לציין מדפסת/שרת ipp:‎ או ipps:‎."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " ‪-v כתובת התקן‬ ציון socket:‎ או התקן usb:‎ (הוספה/עריכה)."; "%ddpi" = "%d נק׳ לאינץ׳"; "%dx%ddpi" = "%dx%d נק׳ לאינץ׳"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; "job-state-reasons.none" = "בהמתנה."; "media.iso_b5_176x250mm" = "מעטפה B5"; "media.iso_b5-extra_201x276mm" = "B5 (תוספת)"; "media.iso_c6_114x162mm" = "מעטפה C6"; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d ב־%02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "לפני %d ימים ב־%02d:%02d:%02d"; "%s: Bad 'server-port' value." = "%s: ערך 'server-port' (שרת-פתחה) שגוי."; "%s: Bad job ID." = "%s: מזהה משימה שגוי."; "%s: Missing '-d PRINTER'." = "%s: חסר ‪'-d מדפסת'‬."; "media.iso_c2_458x648mm" = "מעטפה C2"; "media.iso_c1_648x917mm" = "מעטפה C1"; "media.iso_c10_28x40mm" = "מעטפה C10"; "media.iso_c0_917x1297mm" = "מעטפה C0"; "media.iso_b6c4_125x324mm" = "מעטפה B6/C4"; "media.na_a2_4.375x5.75in" = "מעטפה A2"; "job-state-reasons.aborted-by-system" = "נעצרת."; "%s: Missing copy count after '-n'." = "%s: חסרה כמות עותקים אחרי '‎-n'."; "%s: Sub-command 'autoadd' is not supported." = "%s: תת־הפקודה 'autoadd' (הוספה אוטומטית) אינה נתמכת."; "job-state-reasons.errors-detected" = "התגלו שגיאות."; "job-state-reasons.job-canceled-by-user" = "בוטלה על ידי המשתמש."; "job-state-reasons.document-unprintable-error" = "שגיאת קובץ לא מתאים להדפסה."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "הטופס הזה מתקין אישור TLS מהימן שקיבלת מרשות אישורים (‚CA’). לאחר ההתקנה, ייעשה בו שימוש מייד."; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "שימוש: %s SUB-COMMAND [OPTIONS] [FILENAME] (תת־פקודה [אפשרויות] [שם קובץ]\n"; "finishings.86" = "ניקוב מרובה חורים משמאל"; "Wallis and Futuna" = "ואליס ופוטונה"; "finishings.85" = "ניקוב 4 חורים מלמטה"; "%s: Missing title after '-t'." = "%s: חסרה כותרת אחרי '‎-t'."; "%s: Missing space after '-o'." = "%s: חסר רווח אחרי '‎-o'."; "%s: Unable to access '%s': %s" = "%s: לא ניתן לגשת אל '%s':‏ %s"; "%s: Sub-command '%s' does not accept files." = "%s: תת־הפקודה '%s' לא מקבלת קבצים."; "Brunei Darussalam" = "ברוניי דארוסלאם"; "Contact" = "יצירת קשר"; "Côte d'Ivoire" = "חוף השנהב"; "Eswatini" = "אסוואטיני"; "Falkland Islands (Malvinas)" = "איי פוקלנד"; "Faroe Islands" = "איי פארו"; "Holy See" = "הכס הקדוש"; "Informational" = "ליידוע"; "Micronesia (Federated States of)" = "מיקרונזיה (המדינות הפדרטיביות של)"; "Montserrat" = "מונטסראט"; "United Kingdom" = "הממלכה המאוחדת"; "Uruguay" = "אורוגוואי"; "United Kingdom of Great Britain and Northern Ireland" = "הממלכה המאוחדת של בריטניה הגדולה וצפון אירלנד"; "job-state-reasons.document-password-error" = "שגיאת סיסמת מסמך."; "media-type.plastic" = "פלסטיק"; "media.iso_a1x3_841x1783mm" = "A1x3"; "%s: Unable to get available devices: %s" = "%s: לא ניתן למשוך את ההתקנים הזמינים: %s"; "Canceled %s" = "%s בוטלה"; "Completed %s" = "%s הושלמה"; "Domain Name" = "שם תחום"; "Niue" = "ניואה"; "Off" = "כבוי"; "Released held new jobs." = "שוחררו משימות חדשות שהוחזקו."; "Reprinted job." = "משימה הודפסה מחדש."; "Saint Helena, Ascension and Tristan da Cunha" = "סנט הלנה, אסנשן וטריסטן דה קונה"; "South Georgia and the South Sandwich Islands" = "איי ג׳ורג׳יה הדרומית ואיי סנדוויץ׳ הדרומיים"; "Tuvalu" = "טובאלו"; "Updating Network Configuration" = "הגדרות הרשת מתעדכנות"; "Venezuela (Bolivarian Republic of)" = "ונצואלה (הרפובליקה הבוליברית של)"; "Viet Nam" = "וייטנאם"; "Virgin Islands (British)" = "איי הבתולה הבריטיים"; "Virgin Islands (U.S.)" = "איי הבתולה של ארצות הברית"; "finishings.82" = "ניקוב 4 חורים משמאל"; "finishings.83" = "ניקוב 4 חורים מלמעלה"; "finishings.84" = "ניקוב 4 חורים מימין"; "finishings.88" = "ניקוב מרובה חורים מימין"; "job-state-reasons.document-format-error" = "שגיאת תצורת מסמך."; "holding new jobs" = "משימות חזקות מוחזקות"; "job-state-reasons.document-permission-error" = "שגיאת הרשאות מסמך."; "job-state-reasons.job-data-insufficient" = "אין מספיק נתונים."; "finishings.89" = "ניקוב מרובה חורים מלמטה"; "finishings.90" = "קיפול אקורדיאון"; "media-type.envelope-fine" = "מעטפה עדינה"; "media-type.envelope-heavyweight" = "מעטפה חסונה"; "media-type.envelope-inkjet" = "מעטפת הזרקת דיו"; "media-type.envelope-preprinted" = "מעטפה מודפסת"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_c7c6_81x162mm" = "מעטפה C7/C6"; "media.iso_c8_57x81mm" = "מעטפה C8"; "media.iso_c7_81x114mm" = "מעטפת C7"; "media.iso_c9_40x57mm" = "מעטפה C9"; "media.iso_dl_110x220mm" = "מעטפה DL"; "Primary DNS" = "DNS עיקרי"; "Queued %s" = "%s בתור"; "Release Job" = "שחרור משימה"; "Secondary DNS" = "DNS משני"; "Seychelles" = "סיישל"; "Sierra Leone" = "סיירה לאון"; "Started %s" = "החלה ב־%s"; "Sweden" = "שוודיה"; "Syrian Arab Republic" = "סוריה (הרפובליקה הערבית הסורית)"; "Switzerland" = "שווייץ"; "Taiwan, Province of China" = "טאיוואן, פרובינציה של סין"; "Tajikistan" = "טג׳יקיסטן"; "Tanzania, United Republic of" = "טנזניה, הרפובליקה המאוחדת של"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "הטופס הזה מייצר בקשת חתימת אישור (‚CSR’) שניתן לשלוח לרשות אישורים (‚CA’) כדי לקבל אישור TLS מהימן. המפתח הפרטי נשמח בנפרד לשימוש עם האישור שקיבלת מרשות האישורים."; "Timor-Leste" = "מזרח טימור"; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "הטופס הזה מייצר אישור TLS ‚חתום-עצמאית’ להדפסה מאובטחת. אישורים שנחתמו עצמאית לא נחשבים למהימנים מצד הדפדפנים."; "Turkey" = "טורקיה"; "Turkmenistan" = "טורקמניסטן"; "Turks and Caicos Islands" = "איי טרקס וקייקוס"; "at %02d:%02d:%02d" = "ב־%02d:%02d:%02d"; "finishings.87" = "ניקוב מרובה חורים מלמעלה"; "job-state-reasons.job-canceled-at-device" = "בוטלה במדפסת."; "job-state-reasons.job-completed-successfully" = "הודפסה."; "job-state-reasons.job-completed-with-errors" = "הודפסה עם שגיאות."; "job-state-reasons.job-completed-with-warnings" = "הודפסה עם אזהרות."; "media-type.envelope-lightweight" = "מעטפה קלילה"; "media-type.envelope-plain" = "מעטפה פשוטה"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2x3_594x1261mm" = "A2x3"; "%s: Missing '-m DRIVER-NAME'." = "%s: חסר ‪'-m שם מנהל התקן'‬."; "%s: Missing '-v DEVICE-URI'." = "%s: חסר ‪'-v כתובת-התקן'‬."; "%s: Missing device URI after '-v'." = "%s: חסרה כתובת התקן אחרי '‎-v'."; "%s: Missing driver name after '-m'." = "%s: חסר שם מנהל התקן אחרי '‎-m'."; "%s: Missing filename after '--'." = "%s: חסר שם קובץ אחרי '--'."; "%s: Missing hostname after '-h'." = "%s: חסר שם מארח אחרי '‎-h'."; "%s: Missing job ID after '-j'." = "%s: חסר מזהה משימה אחרי '‎-j'."; "%s: Missing option(s) after '-o'." = "%s: חסרה אפשרות אחת או יותר אחרי '‎-o'."; "%s: Missing printer URI after '-u'." = "%s: חסרה כתובת מדפסת אחרי '‎-u'."; "%s: Missing printer name after '-d'." = "%s: חסר שם המדפסת אחרי '‎-d'."; "Aborted %s" = "%s בוטלה"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP עם כתובת ידנית"; "IPv4 Address" = "כתובת IPv4"; "IPv6 Address" = "כתובת IPv6"; "IPv4 Gateway" = "שער גישה IPv4"; "IPv4 Netmask" = "מסכת רשת IPv4"; "IPv6 Configuration" = "הגדרות IPv6"; "IPv4 Configuration" = "הגדרות IPv4"; "Joining Wi-Fi Network" = "הצטרפות לרשת אלחוטית"; "Change Network Settings" = "עריכת הגדרות רשת"; "Hold Job" = "החזקת משימה"; "Hold New Jobs" = "החזקת משימות חדשות"; "Holding new jobs." = "משימות חדשות מוחזקות."; "IPv6 Link-Local" = "קישור מקומי IPv6"; "IPv6 Prefix Length" = "אורך קידומת IPv6"; "Invalid IPv4 address." = "כתובת IPv4 שגויה."; "Invalid IPv4 netmask." = "מסכת רשת IPv4 שגויה."; "Invalid IPv6 address." = "כתובת IPv6 שגויה."; "Invalid IPv6 prefix length." = "אורך קידומת IPv6 שגויה."; "Invalid network configuration." = "הגדרות הרשת שגויות."; "Job canceled." = "המשימה בוטלה."; "Job held." = "המשימה מוחזקת."; "Job released." = "המשימה שוחררה."; "Manual Configuration" = "הגדרות ידניות"; "Missing job ID." = "חסר מזהה משימה."; "Release Held New Jobs" = "שחרור משימות חדשות שהוחזקו"; "Suriname" = "סורינאם"; "Svalbard and Jan Mayen" = "איי סבאלברד ויאן מאיין"; "Tunisia" = "תוניסיה"; "finishings.80" = "ניקוב 3 חורים מימין"; "finishings.81" = "ניקוב 3 חורים מלמטה"; "job-state-reasons.compression-error" = "שגיאת פריסה."; "Sint Maarten (Dutch part)" = "סן מרטן (השטח ההולנדי)"; "United States Minor Outlying Islands" = "איים קטנים מרוחקים של ארצות הברית"; "Hidden SSID" = "SSID מוסתר"; "Missing network name." = "שם הרשת חסר."; "City/Locality" = "עיר/מועצה אזורית"; "yesterday at %02d:%02d:%02d" = "אתמול ב־%02d:%02d:%02d"; "media.na_c5_6.5x9.5in" = "מעטפה C5"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b10_32x45mm" = "JIS B10"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_b7_88x125mm" = "B7"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b8_64x91mm" = "JIS B8"; "media.iso_a5-extra_174x235mm" = "A5 (מוגדל)"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a3_297x420mm" = "A3"; "media.jis_b6_128x182mm" = "JIS B6"; "media.iso_b3_353x500mm" = "B3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.jis_b3_364x515mm" = "JIS B3"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_b9_44x62mm" = "B9"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a9_37x52mm" = "A9"; "media.jis_b2_515x728mm" = "JIS B2"; "media.iso_b8_62x88mm" = "B8"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b6_125x176mm" = "B6"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_a5_148x210mm" = "A5"; "media.jis_exec_216x330mm" = ""; "media.iso_b10_31x44mm" = "B10"; "media.jis_b9_45x64mm" = "JIS B9"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (מוגדל)"; "media.iso_a3-extra_322x445mm" = "A3 (מוגדל)"; "media.jis_b5_182x257mm" = "JIS B5"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media-type.paper" = "נייר"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_b2_500x707mm" = "B2"; pappl-1.4.9/pappl/strings/it.strings000066400000000000000000001362421476704353100175170ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Annulla tutti i lavori (cancella.)"; " -c COPIES" = "-c COP"; " -d PRINTER Specify printer." = " -d PRINTER Specifica la stampante."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Specificare l'ID del lavoro (cancel.)"; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Specificare il driver (add/modify.)"; " -n COPIES Specify number of copies (submit)." = " -n COPIES Specificare il numero di copie (sottomesso.)"; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Specificare l'opzione (add,modify,server,submit.)"; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 a 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 a 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZZAZIONE"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Specifica ipp: o ipps: stampante/server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Specificare la presa: o usb: dispositivo (add/modify.)"; " add PRINTER Add a printer." = " add PRINTER Aggiungi una stampante."; " autoadd Automatically add supported printers." = " autoadd Aggiungi automaticamente le stampanti supportate."; " cancel Cancel one or more jobs." = " cancel Cancella uno o più lavori."; " default Set the default printer." = " default Impostare la stampante predefinita."; " delete Delete a printer." = " delete Cancella una stampante."; " devices List devices." = " devices Elenca dispositivi."; " drivers List drivers." = " drivers Elenca i driver."; " jobs List jobs." = " jobs Lista lavori."; " modify Modify a printer." = " modify modificare una stampante."; " options List printer options." = " options Elenca le opzioni della stampante."; " pause Pause printing for a printer." = " pause Stampa pausa per una stampante."; " printers List printers." = " printers Elenca le stampanti."; " resume Resume printing for a printer." = " resume Riprendi la stampa per una stampante."; " server Run a server." = " server Eseguire un server."; " shutdown Shutdown a running server." = " shutdown Spegni un server in esecuzione."; " status Show server/printer/job status." = " status Mostra lo stato server/printer/job."; " submit Submit a file for printing." = " submit inviare un file per la stampa."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d pollici/sec"; "%d job" = "%d lavoro"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%d dpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g \""; /* size (type+borderless) */ "%s (%s%s)" = "%s ( %s %s )"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) da %s"; /* Source/Tray Media */ "%s Media" = "%s Media"; "%s: Bad 'server-port' value." = "%s: Bad server-port value."; "%s: Bad job ID." = "Bad job ID."; "%s: Bad printer URI '%s'." = "%s: Scarsa URI stampante ' %s '."; "%s: Cannot specify more than one sub-command." = "%s: Non è possibile specificare più di un sottocomando."; "%s: Empty print file received on the standard input." = "%s: File di stampa vuoto ricevuto sull'ingresso standard."; "%s: Failed to create a system." = "%s: Non è riuscito a creare un sistema."; "%s: Missing '-d PRINTER'." = "%s: Manca il \"-d PRINTER\". '"; "%s: Missing '-m DRIVER-NAME'." = "%s: Mancano '-m DRIVER-NAME. '"; "%s: Missing '-v DEVICE-URI'." = "%s: Manca \"-v DEVICE-URI\". '"; "%s: Missing copy count after '-n'." = "%s: Conto di copia mancante dopo -n."; "%s: Missing device URI after '-v'." = "%s: URI dispositivo mancante dopo -v."; "%s: Missing driver name after '-m'." = "%s: Nome del conducente mancante dopo -m."; "%s: Missing filename after '--'." = "%s: Nome file mancante dopo \"--\"."; "%s: Missing hostname after '-h'." = "%s: Nome host mancante dopo -h."; "%s: Missing job ID after '-j'." = "%s: Identificazione del lavoro dopo -j."; "%s: Missing option(s) after '-o'." = "%s: opzione mancante (s) dopo -o."; "%s: Missing printer URI after '-u'." = "%s: URI della stampante mancante dopo -u."; "%s: Missing printer name after '-d'." = "%s: Nome della stampante mancante dopo -d."; "%s: Missing space after '-o'." = "%s: Manca spazio dopo -o."; "%s: Missing title after '-t'." = "%s: Titolo mancante dopo -t."; "%s: No default printer available." = "%s: Nessuna stampante predefinita disponibile."; "%s: No files to print." = "%s: Nessun file da stampare."; "%s: Server is not running." = "%s: Il server non è in esecuzione."; "%s: Sub-command '%s' does not accept files." = "%s: Sub-command '%s' non accetta i file."; "%s: Sub-command 'autoadd' is not supported." = "%s: L'autoadd subcomand non è supportato."; "%s: Too many files." = "%s: Troppi file."; "%s: Unable to access '%s': %s" = "%s: Incapace di accedere '%s': %s"; "%s: Unable to add printer: %s" = "%s: Incapace di aggiungere la stampante: %s"; "%s: Unable to cancel job: %s" = "%s: Incapace di annullare il lavoro: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Incapace di connettersi alla stampante a '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Incapace di connettersi al server: %s"; "%s: Unable to create temporary file: %s" = "%s: Incapace di creare file temporanei: %s"; "%s: Unable to delete printer: %s" = "%s: Incapace di eliminare la stampante: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Incapace di ottenere informazioni per '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Incapace di ottenere informazioni per la stampante: %s"; "%s: Unable to get printer options: %s" = "%s: Incapace di ottenere le opzioni della stampante: %s"; "%s: Unable to modify printer: %s" = "%s: Incapace di modificare la stampante: %s"; "%s: Unable to pause printer: %s" = "%s: Incapace di mettere in pausa la stampante: %s"; "%s: Unable to print '%s': %s" = "%s: Incapace di stampare ' %s ': %s"; "%s: Unable to resume printer: %s" = "%s: Incapace di riprendere la stampante: %s"; "%s: Unable to set default printer: %s" = "%s: Non è possibile impostare la stampante predefinita: %s"; "%s: Unable to shutdown server: %s" = "%s: Non è possibile disattivare il server: %s"; "%s: Unable to start server: %s" = "%s: Incapace di avviare il server: %s"; "%s: Unable to write to temporary file: %s" = "%s: Incapace di scrivere a file temporanei: %s"; "%s: Unknown option '%s'." = "%s: Opzione sconosciuta '%s'."; "%s: Unknown option '-%c'." = "%s: Opzione sconosciuta '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Sconosciuto sottocomandi '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Schema URI non supportato %s '."; "%s: Warning - user credentials are not supported in URIs." = "%s: Attenzione: le credenziali dell'utente non sono supportate negli URI."; ", Borderless" = "♪"; "A printer with that name already exists." = "Una stampante con quel nome esiste già."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Aggiungi stampante"; "Admin Group" = "Gruppo di amministrazione"; "Afghanistan" = "Afghanistan"; "Albania" = "Albania"; "Algeria" = "Algeria"; "American Samoa" = "American Samoa"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antartide"; "Antigua and Barbuda" = "Antigua e Barbuda"; "Argentina" = "Argentina"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Auto"; "Auto-Detect Driver" = "Driver di rilevamento automatico"; "Azerbaijan" = "Azerbaigian"; "Bad administration group." = "Brutto gruppo amministrativo."; "Bad port number." = "Brutto numero di porta."; "Bad print group." = "Cattivo gruppo di stampa."; "Bad printer defaults." = "Bad default della stampante."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrain"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbados"; "Belarus" = "Bielorussia"; "Belgium" = "Belgio"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivia (Stato nazionale)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius e Saba"; "Borderless" = "Borderless"; "Bosnia and Herzegovina" = "Bosnia-Erzegovina"; "Botswana" = "Botswana"; "Bouvet Island" = "Isola di Bouvet"; "Brazil" = "Brasile"; "British Indian Ocean Territory" = "British Indian Ocean Territorio"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bulgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Cambogia"; "Cameroon" = "Camerun"; "Canada" = "Canada"; "Cancel All Jobs" = "Annulla tutti i lavori"; "Cancel Job" = "Annullare il lavoro"; "Canceled %s" = "Canceled %s"; "Canceling" = "Annullamento"; "Cayman Islands" = "Isole Cayman"; "Central African Republic" = "Repubblica Centrafricana"; "Certificate created." = "Certificato creato."; "Certificate installed." = "Certificato installato."; "Certificate request created." = "Richiesta certificato creata."; "Chad" = "Ciad"; "Change Access Password" = "Cambia password di accesso"; "Change Log Level" = "Cambia il livello di registro"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Modifica della rete Wi-Fi"; "Changes Saved." = "Cambiamenti salvati."; "Changes saved." = "Cambiamenti salvati."; "Chile" = "Cile"; "China" = "Cina"; "Christmas Island" = "Isola di Natale"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Isole Cocos (Keeling)"; "Colombia" = "Colombia"; "Comoros" = "Comore"; "Completed %s" = "Completed %s"; "Configuration" = "Configurazione"; "Configure Media" = "Configurare i media"; "Confirm Cancel All" = "Confermare Annulla Tutti"; "Confirm Delete Printer" = "Conferma Cancella stampante"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, Repubblica Democratica del"; "Contact" = "Contatto"; "Cook Islands" = "Isole Cook"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Crea richiesta di firma del certificato"; "Create New Certificate" = "Crea nuovo certificato"; "Create New TLS Certificate" = "Crea nuovo certificato TLS"; "Create TLS Certificate Request" = "Creare TLS Richiesta certificato"; "Croatia" = "Croazia"; "Cuba" = "Cuba"; "Curaçao" = "Curaa"; "Current Password" = "Password corrente"; "Custom Size" = "Dimensione personalizzata"; "Cyprus" = "Cipro"; "Czechia" = "Repubblica ceca"; "Côte d'Ivoire" = "Cte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "Nome di servizio DNS-SD"; "Debugging" = "Debug"; "Default printer set." = "Set stampante predefinito."; "Delete" = "Cancella"; "Delete Printer" = "Eliminare la stampante"; "Denmark" = "Danimarca"; "Djibouti" = "Gibuti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominica"; "Dominican Republic" = "Repubblica Dominicana"; "Download Certificate Request File" = "Scarica il file di richiesta del certificato"; "Ecuador" = "Ecuador"; "Egypt" = "Egitto"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Guinea equatoriale"; "Eritrea" = "Eritrea"; "Errors" = "Errori"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Etiopia"; "Falkland Islands (Malvinas)" = "Isole Falkland (Malvinas)"; "Faroe Islands" = "Isole Faroe"; "Fatal Errors/Conditions" = "Errori/Condizioni"; "Fiji" = "Fiji"; "Finland" = "Finlandia"; "France" = "Francia"; "French Guiana" = "Guiana francese"; "French Polynesia" = "Polinesia francese"; "French Southern Territories" = "Territori del Sud francese"; "Gabon" = "Gabon"; "Gambia" = "Gambia"; "Georgia" = "Georgia"; "Germany" = "Germania"; "Ghana" = "Ghana"; "Gibraltar" = "Gibilterra"; "Greece" = "Grecia"; "Greenland" = "Groenlandia"; "Grenada" = "Grenada"; "Group changes saved." = "Cambiamenti di gruppo salvati."; "Guadeloupe" = "Guadalupa"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Island e McDonald Islands"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Santa Sede"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Nome host"; "Human-Readable Location" = "Posizione leggibile umana"; "Hungary" = "Ungheria"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Islanda"; "Identify Printer" = "Identificare la stampante"; "India" = "India"; "Indonesia" = "Indonesia"; "Informational" = "Informazioni"; "Install TLS Certificate" = "Installare TLS Certificato"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Invalid Job ID."; "Invalid certificate or private key." = "Certificato non valido o chiave privata."; "Invalid form data." = "Dati formali non validi."; "Invalid form submission." = "Modulo non valido."; "Invalid job ID." = "ID del lavoro non valido."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (Repubblica Islamica di)"; "Iraq" = "Iraq"; "Ireland" = "Irlanda"; "Isle of Man" = "Isle of Man"; "Israel" = "Israele"; "Italy" = "Italia"; "Jamaica" = "Giamaica"; "Japan" = "Giappone"; "Jersey" = "Jersey"; "Job #" = "Lavoro"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Lavoro"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Giordania"; "Kazakhstan" = "Kazakistan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Corea (Repubblica popolare democratica)"; "Korea, Republic of" = "Repubblica di Corea"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kirghizistan"; "Landscape" = "paesaggio paesaggio"; "Lao People's Democratic Republic" = "Lao Repubblica Democratica del Popolo"; "Latvia" = "Lettonia"; "Lebanon" = "Libano"; "Lesotho" = "Lesotho"; "Level" = "Livello"; "Liberia" = "Liberia"; "Libya" = "Libia"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lituania"; "Location" = "Location"; "Log Level" = "Livello di log"; "Logging" = "Registrazione"; "Logs" = "Log"; "Luxembourg" = "Lussemburgo"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malesia"; "Maldives" = "Maldive"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Isole Marshall"; "Martinique" = "Martinica"; "Mauritania" = "Mauritania"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Media"; "Mexico" = "Messico"; "Micronesia (Federated States of)" = "Micronesia (Stati federali)"; "Missing action." = "Azione mancante."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "Manca la chiave privata."; "Moldova, Republic of" = "Moldavia, Repubblica"; "Monaco" = "Monaco"; "Mongolia" = "Mongolia"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Marocco"; "Mozambique" = "Mozambico"; "Myanmar" = "Myanmar"; "Name" = "Nome"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Paesi Bassi"; "Network" = "Rete di rete"; "Network Printer" = "Stampante di rete"; "Networking" = "Networking"; "New Caledonia" = "Nuova Caledonia"; "New Zealand" = "Nuova Zelanda"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "Nessuna stampante predefinita impostata."; "No jobs in history." = "Nessun lavoro nella storia."; "Norfolk Island" = "Isola di Norfolk"; "North Macedonia" = "Macedonia settentrionale"; "Northern Mariana Islands" = "Isole Marianne Settentrionali"; "Norway" = "Norvegia"; "Not set" = "Non impostato"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Opzioni:"; "Organization" = "Organizzazione"; "Organization Name" = "Nome dell'organizzazione"; "Other Settings" = "Altre impostazioni"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palestina, Stato di"; "Panama" = "Panama"; "Papua New Guinea" = "Papua Nuova Guinea"; "Paraguay" = "Paraguay"; "Password" = "Password"; "Password changed." = "La password è cambiata."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "La password deve essere lunga almeno otto caratteri e contenere almeno una lettera maiuscola, una lettera minuscola e una cifra."; "Passwords do not match." = "Le password non corrispondono."; "Pause Printing" = "Stampa Pausa"; "Peru" = "Perù"; "Philippines" = "Filippine"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Inserisci un nome host o un indirizzo IP per la stampante."; "Please enter a printer name." = "Inserisci un nome della stampante."; "Please select a device." = "Selezionare un dispositivo."; "Please select a driver." = "Si prega di selezionare un driver."; "Please select a valid log level." = "Si prega di selezionare un livello di registro valido."; "Poland" = "Polonia"; "Portrait" = "Ritratto"; "Portugal" = "Portogallo"; "Primary DNS" = "Primary DNS"; "Print Group" = "Gruppo di stampa"; "Print Test Page" = "Pagina di test di stampa"; "Print job options:" = "Stampa opzioni di lavoro:"; "Printer identified." = "Stampante identificata."; "Printer is currently active." = "La stampante è attualmente attiva."; "Printer names must start with a letter or underscore and cannot contain special characters." = "I nomi della stampante devono iniziare con una lettera o un sottoscopo e non possono contenere caratteri speciali."; "Printer options:" = "Opzioni di stampa:"; "Printer paused." = "Stampante in pausa."; "Printer pausing." = "Stampante pausing."; "Printer resuming." = "Stampante che riprende."; "Printers" = "Stampanti"; "Printing Defaults" = "Stampa di default"; "Puerto Rico" = "Porto Rico"; "Qatar" = "Qatar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Ristampa lavoro"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Riprendi la stampa"; "Reverse Landscape" = "Paesaggio inverso"; "Reverse Portrait" = "Ritratto inverso"; "Romania" = "Romania"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Correre, %s da %s %s ."; "Russian Federation" = "Federazione russa"; "Rwanda" = "Ruanda"; "Réunion" = "Runion"; "Saint Barthélemy" = "San Bartolomeo"; "Saint Helena, Ascension and Tristan da Cunha" = "Sant'Elena, Ascensione e Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts e Nevis"; "Saint Lucia" = "Santa Lucia"; "Saint Martin (French part)" = "Saint Martin (parte francese)"; "Saint Pierre and Miquelon" = "Saint Pierre e Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent e Grenadine"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome e Principe"; "Saudi Arabia" = "Arabia Saudita"; "Save Changes" = "Salvare le modifiche"; "Secondary DNS" = "Secondary DNS"; "Security" = "Sicurezza"; "Select Driver" = "Selezionare il driver"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "Il server non è in esecuzione."; "Set Access Password" = "Impostare la password di accesso"; "Set as Default" = "Impostare come predefinito"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapore"; "Sint Maarten (Dutch part)" = "Sint Maarten (parte olandese)"; "Slovakia" = "Slovacchia"; "Slovenia" = "Slovenia"; "Solomon Islands" = "Isole Salomone"; "Somalia" = "Somalia"; "South Africa" = "Sudafrica"; "South Georgia and the South Sandwich Islands" = "Georgia del Sud e Isole Sandwich del Sud"; "South Sudan" = "Sudan del Sud"; "Spain" = "Spagna"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "Stato"; "Sub-commands:" = "Sottocomandi:"; "Sudan" = "Sudan"; "Supplies" = "Forniture"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard e Jan Mayen"; "Sweden" = "Svezia"; "Switzerland" = "Svizzera"; "Syrian Arab Republic" = "Repubblica araba siriana"; "Taiwan, Province of China" = "Taiwan, Provincia della Cina"; "Tajikistan" = "Tajikistan"; "Tanzania, United Republic of" = "Tanzania, Regno Unito"; "Test page printed." = "Testa stampata."; "Thailand" = "Thailandia"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Questo modulo crea una richiesta di firma del certificato (CSR) che è possibile inviare a un'Autorità di certificazione (CA) per ottenere un certificato TLS affidabile. La chiave privata viene salvata separatamente per l'uso con il certificato che si ottiene dalla CA."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Questo modulo crea un nuovo certificato TLS autofirmato per la stampa sicura. I certificati auto-firmati non sono automaticamente affidabili dai browser web."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Questo modulo installerà un certificato TLS di fiducia che hai ottenuto da un'Autorità di certificazione (CA.) Una volta installato, verrà utilizzato immediatamente."; "Timor-Leste" = "Timor Est"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad e Tobago"; "Tunisia" = "Tunisia"; "Turkey" = "Turchia"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Isole Turks e Caicos"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ucraina"; "Unable to access test print file." = "Non è possibile accedere al file di stampa di prova."; "Unable to copy print job." = "Incapace di copiare il lavoro di stampa."; "Unable to create certificate request." = "Non è possibile creare una richiesta di certificato."; "Unable to create certificate." = "Non è possibile creare un certificato."; "Unable to create test print job." = "Incapace di creare un lavoro di stampa di prova."; "Unable to identify printer." = "Incapace di identificare la stampante."; "Unable to lookup address." = "Non riesco a cercare l'indirizzo."; "Unable to use that driver." = "Non riesco a usare quel conducente."; "United Arab Emirates" = "Emirati Arabi Uniti"; "United Kingdom" = "Regno Unito"; "United Kingdom of Great Britain and Northern Ireland" = "Regno Unito di Gran Bretagna e Irlanda del Nord"; "United States Minor Outlying Islands" = "Isole Minori degli Stati Uniti"; "United States of America" = "Stati Uniti d'America"; "Unknown" = "Sconosciuto"; "Unknown action." = "Azione sconosciuta."; "Unknown form action." = "Azione forma sconosciuta."; "Unknown form request." = "Richiesta forma sconosciuta."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Utilizzo: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Usa la mia posizione"; "Users" = "Utenti"; "Uzbekistan" = "Uzbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (Repubblica bolivariana di)"; "Version %s" = "Versione %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "Visualizza i log"; "Virgin Islands (British)" = "Isole Vergini (britanniche)"; "Virgin Islands (U.S.)" = "Isole Vergini (USA)"; "Wallis and Futuna" = "Wallis e Futuna"; "Warning" = "Avvertenza"; "Western Sahara" = "Sahara occidentale"; "Wi-Fi Configuration" = "Configurazione Wi-Fi"; "Wi-Fi Network" = "Rete Wi-Fi"; "Width" = "Larghezza"; "Wrong old password." = "Una vecchia password sbagliata."; "Yemen" = "Yemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Numero di copie"; "default printer" = "stampante predefinita"; "finishings" = "Finitura"; "finishings.10" = "Piegare"; "finishings.100" = "Z fold"; "finishings.101" = "Ingegneria Z fold"; "finishings.11" = "Taglio"; "finishings.12" = "Bale"; "finishings.13" = "Produttore di libri"; "finishings.15" = "Cappotto"; "finishings.16" = "Laminato"; "finishings.20" = "Piano a sinistra"; "finishings.21" = "Fondo a sinistra"; "finishings.22" = "Staple top destra"; "finishings.23" = "Fondo a destra"; "finishings.24" = "Cucitura bordo sinistra"; "finishings.25" = "Maglia di punto bordo"; "finishings.26" = "Cucitura bordo destra"; "finishings.27" = "Bordo punto inferiore"; "finishings.28" = "2 graffe a sinistra"; "finishings.29" = "2 graffe in alto"; "finishings.3" = "Nessuno"; "finishings.30" = "2 graffe a destra"; "finishings.31" = "2 graffe sul fondo"; "finishings.32" = "3 graffe a sinistra"; "finishings.33" = "3 graffe in alto"; "finishings.34" = "3 graffe a destra"; "finishings.35" = "3 graffe sul fondo"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind sinistra"; "finishings.51" = "Top Bind"; "finishings.52" = "A destra binaria"; "finishings.53" = "Fondo legato"; "finishings.6" = "Copertura"; "finishings.60" = "Tagliare ogni pagina"; "finishings.61" = "Tagliare dopo ogni documento"; "finishings.62" = "Tagliare dopo ogni set"; "finishings.63" = "Tagliare dopo il lavoro"; "finishings.7" = "Bind"; "finishings.70" = "In alto a sinistra"; "finishings.71" = "In basso a sinistra"; "finishings.72" = "Cima a destra"; "finishings.73" = "Taglio basso a destra"; "finishings.74" = "2 buche a sinistra"; "finishings.75" = "Pugno a 2 buche"; "finishings.76" = "Pugno a 2 buche a destra"; "finishings.77" = "2 buche fondo del pugno"; "finishings.78" = "Punzone a 3 buche sinistra"; "finishings.79" = "Top a 3 buche"; "finishings.8" = "Cucitura della sella"; "finishings.80" = "3 buche destra"; "finishings.81" = "3 buche di fondo"; "finishings.82" = "Punzone a 4 buche sinistra"; "finishings.83" = "Top a 4 buche"; "finishings.84" = "4 buche destra"; "finishings.85" = "4 buche di fondo"; "finishings.86" = "Punzone a più buche sinistra"; "finishings.87" = "Taglio a foro multiplo"; "finishings.88" = "Pugno multiforo a destra"; "finishings.89" = "Taglio a foro multi"; "finishings.9" = "Cucitura bordo"; "finishings.90" = "Piega di accordo"; "finishings.91" = "Doppio cancello pieghevole"; "finishings.92" = "Cancello pieghevole"; "finishings.93" = "Mezza piega"; "finishings.94" = "Piega mezza Z"; "finishings.95" = "Cancello sinistro"; "finishings.96" = "Letter fold"; "finishings.97" = "Piega parallela"; "finishings.98" = "Poster fold"; "finishings.99" = "Cancello destro"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Stoccata."; "job-state-reasons.compression-error" = "Errore di decompressione."; "job-state-reasons.document-format-error" = "Errore formato documento."; "job-state-reasons.document-password-error" = "Errore della password del documento."; "job-state-reasons.document-permission-error" = "Errore di autorizzazione del documento."; "job-state-reasons.document-unprintable-error" = "Documento errore non stampabile."; "job-state-reasons.errors-detected" = "Errori rilevati."; "job-state-reasons.job-canceled-at-device" = "Annullato alla stampante."; "job-state-reasons.job-canceled-by-user" = "Annullato dall'utente."; "job-state-reasons.job-completed-successfully" = "Stampato."; "job-state-reasons.job-completed-with-errors" = "Stampato con errori."; "job-state-reasons.job-completed-with-warnings" = "Stampato con avvisi."; "job-state-reasons.job-data-insufficient" = "Dati insufficienti."; "job-state-reasons.job-fetchable" = "In piedi."; "job-state-reasons.job-incoming" = "In arrivo."; "job-state-reasons.job-printing" = "Stampa."; "job-state-reasons.job-queued" = "Prepararsi alla stampa."; "job-state-reasons.job-spooling" = "Spooling."; "job-state-reasons.none" = "In attesa."; "job-state-reasons.printer-stopped" = "Stampante offline."; "job-state-reasons.printer-stopped-partly" = "Stampante parzialmente interrotta."; "job-state-reasons.processing-to-stop-point" = "Stoccata."; "job-state-reasons.queued-in-device" = "Pronti."; "job-state-reasons.warnings-detected" = "Avvertenze rilevate."; "job-state.3" = "Finanziamenti"; "job-state.4" = "Tenuto"; "job-state.5" = "Trattamento"; "job-state.6" = "Fermata"; "job-state.7" = "Annullamento"; "job-state.8" = "Abortito"; "job-state.9" = "Completato"; "joining" = "unirsi"; "media" = "Media"; "media-col" = "Media"; "media-size" = "Dimensioni media"; "media-size-name" = "Dimensioni media"; "media-source" = "Vassoio di ingresso"; "media-source.alternate" = "Alternare"; "media-source.alternate-roll" = "Rotolo alternativo"; "media-source.auto" = "Automatico"; "media-source.bottom" = "Fondo"; "media-source.by-pass-tray" = "Vassoio multiuso"; "media-source.center" = "Centro"; "media-source.disc" = "Disc"; "media-source.envelope" = "Busta"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Grande capacità"; "media-source.left" = "Sinistra"; "media-source.main" = "Principale"; "media-source.main-roll" = "Rullo principale"; "media-source.manual" = "Manuale"; "media-source.middle" = "Medio"; "media-source.photo" = "Foto"; "media-source.rear" = "Indietro"; "media-source.right" = "Giusto."; "media-source.roll-1" = "Rotolo 1"; "media-source.roll-10" = "Rotolo 10"; "media-source.roll-2" = "Rotolo 2"; "media-source.roll-3" = "Rotolo 3"; "media-source.roll-4" = "Rotolo 4"; "media-source.roll-5" = "Rotolo 5"; "media-source.roll-6" = "Rotolo 6"; "media-source.roll-7" = "Rotolo 7"; "media-source.roll-8" = "Rotolo 8"; "media-source.roll-9" = "Rotolo 9"; "media-source.side" = "Lato"; "media-source.top" = "Top"; "media-source.tray-1" = "Vassoio 1"; "media-source.tray-10" = "Vassoio 10"; "media-source.tray-11" = "Vassoio 11"; "media-source.tray-12" = "Vassoio 12"; "media-source.tray-13" = "Vassoio 13"; "media-source.tray-14" = "Vassoio 14"; "media-source.tray-15" = "Vassoio 15"; "media-source.tray-16" = "Vassoio 16"; "media-source.tray-17" = "Vassoio 17"; "media-source.tray-18" = "Vassoio 18"; "media-source.tray-19" = "Vassoio 19"; "media-source.tray-2" = "Vassoio 2"; "media-source.tray-20" = "Vassoio 20"; "media-source.tray-3" = "Vassoio 3"; "media-source.tray-4" = "Vassoio 4"; "media-source.tray-5" = "Vassoio 5"; "media-source.tray-6" = "Vassoio 6"; "media-source.tray-7" = "Vassoio 7"; "media-source.tray-8" = "Vassoio 8"; "media-source.tray-9" = "Vassoio 9"; "media-tracking" = "Monitoraggio dei media"; "media-tracking.continuous" = "Continuo"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Tipo di mezzo"; "media-type.aluminum" = "Alluminio"; "media-type.auto" = "Automatico"; "media-type.back-print-film" = "Film di stampa"; "media-type.cardboard" = "Carta"; "media-type.cardstock" = "Carni bovine"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuo"; "media-type.continuous-long" = "Lunga durata continua"; "media-type.continuous-short" = "Basso continuo"; "media-type.corrugated-board" = "Consiglio ondulato"; "media-type.disc" = "Disco ottico"; "media-type.disc-glossy" = "Disco ottico lucido"; "media-type.disc-high-gloss" = "Disco ottico lucido"; "media-type.disc-matte" = "Disco ottico opaco"; "media-type.disc-satin" = "Disco ottico raso"; "media-type.disc-semi-gloss" = "Disco ottico semiglossa"; "media-type.double-wall" = "Doppia parete"; "media-type.dry-film" = "Film secco"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Foglio di goffratura"; "media-type.end-board" = "Pensione finale"; "media-type.envelope" = "Busta"; "media-type.envelope-archival" = "Busta Archival"; "media-type.envelope-bond" = "Busta di legame"; "media-type.envelope-coated" = "Busta rivestita"; "media-type.envelope-cotton" = "Busta di cotone"; "media-type.envelope-fine" = "Fine busta"; "media-type.envelope-heavyweight" = "Busta pesante"; "media-type.envelope-inkjet" = "Busta a getto d'inchiostro"; "media-type.envelope-lightweight" = "Busta leggera"; "media-type.envelope-plain" = "Busta di lamina"; "media-type.envelope-preprinted" = "Busta prestampata"; "media-type.envelope-window" = "Busta finestrata"; "media-type.fabric" = "Tessuto"; "media-type.fabric-archival" = "Tessuto d'archival"; "media-type.fabric-glossy" = "Tessuto lucido"; "media-type.fabric-high-gloss" = "Tessuto lucido"; "media-type.fabric-matte" = "Tessuto opaco"; "media-type.fabric-semi-gloss" = "Tessuto semi-glossa"; "media-type.fabric-waterproof" = "Tessuto impermeabile"; "media-type.film" = "Film"; "media-type.flexo-base" = "Base Flexo"; "media-type.flexo-photo-polymer" = "Polimero fotografico Flexo"; "media-type.flute" = "Flusso"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "Tavole di taglio complete"; "media-type.glass" = "Vetro"; "media-type.glass-colored" = "Vetro colorato"; "media-type.glass-opaque" = "Vetro opaco"; "media-type.glass-surfaced" = "Vetro superficiale"; "media-type.glass-textured" = "Vetro strutturato"; "media-type.gravure-cylinder" = "Cilindro di scarico"; "media-type.image-setter-paper" = "Immagine carta setter"; "media-type.imaging-cylinder" = "Cilindro di imaging"; "media-type.labels" = "Etichette"; "media-type.labels-colored" = "Etichette colorate"; "media-type.labels-glossy" = "Etichette lucide"; "media-type.labels-high-gloss" = "Etichette ad alta lucentezza"; "media-type.labels-inkjet" = "Etichette inkjet"; "media-type.labels-matte" = "Etichette opzionali"; "media-type.labels-permanent" = "Etichette permanenti"; "media-type.labels-satin" = "Etichette in raso"; "media-type.labels-security" = "Etichette di sicurezza"; "media-type.labels-semi-gloss" = "Etichette semi-glossa"; "media-type.laminating-foil" = "Laminazione"; "media-type.letterhead" = "Lettera"; "media-type.metal" = "Metallo"; "media-type.metal-glossy" = "Metallo lucido"; "media-type.metal-high-gloss" = "Metallo lucido"; "media-type.metal-matte" = "Metallo opaco"; "media-type.metal-satin" = "Metallo satinato"; "media-type.metal-semi-gloss" = "Metal semi lucido"; "media-type.mounting-tape" = "Nastro di montaggio"; "media-type.multi-layer" = "Multi strato"; "media-type.multi-part-form" = "Forma a più parti"; "media-type.other" = "Altri"; "media-type.paper" = "Carta"; "media-type.photographic" = "Carta fotografica"; "media-type.photographic-archival" = "Archivio fotografico"; "media-type.photographic-film" = "Film fotografici"; "media-type.photographic-glossy" = "Carta fotografica lucida"; "media-type.photographic-high-gloss" = "Carta fotografica lucida"; "media-type.photographic-matte" = "Carta fotografica opaca"; "media-type.photographic-satin" = "Carta fotografica raso"; "media-type.photographic-semi-gloss" = "Carta fotografica semiglossa"; "media-type.plastic" = "Plastica"; "media-type.plastic-archival" = "Archivio plastica"; "media-type.plastic-colored" = "Plastica colorata"; "media-type.plastic-glossy" = "Plastica lucida"; "media-type.plastic-high-gloss" = "Plastica alta lucentezza"; "media-type.plastic-matte" = "opaco di plastica"; "media-type.plastic-satin" = "Raso di plastica"; "media-type.plastic-semi-gloss" = "Plastica semiluce"; "media-type.plate" = "Piatto"; "media-type.polyester" = "Poliestere"; "media-type.pre-cut-tabs" = "Tavole pre-taglio"; "media-type.roll" = "Roll"; "media-type.screen" = "Schermo"; "media-type.screen-paged" = "Pagina dello schermo"; "media-type.self-adhesive" = "Autoadesivo"; "media-type.self-adhesive-film" = "Film autoadesivo"; "media-type.shrink-foil" = "Lamina di gamberetti"; "media-type.single-face" = "Faccia singola"; "media-type.single-wall" = "Singola parete"; "media-type.sleeve" = "Manica"; "media-type.stationery" = "Cancelleria"; "media-type.stationery-archival" = "Archivio della Cancelleria"; "media-type.stationery-coated" = "Carta rivestita"; "media-type.stationery-cotton" = "Cotone di cancelleria"; "media-type.stationery-fine" = "Carta di velluto"; "media-type.stationery-heavyweight" = "Carta resistente"; "media-type.stationery-heavyweight-coated" = "Posteriore pesante rivestito"; "media-type.stationery-inkjet" = "Carta a getto d'inchiostro"; "media-type.stationery-letterhead" = "Lettera"; "media-type.stationery-lightweight" = "Carta leggera"; "media-type.stationery-preprinted" = "Carta stampata"; "media-type.stationery-prepunched" = "Carta perforata"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Trattore"; "media-type.transfer" = "Trasferimento"; "media-type.transparency" = "Trasparenza"; "media-type.triple-wall" = "Tripla parete"; "media-type.wet-film" = "Wet film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 o US Letter"; "media.iso_2a0_1189x1682mm" = "2."; "media.iso_a0_841x1189mm" = "A."; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3-3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 busta"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B."; "media.iso_c0_917x1297mm" = "C0 busta"; "media.iso_c10_28x40mm" = "C10 busta"; "media.iso_c1_648x917mm" = "C1 busta"; "media.iso_c2_458x648mm" = "C2 busta"; "media.iso_c3_324x458mm" = "C3 busta"; "media.iso_c4_229x324mm" = "C4 busta"; "media.iso_c5_162x229mm" = "C5 busta"; "media.iso_c6_114x162mm" = "C6 busta"; "media.iso_c6c5_114x229mm" = "C6/C5 busta"; "media.iso_c7_81x114mm" = "C7 busta"; "media.iso_c7c6_81x162mm" = "C7/C6"; "media.iso_c8_57x81mm" = "C8 busta"; "media.iso_c9_40x57mm" = "C9 busta"; "media.iso_dl_110x220mm" = "Busta DL"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Esecutivo"; "media.jpn_chou2_111.1x146mm" = "Busta Chou 2"; "media.jpn_chou3_120x235mm" = "Busta Chou 3"; "media.jpn_chou40_90x225mm" = "Busta Chou 40"; "media.jpn_chou4_90x205mm" = "Busta Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Busta Kahu"; "media.jpn_kaku2_240x332mm" = "Busta Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Rispondi"; "media.jpn_you4_105x235mm" = "Busta 4"; "media.na_a2_4.375x5.75in" = "Busta A2"; "media.na_c5_6.5x9.5in" = "Busta C5"; "media.na_executive_7.25x10.5in" = "Esecutivo"; "media.na_fanfold-eur_8.5x12in" = "Fanfold europeo"; "media.na_fanfold-us_11x14.875in" = "Fanfold USA"; "media.na_foolscap_8.5x13in" = "Schiuma"; "media.na_invoice_5.5x8.5in" = "Dichiarazione"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "Legale USA"; "media.na_letter-extra_9.5x12in" = "Lettera degli Stati Uniti (Extra)"; "media.na_letter-plus_8.5x12.69in" = "Lettera degli Stati Uniti (Plus)"; "media.na_letter_8.5x11in" = "Lettera degli Stati Uniti"; "media.na_monarch_3.875x7.5in" = "Busta Monarch"; "media.na_number-10_4.125x9.5in" = "Busta #10"; "media.na_number-11_4.5x10.375in" = "Busta #11"; "media.na_number-12_4.75x11in" = "Busta #12"; "media.na_number-14_5x11.5in" = "Busta #14"; "media.na_number-9_3.875x8.875in" = "Busta #9"; "media.na_personal_3.625x6.5in" = "Busta personale"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Invito alla busta"; "media.om_italian_110x230mm" = "Busta italiana"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180 mm"; "media.om_pa-kai_267x389mm" = "267 x 389m m"; "media.om_postfix_114x229mm" = "Postfix della busta"; "media.prc_10_324x458mm" = "Busta cinese #10"; "media.prc_16k_146x215mm" = "Cinese 16k"; "media.prc_1_102x165mm" = "Busta cinese #1"; "media.prc_2_102x176mm" = "Busta cinese #2"; "media.prc_32k_97x151mm" = "Cinese 32k"; "media.prc_3_125x176mm" = "Busta cinese #3"; "media.prc_4_110x208mm" = "Busta cinese #4"; "media.prc_5_110x220mm" = "Busta cinese #5"; "media.prc_6_120x320mm" = "Busta cinese #6"; "media.prc_7_160x230mm" = "Busta cinese #7"; "media.prc_8_120x309mm" = "Busta cinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8."; "not configured" = "non configurato"; "not visible" = "non visibile"; "off" = "Fuori"; "on" = "su"; "orientation-requested" = "Orientamento"; "orientation-requested.3" = "Ritratto"; "orientation-requested.4" = "paesaggio paesaggio"; "orientation-requested.5" = "Paesaggio inverso"; "orientation-requested.6" = "Ritratto inverso"; "orientation-requested.7" = "Nessuno"; "output-bin" = "Vassoio di uscita"; "output-bin.auto" = "Automatico"; "output-bin.bottom" = "Fondo"; "output-bin.center" = "Centro"; "output-bin.face-down" = "Faccia a terra"; "output-bin.face-up" = "Faccia in su"; "output-bin.large-capacity" = "Grande capacità"; "output-bin.left" = "Sinistra"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Medio"; "output-bin.my-mailbox" = "La mia casella di posta"; "output-bin.rear" = "Indietro"; "output-bin.right" = "Giusto."; "output-bin.side" = "Lato"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Vassoio 1"; "output-bin.tray-10" = "Vassoio 10"; "output-bin.tray-2" = "Vassoio 2"; "output-bin.tray-3" = "Vassoio 3"; "output-bin.tray-4" = "Vassoio 4"; "output-bin.tray-5" = "Vassoio 5"; "output-bin.tray-6" = "Vassoio 6"; "output-bin.tray-7" = "Vassoio 7"; "output-bin.tray-8" = "Vassoio 8"; "output-bin.tray-9" = "Vassoio 9"; "print-color-mode" = "Modalità di stampa"; "print-color-mode.auto" = "Automatico"; "print-color-mode.auto-monochrome" = "Auto monocromatica"; "print-color-mode.bi-level" = "Testo"; "print-color-mode.color" = "Colore"; "print-color-mode.highlight" = "In evidenza"; "print-color-mode.monochrome" = "Monocromatico"; "print-color-mode.process-bi-level" = "Testo di processo"; "print-color-mode.process-monochrome" = "Processo monocromatico"; "print-content-optimize" = "Ottimizzazione per"; "print-content-optimize.auto" = "Automatico"; "print-content-optimize.graphic" = "Grafica"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Testo"; "print-content-optimize.text-and-graphic" = "Testo e grafica"; "print-darkness" = "Stampa Oscurità"; "print-quality" = "Qualità della stampa"; "print-quality.3" = "Progetto"; "print-quality.4" = "Normale"; "print-quality.5" = "Migliore"; "print-scaling" = "Scala"; "print-scaling.auto" = "Automatico"; "print-scaling.auto-fit" = "Autofit"; "print-scaling.fill" = "Riempi"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "Nessuno"; "print-speed" = "Velocità di stampa"; "printer-resolution" = "Risoluzione"; "printer-state-reasons.cover-open" = "Copertina aperta."; "printer-state-reasons.door-open" = "Porta aperta."; "printer-state-reasons.identify-printer-requested" = "Identificare la stampante."; "printer-state-reasons.input-tray-missing" = "Vassoio di carta mancante."; "printer-state-reasons.marker-supply-empty" = "Fuori dall'inchiostro."; "printer-state-reasons.marker-supply-low" = "Inchiostro basso."; "printer-state-reasons.marker-waste-almost-full" = "Cestino quasi pieno."; "printer-state-reasons.marker-waste-full" = "Cestino pieno."; "printer-state-reasons.media-empty" = "Fuori carta."; "printer-state-reasons.media-jam" = "La marmellata di carta."; "printer-state-reasons.media-low" = "Sostituisci la carta presto."; "printer-state-reasons.media-needed" = "Carta di carico."; "printer-state-reasons.none" = "Pronti."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "Vedi la stampante."; "printer-state-reasons.spool-area-full" = "Stampante occupata."; "printer-state-reasons.toner-empty" = "Fuori dal toner."; "printer-state-reasons.toner-low" = "Toner basso."; "printer-state.3" = "Idle"; "printer-state.4" = "Trattamento"; "printer-state.5" = "Fermata"; "sides" = "Stampa a 2 posizioni"; "sides.one-sided" = "Fuori"; "sides.two-sided-long-edge" = "Su (portrait)"; "sides.two-sided-short-edge" = "Su (paesaggio)"; "unable to join" = "in grado di aderire"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Isole"; pappl-1.4.9/pappl/strings/it_strings.h000066400000000000000000001567451476704353100200400ustar00rootroot00000000000000static const char *it_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Annulla tutti i lavori (cancella.)\";\n" "\" -c COPIES\" = \"-c COP\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Specifica la stampante.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Specificare l'ID del lavoro (cancel.)\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Specificare il driver (add/modify.)\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Specificare il numero di copie (sottomesso.)\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (default)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=VALUE Specificare l'opzione (add,modify,server,submit.)\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 a 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 a 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOCATION\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZZAZIONE\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Specifica ipp: o ipps: stampante/server.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Specificare la presa: o usb: dispositivo (add/modify.)\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Aggiungi una stampante.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Aggiungi automaticamente le stampanti supportate.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Cancella uno o più lavori.\";\n" "\" default Set the default printer.\" = \" default Impostare la stampante predefinita.\";\n" "\" delete Delete a printer.\" = \" delete Cancella una stampante.\";\n" "\" devices List devices.\" = \" devices Elenca dispositivi.\";\n" "\" drivers List drivers.\" = \" drivers Elenca i driver.\";\n" "\" jobs List jobs.\" = \" jobs Lista lavori.\";\n" "\" modify Modify a printer.\" = \" modify modificare una stampante.\";\n" "\" options List printer options.\" = \" options Elenca le opzioni della stampante.\";\n" "\" pause Pause printing for a printer.\" = \" pause Stampa pausa per una stampante.\";\n" "\" printers List printers.\" = \" printers Elenca le stampanti.\";\n" "\" resume Resume printing for a printer.\" = \" resume Riprendi la stampa per una stampante.\";\n" "\" server Run a server.\" = \" server Eseguire un server.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Spegni un server in esecuzione.\";\n" "\" status Show server/printer/job status.\" = \" status Mostra lo stato server/printer/job.\";\n" "\" submit Submit a file for printing.\" = \" submit inviare un file per la stampa.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d pollici/sec\";\n" "\"%d job\" = \"%d lavoro\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%d dpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g \\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s ( %s %s )\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) da %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Media\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Bad server-port value.\";\n" "\"%s: Bad job ID.\" = \"Bad job ID.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Scarsa URI stampante ' %s '.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Non è possibile specificare più di un sottocomando.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: File di stampa vuoto ricevuto sull'ingresso standard.\";\n" "\"%s: Failed to create a system.\" = \"%s: Non è riuscito a creare un sistema.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Manca il \\\"-d PRINTER\\\". '\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Mancano '-m DRIVER-NAME. '\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Manca \\\"-v DEVICE-URI\\\". '\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Conto di copia mancante dopo -n.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: URI dispositivo mancante dopo -v.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Nome del conducente mancante dopo -m.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Nome file mancante dopo \\\"--\\\".\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Nome host mancante dopo -h.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Identificazione del lavoro dopo -j.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: opzione mancante (s) dopo -o.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: URI della stampante mancante dopo -u.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Nome della stampante mancante dopo -d.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Manca spazio dopo -o.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Titolo mancante dopo -t.\";\n" "\"%s: No default printer available.\" = \"%s: Nessuna stampante predefinita disponibile.\";\n" "\"%s: No files to print.\" = \"%s: Nessun file da stampare.\";\n" "\"%s: Server is not running.\" = \"%s: Il server non è in esecuzione.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Sub-command '%s' non accetta i file.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: L'autoadd subcomand non è supportato.\";\n" "\"%s: Too many files.\" = \"%s: Troppi file.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Incapace di accedere '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Incapace di aggiungere la stampante: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Incapace di annullare il lavoro: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Incapace di connettersi alla stampante a '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Incapace di connettersi al server: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Incapace di creare file temporanei: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Incapace di eliminare la stampante: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Incapace di ottenere informazioni per '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Incapace di ottenere informazioni per la stampante: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Incapace di ottenere le opzioni della stampante: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Incapace di modificare la stampante: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Incapace di mettere in pausa la stampante: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Incapace di stampare ' %s ': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Incapace di riprendere la stampante: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Non è possibile impostare la stampante predefinita: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Non è possibile disattivare il server: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Incapace di avviare il server: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Incapace di scrivere a file temporanei: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Opzione sconosciuta '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Opzione sconosciuta '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Sconosciuto sottocomandi '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Schema URI non supportato %s '.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Attenzione: le credenziali dell'utente non sono supportate negli URI.\";\n" "\", Borderless\" = \"♪\";\n" "\"A printer with that name already exists.\" = \"Una stampante con quel nome esiste già.\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"Aggiungi stampante\";\n" "\"Admin Group\" = \"Gruppo di amministrazione\";\n" "\"Afghanistan\" = \"Afghanistan\";\n" "\"Albania\" = \"Albania\";\n" "\"Algeria\" = \"Algeria\";\n" "\"American Samoa\" = \"American Samoa\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antartide\";\n" "\"Antigua and Barbuda\" = \"Antigua e Barbuda\";\n" "\"Argentina\" = \"Argentina\";\n" "\"Armenia\" = \"Armenia\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australia\";\n" "\"Austria\" = \"Austria\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Driver di rilevamento automatico\";\n" "\"Azerbaijan\" = \"Azerbaigian\";\n" "\"Bad administration group.\" = \"Brutto gruppo amministrativo.\";\n" "\"Bad port number.\" = \"Brutto numero di porta.\";\n" "\"Bad print group.\" = \"Cattivo gruppo di stampa.\";\n" "\"Bad printer defaults.\" = \"Bad default della stampante.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahrain\";\n" "\"Bangladesh\" = \"Bangladesh\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Bielorussia\";\n" "\"Belgium\" = \"Belgio\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermuda\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivia (Stato nazionale)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius e Saba\";\n" "\"Borderless\" = \"Borderless\";\n" "\"Bosnia and Herzegovina\" = \"Bosnia-Erzegovina\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Isola di Bouvet\";\n" "\"Brazil\" = \"Brasile\";\n" "\"British Indian Ocean Territory\" = \"British Indian Ocean Territorio\";\n" "\"Brunei Darussalam\" = \"Brunei Darussalam\";\n" "\"Bulgaria\" = \"Bulgaria\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cabo Verde\";\n" "\"Cambodia\" = \"Cambogia\";\n" "\"Cameroon\" = \"Camerun\";\n" "\"Canada\" = \"Canada\";\n" "\"Cancel All Jobs\" = \"Annulla tutti i lavori\";\n" "\"Cancel Job\" = \"Annullare il lavoro\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"Annullamento\";\n" "\"Cayman Islands\" = \"Isole Cayman\";\n" "\"Central African Republic\" = \"Repubblica Centrafricana\";\n" "\"Certificate created.\" = \"Certificato creato.\";\n" "\"Certificate installed.\" = \"Certificato installato.\";\n" "\"Certificate request created.\" = \"Richiesta certificato creata.\";\n" "\"Chad\" = \"Ciad\";\n" "\"Change Access Password\" = \"Cambia password di accesso\";\n" "\"Change Log Level\" = \"Cambia il livello di registro\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"Modifica della rete Wi-Fi\";\n" "\"Changes Saved.\" = \"Cambiamenti salvati.\";\n" "\"Changes saved.\" = \"Cambiamenti salvati.\";\n" "\"Chile\" = \"Cile\";\n" "\"China\" = \"Cina\";\n" "\"Christmas Island\" = \"Isola di Natale\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"Isole Cocos (Keeling)\";\n" "\"Colombia\" = \"Colombia\";\n" "\"Comoros\" = \"Comore\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"Configurazione\";\n" "\"Configure Media\" = \"Configurare i media\";\n" "\"Confirm Cancel All\" = \"Confermare Annulla Tutti\";\n" "\"Confirm Delete Printer\" = \"Conferma Cancella stampante\";\n" "\"Congo\" = \"Congo\";\n" "\"Congo, Democratic Republic of the\" = \"Congo, Repubblica Democratica del\";\n" "\"Contact\" = \"Contatto\";\n" "\"Cook Islands\" = \"Isole Cook\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Crea richiesta di firma del certificato\";\n" "\"Create New Certificate\" = \"Crea nuovo certificato\";\n" "\"Create New TLS Certificate\" = \"Crea nuovo certificato TLS\";\n" "\"Create TLS Certificate Request\" = \"Creare TLS Richiesta certificato\";\n" "\"Croatia\" = \"Croazia\";\n" "\"Cuba\" = \"Cuba\";\n" "\"Curaçao\" = \"Curaa\";\n" "\"Current Password\" = \"Password corrente\";\n" "\"Custom Size\" = \"Dimensione personalizzata\";\n" "\"Cyprus\" = \"Cipro\";\n" "\"Czechia\" = \"Repubblica ceca\";\n" "\"Côte d'Ivoire\" = \"Cte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"Nome di servizio DNS-SD\";\n" "\"Debugging\" = \"Debug\";\n" "\"Default printer set.\" = \"Set stampante predefinito.\";\n" "\"Delete\" = \"Cancella\";\n" "\"Delete Printer\" = \"Eliminare la stampante\";\n" "\"Denmark\" = \"Danimarca\";\n" "\"Djibouti\" = \"Gibuti\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"Dominica\";\n" "\"Dominican Republic\" = \"Repubblica Dominicana\";\n" "\"Download Certificate Request File\" = \"Scarica il file di richiesta del certificato\";\n" "\"Ecuador\" = \"Ecuador\";\n" "\"Egypt\" = \"Egitto\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Guinea equatoriale\";\n" "\"Eritrea\" = \"Eritrea\";\n" "\"Errors\" = \"Errori\";\n" "\"Estonia\" = \"Estonia\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Etiopia\";\n" "\"Falkland Islands (Malvinas)\" = \"Isole Falkland (Malvinas)\";\n" "\"Faroe Islands\" = \"Isole Faroe\";\n" "\"Fatal Errors/Conditions\" = \"Errori/Condizioni\";\n" "\"Fiji\" = \"Fiji\";\n" "\"Finland\" = \"Finlandia\";\n" "\"France\" = \"Francia\";\n" "\"French Guiana\" = \"Guiana francese\";\n" "\"French Polynesia\" = \"Polinesia francese\";\n" "\"French Southern Territories\" = \"Territori del Sud francese\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Georgia\";\n" "\"Germany\" = \"Germania\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibilterra\";\n" "\"Greece\" = \"Grecia\";\n" "\"Greenland\" = \"Groenlandia\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Cambiamenti di gruppo salvati.\";\n" "\"Guadeloupe\" = \"Guadalupa\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Guinea\";\n" "\"Guinea-Bissau\" = \"Guinea-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island e McDonald Islands\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"Santa Sede\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Nome host\";\n" "\"Human-Readable Location\" = \"Posizione leggibile umana\";\n" "\"Hungary\" = \"Ungheria\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"Islanda\";\n" "\"Identify Printer\" = \"Identificare la stampante\";\n" "\"India\" = \"India\";\n" "\"Indonesia\" = \"Indonesia\";\n" "\"Informational\" = \"Informazioni\";\n" "\"Install TLS Certificate\" = \"Installare TLS Certificato\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"Invalid Job ID.\";\n" "\"Invalid certificate or private key.\" = \"Certificato non valido o chiave privata.\";\n" "\"Invalid form data.\" = \"Dati formali non validi.\";\n" "\"Invalid form submission.\" = \"Modulo non valido.\";\n" "\"Invalid job ID.\" = \"ID del lavoro non valido.\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (Repubblica Islamica di)\";\n" "\"Iraq\" = \"Iraq\";\n" "\"Ireland\" = \"Irlanda\";\n" "\"Isle of Man\" = \"Isle of Man\";\n" "\"Israel\" = \"Israele\";\n" "\"Italy\" = \"Italia\";\n" "\"Jamaica\" = \"Giamaica\";\n" "\"Japan\" = \"Giappone\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Lavoro\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"Lavoro\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"Giordania\";\n" "\"Kazakhstan\" = \"Kazakistan\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Corea (Repubblica popolare democratica)\";\n" "\"Korea, Republic of\" = \"Repubblica di Corea\";\n" "\"Kuwait\" = \"Kuwait\";\n" "\"Kyrgyzstan\" = \"Kirghizistan\";\n" "\"Landscape\" = \"paesaggio paesaggio\";\n" "\"Lao People's Democratic Republic\" = \"Lao Repubblica Democratica del Popolo\";\n" "\"Latvia\" = \"Lettonia\";\n" "\"Lebanon\" = \"Libano\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Livello\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libia\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Lituania\";\n" "\"Location\" = \"Location\";\n" "\"Log Level\" = \"Livello di log\";\n" "\"Logging\" = \"Registrazione\";\n" "\"Logs\" = \"Log\";\n" "\"Luxembourg\" = \"Lussemburgo\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagascar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malesia\";\n" "\"Maldives\" = \"Maldive\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"Isole Marshall\";\n" "\"Martinique\" = \"Martinica\";\n" "\"Mauritania\" = \"Mauritania\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Media\";\n" "\"Mexico\" = \"Messico\";\n" "\"Micronesia (Federated States of)\" = \"Micronesia (Stati federali)\";\n" "\"Missing action.\" = \"Azione mancante.\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"Manca la chiave privata.\";\n" "\"Moldova, Republic of\" = \"Moldavia, Repubblica\";\n" "\"Monaco\" = \"Monaco\";\n" "\"Mongolia\" = \"Mongolia\";\n" "\"Montenegro\" = \"Montenegro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Marocco\";\n" "\"Mozambique\" = \"Mozambico\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Nome\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Paesi Bassi\";\n" "\"Network\" = \"Rete di rete\";\n" "\"Network Printer\" = \"Stampante di rete\";\n" "\"Networking\" = \"Networking\";\n" "\"New Caledonia\" = \"Nuova Caledonia\";\n" "\"New Zealand\" = \"Nuova Zelanda\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"Nessuna stampante predefinita impostata.\";\n" "\"No jobs in history.\" = \"Nessun lavoro nella storia.\";\n" "\"Norfolk Island\" = \"Isola di Norfolk\";\n" "\"North Macedonia\" = \"Macedonia settentrionale\";\n" "\"Northern Mariana Islands\" = \"Isole Marianne Settentrionali\";\n" "\"Norway\" = \"Norvegia\";\n" "\"Not set\" = \"Non impostato\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Opzioni:\";\n" "\"Organization\" = \"Organizzazione\";\n" "\"Organization Name\" = \"Nome dell'organizzazione\";\n" "\"Other Settings\" = \"Altre impostazioni\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palestina, Stato di\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua Nuova Guinea\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Password\";\n" "\"Password changed.\" = \"La password è cambiata.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"La password deve essere lunga almeno otto caratteri e contenere almeno una lettera maiuscola, una lettera minuscola e una cifra.\";\n" "\"Passwords do not match.\" = \"Le password non corrispondono.\";\n" "\"Pause Printing\" = \"Stampa Pausa\";\n" "\"Peru\" = \"Perù\";\n" "\"Philippines\" = \"Filippine\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Inserisci un nome host o un indirizzo IP per la stampante.\";\n" "\"Please enter a printer name.\" = \"Inserisci un nome della stampante.\";\n" "\"Please select a device.\" = \"Selezionare un dispositivo.\";\n" "\"Please select a driver.\" = \"Si prega di selezionare un driver.\";\n" "\"Please select a valid log level.\" = \"Si prega di selezionare un livello di registro valido.\";\n" "\"Poland\" = \"Polonia\";\n" "\"Portrait\" = \"Ritratto\";\n" "\"Portugal\" = \"Portogallo\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"Gruppo di stampa\";\n" "\"Print Test Page\" = \"Pagina di test di stampa\";\n" "\"Print job options:\" = \"Stampa opzioni di lavoro:\";\n" "\"Printer identified.\" = \"Stampante identificata.\";\n" "\"Printer is currently active.\" = \"La stampante è attualmente attiva.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"I nomi della stampante devono iniziare con una lettera o un sottoscopo e non possono contenere caratteri speciali.\";\n" "\"Printer options:\" = \"Opzioni di stampa:\";\n" "\"Printer paused.\" = \"Stampante in pausa.\";\n" "\"Printer pausing.\" = \"Stampante pausing.\";\n" "\"Printer resuming.\" = \"Stampante che riprende.\";\n" "\"Printers\" = \"Stampanti\";\n" "\"Printing Defaults\" = \"Stampa di default\";\n" "\"Puerto Rico\" = \"Porto Rico\";\n" "\"Qatar\" = \"Qatar\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"Ristampa lavoro\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"Riprendi la stampa\";\n" "\"Reverse Landscape\" = \"Paesaggio inverso\";\n" "\"Reverse Portrait\" = \"Ritratto inverso\";\n" "\"Romania\" = \"Romania\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Correre, %s da %s %s .\";\n" "\"Russian Federation\" = \"Federazione russa\";\n" "\"Rwanda\" = \"Ruanda\";\n" "\"Réunion\" = \"Runion\";\n" "\"Saint Barthélemy\" = \"San Bartolomeo\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Sant'Elena, Ascensione e Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts e Nevis\";\n" "\"Saint Lucia\" = \"Santa Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (parte francese)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre e Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint Vincent e Grenadine\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Sao Tome e Principe\";\n" "\"Saudi Arabia\" = \"Arabia Saudita\";\n" "\"Save Changes\" = \"Salvare le modifiche\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"Sicurezza\";\n" "\"Select Driver\" = \"Selezionare il driver\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbia\";\n" "\"Server is not running.\" = \"Il server non è in esecuzione.\";\n" "\"Set Access Password\" = \"Impostare la password di accesso\";\n" "\"Set as Default\" = \"Impostare come predefinito\";\n" "\"Seychelles\" = \"Seychelles\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapore\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (parte olandese)\";\n" "\"Slovakia\" = \"Slovacchia\";\n" "\"Slovenia\" = \"Slovenia\";\n" "\"Solomon Islands\" = \"Isole Salomone\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"Sudafrica\";\n" "\"South Georgia and the South Sandwich Islands\" = \"Georgia del Sud e Isole Sandwich del Sud\";\n" "\"South Sudan\" = \"Sudan del Sud\";\n" "\"Spain\" = \"Spagna\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"Stato\";\n" "\"Sub-commands:\" = \"Sottocomandi:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Forniture\";\n" "\"Suriname\" = \"Suriname\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard e Jan Mayen\";\n" "\"Sweden\" = \"Svezia\";\n" "\"Switzerland\" = \"Svizzera\";\n" "\"Syrian Arab Republic\" = \"Repubblica araba siriana\";\n" "\"Taiwan, Province of China\" = \"Taiwan, Provincia della Cina\";\n" "\"Tajikistan\" = \"Tajikistan\";\n" "\"Tanzania, United Republic of\" = \"Tanzania, Regno Unito\";\n" "\"Test page printed.\" = \"Testa stampata.\";\n" "\"Thailand\" = \"Thailandia\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Questo modulo crea una richiesta di firma del certificato (CSR) che è possibile inviare a un'Autorità di certificazione (CA) per ottenere un certificato TLS affidabile. La chiave privata viene salvata separatamente per l'uso con il certificato che si ottiene dalla CA.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Questo modulo crea un nuovo certificato TLS autofirmato per la stampa sicura. I certificati auto-firmati non sono automaticamente affidabili dai browser web.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Questo modulo installerà un certificato TLS di fiducia che hai ottenuto da un'Autorità di certificazione (CA.) Una volta installato, verrà utilizzato immediatamente.\";\n" "\"Timor-Leste\" = \"Timor Est\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad e Tobago\";\n" "\"Tunisia\" = \"Tunisia\";\n" "\"Turkey\" = \"Turchia\";\n" "\"Turkmenistan\" = \"Turkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Isole Turks e Caicos\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ucraina\";\n" "\"Unable to access test print file.\" = \"Non è possibile accedere al file di stampa di prova.\";\n" "\"Unable to copy print job.\" = \"Incapace di copiare il lavoro di stampa.\";\n" "\"Unable to create certificate request.\" = \"Non è possibile creare una richiesta di certificato.\";\n" "\"Unable to create certificate.\" = \"Non è possibile creare un certificato.\";\n" "\"Unable to create test print job.\" = \"Incapace di creare un lavoro di stampa di prova.\";\n" "\"Unable to identify printer.\" = \"Incapace di identificare la stampante.\";\n" "\"Unable to lookup address.\" = \"Non riesco a cercare l'indirizzo.\";\n" "\"Unable to use that driver.\" = \"Non riesco a usare quel conducente.\";\n" "\"United Arab Emirates\" = \"Emirati Arabi Uniti\";\n" "\"United Kingdom\" = \"Regno Unito\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Regno Unito di Gran Bretagna e Irlanda del Nord\";\n" "\"United States Minor Outlying Islands\" = \"Isole Minori degli Stati Uniti\";\n" "\"United States of America\" = \"Stati Uniti d'America\";\n" "\"Unknown\" = \"Sconosciuto\";\n" "\"Unknown action.\" = \"Azione sconosciuta.\";\n" "\"Unknown form action.\" = \"Azione forma sconosciuta.\";\n" "\"Unknown form request.\" = \"Richiesta forma sconosciuta.\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Utilizzo: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\";\n" "\"Use My Position\" = \"Usa la mia posizione\";\n" "\"Users\" = \"Utenti\";\n" "\"Uzbekistan\" = \"Uzbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (Repubblica bolivariana di)\";\n" "\"Version %s\" = \"Versione %s\";\n" "\"Viet Nam\" = \"Viet Nam\";\n" "\"View Logs\" = \"Visualizza i log\";\n" "\"Virgin Islands (British)\" = \"Isole Vergini (britanniche)\";\n" "\"Virgin Islands (U.S.)\" = \"Isole Vergini (USA)\";\n" "\"Wallis and Futuna\" = \"Wallis e Futuna\";\n" "\"Warning\" = \"Avvertenza\";\n" "\"Western Sahara\" = \"Sahara occidentale\";\n" "\"Wi-Fi Configuration\" = \"Configurazione Wi-Fi\";\n" "\"Wi-Fi Network\" = \"Rete Wi-Fi\";\n" "\"Width\" = \"Larghezza\";\n" "\"Wrong old password.\" = \"Una vecchia password sbagliata.\";\n" "\"Yemen\" = \"Yemen\";\n" "\"Zambia\" = \"Zambia\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Numero di copie\";\n" "\"default printer\" = \"stampante predefinita\";\n" "\"finishings\" = \"Finitura\";\n" "\"finishings.10\" = \"Piegare\";\n" "\"finishings.100\" = \"Z fold\";\n" "\"finishings.101\" = \"Ingegneria Z fold\";\n" "\"finishings.11\" = \"Taglio\";\n" "\"finishings.12\" = \"Bale\";\n" "\"finishings.13\" = \"Produttore di libri\";\n" "\"finishings.15\" = \"Cappotto\";\n" "\"finishings.16\" = \"Laminato\";\n" "\"finishings.20\" = \"Piano a sinistra\";\n" "\"finishings.21\" = \"Fondo a sinistra\";\n" "\"finishings.22\" = \"Staple top destra\";\n" "\"finishings.23\" = \"Fondo a destra\";\n" "\"finishings.24\" = \"Cucitura bordo sinistra\";\n" "\"finishings.25\" = \"Maglia di punto bordo\";\n" "\"finishings.26\" = \"Cucitura bordo destra\";\n" "\"finishings.27\" = \"Bordo punto inferiore\";\n" "\"finishings.28\" = \"2 graffe a sinistra\";\n" "\"finishings.29\" = \"2 graffe in alto\";\n" "\"finishings.3\" = \"Nessuno\";\n" "\"finishings.30\" = \"2 graffe a destra\";\n" "\"finishings.31\" = \"2 graffe sul fondo\";\n" "\"finishings.32\" = \"3 graffe a sinistra\";\n" "\"finishings.33\" = \"3 graffe in alto\";\n" "\"finishings.34\" = \"3 graffe a destra\";\n" "\"finishings.35\" = \"3 graffe sul fondo\";\n" "\"finishings.4\" = \"Staple\";\n" "\"finishings.5\" = \"Punch\";\n" "\"finishings.50\" = \"Bind sinistra\";\n" "\"finishings.51\" = \"Top Bind\";\n" "\"finishings.52\" = \"A destra binaria\";\n" "\"finishings.53\" = \"Fondo legato\";\n" "\"finishings.6\" = \"Copertura\";\n" "\"finishings.60\" = \"Tagliare ogni pagina\";\n" "\"finishings.61\" = \"Tagliare dopo ogni documento\";\n" "\"finishings.62\" = \"Tagliare dopo ogni set\";\n" "\"finishings.63\" = \"Tagliare dopo il lavoro\";\n" "\"finishings.7\" = \"Bind\";\n" "\"finishings.70\" = \"In alto a sinistra\";\n" "\"finishings.71\" = \"In basso a sinistra\";\n" "\"finishings.72\" = \"Cima a destra\";\n" "\"finishings.73\" = \"Taglio basso a destra\";\n" "\"finishings.74\" = \"2 buche a sinistra\";\n" "\"finishings.75\" = \"Pugno a 2 buche\";\n" "\"finishings.76\" = \"Pugno a 2 buche a destra\";\n" "\"finishings.77\" = \"2 buche fondo del pugno\";\n" "\"finishings.78\" = \"Punzone a 3 buche sinistra\";\n" "\"finishings.79\" = \"Top a 3 buche\";\n" "\"finishings.8\" = \"Cucitura della sella\";\n" "\"finishings.80\" = \"3 buche destra\";\n" "\"finishings.81\" = \"3 buche di fondo\";\n" "\"finishings.82\" = \"Punzone a 4 buche sinistra\";\n" "\"finishings.83\" = \"Top a 4 buche\";\n" "\"finishings.84\" = \"4 buche destra\";\n" "\"finishings.85\" = \"4 buche di fondo\";\n" "\"finishings.86\" = \"Punzone a più buche sinistra\";\n" "\"finishings.87\" = \"Taglio a foro multiplo\";\n" "\"finishings.88\" = \"Pugno multiforo a destra\";\n" "\"finishings.89\" = \"Taglio a foro multi\";\n" "\"finishings.9\" = \"Cucitura bordo\";\n" "\"finishings.90\" = \"Piega di accordo\";\n" "\"finishings.91\" = \"Doppio cancello pieghevole\";\n" "\"finishings.92\" = \"Cancello pieghevole\";\n" "\"finishings.93\" = \"Mezza piega\";\n" "\"finishings.94\" = \"Piega mezza Z\";\n" "\"finishings.95\" = \"Cancello sinistro\";\n" "\"finishings.96\" = \"Letter fold\";\n" "\"finishings.97\" = \"Piega parallela\";\n" "\"finishings.98\" = \"Poster fold\";\n" "\"finishings.99\" = \"Cancello destro\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"Stoccata.\";\n" "\"job-state-reasons.compression-error\" = \"Errore di decompressione.\";\n" "\"job-state-reasons.document-format-error\" = \"Errore formato documento.\";\n" "\"job-state-reasons.document-password-error\" = \"Errore della password del documento.\";\n" "\"job-state-reasons.document-permission-error\" = \"Errore di autorizzazione del documento.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Documento errore non stampabile.\";\n" "\"job-state-reasons.errors-detected\" = \"Errori rilevati.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Annullato alla stampante.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Annullato dall'utente.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Stampato.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Stampato con errori.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Stampato con avvisi.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Dati insufficienti.\";\n" "\"job-state-reasons.job-fetchable\" = \"In piedi.\";\n" "\"job-state-reasons.job-incoming\" = \"In arrivo.\";\n" "\"job-state-reasons.job-printing\" = \"Stampa.\";\n" "\"job-state-reasons.job-queued\" = \"Prepararsi alla stampa.\";\n" "\"job-state-reasons.job-spooling\" = \"Spooling.\";\n" "\"job-state-reasons.none\" = \"In attesa.\";\n" "\"job-state-reasons.printer-stopped\" = \"Stampante offline.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Stampante parzialmente interrotta.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Stoccata.\";\n" "\"job-state-reasons.queued-in-device\" = \"Pronti.\";\n" "\"job-state-reasons.warnings-detected\" = \"Avvertenze rilevate.\";\n" "\"job-state.3\" = \"Finanziamenti\";\n" "\"job-state.4\" = \"Tenuto\";\n" "\"job-state.5\" = \"Trattamento\";\n" "\"job-state.6\" = \"Fermata\";\n" "\"job-state.7\" = \"Annullamento\";\n" "\"job-state.8\" = \"Abortito\";\n" "\"job-state.9\" = \"Completato\";\n" "\"joining\" = \"unirsi\";\n" "\"media\" = \"Media\";\n" "\"media-col\" = \"Media\";\n" "\"media-size\" = \"Dimensioni media\";\n" "\"media-size-name\" = \"Dimensioni media\";\n" "\"media-source\" = \"Vassoio di ingresso\";\n" "\"media-source.alternate\" = \"Alternare\";\n" "\"media-source.alternate-roll\" = \"Rotolo alternativo\";\n" "\"media-source.auto\" = \"Automatico\";\n" "\"media-source.bottom\" = \"Fondo\";\n" "\"media-source.by-pass-tray\" = \"Vassoio multiuso\";\n" "\"media-source.center\" = \"Centro\";\n" "\"media-source.disc\" = \"Disc\";\n" "\"media-source.envelope\" = \"Busta\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Grande capacità\";\n" "\"media-source.left\" = \"Sinistra\";\n" "\"media-source.main\" = \"Principale\";\n" "\"media-source.main-roll\" = \"Rullo principale\";\n" "\"media-source.manual\" = \"Manuale\";\n" "\"media-source.middle\" = \"Medio\";\n" "\"media-source.photo\" = \"Foto\";\n" "\"media-source.rear\" = \"Indietro\";\n" "\"media-source.right\" = \"Giusto.\";\n" "\"media-source.roll-1\" = \"Rotolo 1\";\n" "\"media-source.roll-10\" = \"Rotolo 10\";\n" "\"media-source.roll-2\" = \"Rotolo 2\";\n" "\"media-source.roll-3\" = \"Rotolo 3\";\n" "\"media-source.roll-4\" = \"Rotolo 4\";\n" "\"media-source.roll-5\" = \"Rotolo 5\";\n" "\"media-source.roll-6\" = \"Rotolo 6\";\n" "\"media-source.roll-7\" = \"Rotolo 7\";\n" "\"media-source.roll-8\" = \"Rotolo 8\";\n" "\"media-source.roll-9\" = \"Rotolo 9\";\n" "\"media-source.side\" = \"Lato\";\n" "\"media-source.top\" = \"Top\";\n" "\"media-source.tray-1\" = \"Vassoio 1\";\n" "\"media-source.tray-10\" = \"Vassoio 10\";\n" "\"media-source.tray-11\" = \"Vassoio 11\";\n" "\"media-source.tray-12\" = \"Vassoio 12\";\n" "\"media-source.tray-13\" = \"Vassoio 13\";\n" "\"media-source.tray-14\" = \"Vassoio 14\";\n" "\"media-source.tray-15\" = \"Vassoio 15\";\n" "\"media-source.tray-16\" = \"Vassoio 16\";\n" "\"media-source.tray-17\" = \"Vassoio 17\";\n" "\"media-source.tray-18\" = \"Vassoio 18\";\n" "\"media-source.tray-19\" = \"Vassoio 19\";\n" "\"media-source.tray-2\" = \"Vassoio 2\";\n" "\"media-source.tray-20\" = \"Vassoio 20\";\n" "\"media-source.tray-3\" = \"Vassoio 3\";\n" "\"media-source.tray-4\" = \"Vassoio 4\";\n" "\"media-source.tray-5\" = \"Vassoio 5\";\n" "\"media-source.tray-6\" = \"Vassoio 6\";\n" "\"media-source.tray-7\" = \"Vassoio 7\";\n" "\"media-source.tray-8\" = \"Vassoio 8\";\n" "\"media-source.tray-9\" = \"Vassoio 9\";\n" "\"media-tracking\" = \"Monitoraggio dei media\";\n" "\"media-tracking.continuous\" = \"Continuo\";\n" "\"media-tracking.gap\" = \"Gap\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Tipo di mezzo\";\n" "\"media-type.aluminum\" = \"Alluminio\";\n" "\"media-type.auto\" = \"Automatico\";\n" "\"media-type.back-print-film\" = \"Film di stampa\";\n" "\"media-type.cardboard\" = \"Carta\";\n" "\"media-type.cardstock\" = \"Carni bovine\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Continuo\";\n" "\"media-type.continuous-long\" = \"Lunga durata continua\";\n" "\"media-type.continuous-short\" = \"Basso continuo\";\n" "\"media-type.corrugated-board\" = \"Consiglio ondulato\";\n" "\"media-type.disc\" = \"Disco ottico\";\n" "\"media-type.disc-glossy\" = \"Disco ottico lucido\";\n" "\"media-type.disc-high-gloss\" = \"Disco ottico lucido\";\n" "\"media-type.disc-matte\" = \"Disco ottico opaco\";\n" "\"media-type.disc-satin\" = \"Disco ottico raso\";\n" "\"media-type.disc-semi-gloss\" = \"Disco ottico semiglossa\";\n" "\"media-type.double-wall\" = \"Doppia parete\";\n" "\"media-type.dry-film\" = \"Film secco\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Foglio di goffratura\";\n" "\"media-type.end-board\" = \"Pensione finale\";\n" "\"media-type.envelope\" = \"Busta\";\n" "\"media-type.envelope-archival\" = \"Busta Archival\";\n" "\"media-type.envelope-bond\" = \"Busta di legame\";\n" "\"media-type.envelope-coated\" = \"Busta rivestita\";\n" "\"media-type.envelope-cotton\" = \"Busta di cotone\";\n" "\"media-type.envelope-fine\" = \"Fine busta\";\n" "\"media-type.envelope-heavyweight\" = \"Busta pesante\";\n" "\"media-type.envelope-inkjet\" = \"Busta a getto d'inchiostro\";\n" "\"media-type.envelope-lightweight\" = \"Busta leggera\";\n" "\"media-type.envelope-plain\" = \"Busta di lamina\";\n" "\"media-type.envelope-preprinted\" = \"Busta prestampata\";\n" "\"media-type.envelope-window\" = \"Busta finestrata\";\n" "\"media-type.fabric\" = \"Tessuto\";\n" "\"media-type.fabric-archival\" = \"Tessuto d'archival\";\n" "\"media-type.fabric-glossy\" = \"Tessuto lucido\";\n" "\"media-type.fabric-high-gloss\" = \"Tessuto lucido\";\n" "\"media-type.fabric-matte\" = \"Tessuto opaco\";\n" "\"media-type.fabric-semi-gloss\" = \"Tessuto semi-glossa\";\n" "\"media-type.fabric-waterproof\" = \"Tessuto impermeabile\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Base Flexo\";\n" "\"media-type.flexo-photo-polymer\" = \"Polimero fotografico Flexo\";\n" "\"media-type.flute\" = \"Flusso\";\n" "\"media-type.foil\" = \"Foil\";\n" "\"media-type.full-cut-tabs\" = \"Tavole di taglio complete\";\n" "\"media-type.glass\" = \"Vetro\";\n" "\"media-type.glass-colored\" = \"Vetro colorato\";\n" "\"media-type.glass-opaque\" = \"Vetro opaco\";\n" "\"media-type.glass-surfaced\" = \"Vetro superficiale\";\n" "\"media-type.glass-textured\" = \"Vetro strutturato\";\n" "\"media-type.gravure-cylinder\" = \"Cilindro di scarico\";\n" "\"media-type.image-setter-paper\" = \"Immagine carta setter\";\n" "\"media-type.imaging-cylinder\" = \"Cilindro di imaging\";\n" "\"media-type.labels\" = \"Etichette\";\n" "\"media-type.labels-colored\" = \"Etichette colorate\";\n" "\"media-type.labels-glossy\" = \"Etichette lucide\";\n" "\"media-type.labels-high-gloss\" = \"Etichette ad alta lucentezza\";\n" "\"media-type.labels-inkjet\" = \"Etichette inkjet\";\n" "\"media-type.labels-matte\" = \"Etichette opzionali\";\n" "\"media-type.labels-permanent\" = \"Etichette permanenti\";\n" "\"media-type.labels-satin\" = \"Etichette in raso\";\n" "\"media-type.labels-security\" = \"Etichette di sicurezza\";\n" "\"media-type.labels-semi-gloss\" = \"Etichette semi-glossa\";\n" "\"media-type.laminating-foil\" = \"Laminazione\";\n" "\"media-type.letterhead\" = \"Lettera\";\n" "\"media-type.metal\" = \"Metallo\";\n" "\"media-type.metal-glossy\" = \"Metallo lucido\";\n" "\"media-type.metal-high-gloss\" = \"Metallo lucido\";\n" "\"media-type.metal-matte\" = \"Metallo opaco\";\n" "\"media-type.metal-satin\" = \"Metallo satinato\";\n" "\"media-type.metal-semi-gloss\" = \"Metal semi lucido\";\n" "\"media-type.mounting-tape\" = \"Nastro di montaggio\";\n" "\"media-type.multi-layer\" = \"Multi strato\";\n" "\"media-type.multi-part-form\" = \"Forma a più parti\";\n" "\"media-type.other\" = \"Altri\";\n" "\"media-type.paper\" = \"Carta\";\n" "\"media-type.photographic\" = \"Carta fotografica\";\n" "\"media-type.photographic-archival\" = \"Archivio fotografico\";\n" "\"media-type.photographic-film\" = \"Film fotografici\";\n" "\"media-type.photographic-glossy\" = \"Carta fotografica lucida\";\n" "\"media-type.photographic-high-gloss\" = \"Carta fotografica lucida\";\n" "\"media-type.photographic-matte\" = \"Carta fotografica opaca\";\n" "\"media-type.photographic-satin\" = \"Carta fotografica raso\";\n" "\"media-type.photographic-semi-gloss\" = \"Carta fotografica semiglossa\";\n" "\"media-type.plastic\" = \"Plastica\";\n" "\"media-type.plastic-archival\" = \"Archivio plastica\";\n" "\"media-type.plastic-colored\" = \"Plastica colorata\";\n" "\"media-type.plastic-glossy\" = \"Plastica lucida\";\n" "\"media-type.plastic-high-gloss\" = \"Plastica alta lucentezza\";\n" "\"media-type.plastic-matte\" = \"opaco di plastica\";\n" "\"media-type.plastic-satin\" = \"Raso di plastica\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastica semiluce\";\n" "\"media-type.plate\" = \"Piatto\";\n" "\"media-type.polyester\" = \"Poliestere\";\n" "\"media-type.pre-cut-tabs\" = \"Tavole pre-taglio\";\n" "\"media-type.roll\" = \"Roll\";\n" "\"media-type.screen\" = \"Schermo\";\n" "\"media-type.screen-paged\" = \"Pagina dello schermo\";\n" "\"media-type.self-adhesive\" = \"Autoadesivo\";\n" "\"media-type.self-adhesive-film\" = \"Film autoadesivo\";\n" "\"media-type.shrink-foil\" = \"Lamina di gamberetti\";\n" "\"media-type.single-face\" = \"Faccia singola\";\n" "\"media-type.single-wall\" = \"Singola parete\";\n" "\"media-type.sleeve\" = \"Manica\";\n" "\"media-type.stationery\" = \"Cancelleria\";\n" "\"media-type.stationery-archival\" = \"Archivio della Cancelleria\";\n" "\"media-type.stationery-coated\" = \"Carta rivestita\";\n" "\"media-type.stationery-cotton\" = \"Cotone di cancelleria\";\n" "\"media-type.stationery-fine\" = \"Carta di velluto\";\n" "\"media-type.stationery-heavyweight\" = \"Carta resistente\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Posteriore pesante rivestito\";\n" "\"media-type.stationery-inkjet\" = \"Carta a getto d'inchiostro\";\n" "\"media-type.stationery-letterhead\" = \"Lettera\";\n" "\"media-type.stationery-lightweight\" = \"Carta leggera\";\n" "\"media-type.stationery-preprinted\" = \"Carta stampata\";\n" "\"media-type.stationery-prepunched\" = \"Carta perforata\";\n" "\"media-type.tab-stock\" = \"Tab stock\";\n" "\"media-type.tractor\" = \"Trattore\";\n" "\"media-type.transfer\" = \"Trasferimento\";\n" "\"media-type.transparency\" = \"Trasparenza\";\n" "\"media-type.triple-wall\" = \"Tripla parete\";\n" "\"media-type.wet-film\" = \"Wet film\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 o US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2.\";\n" "\"media.iso_a0_841x1189mm\" = \"A.\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3-3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 busta\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B.\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 busta\";\n" "\"media.iso_c10_28x40mm\" = \"C10 busta\";\n" "\"media.iso_c1_648x917mm\" = \"C1 busta\";\n" "\"media.iso_c2_458x648mm\" = \"C2 busta\";\n" "\"media.iso_c3_324x458mm\" = \"C3 busta\";\n" "\"media.iso_c4_229x324mm\" = \"C4 busta\";\n" "\"media.iso_c5_162x229mm\" = \"C5 busta\";\n" "\"media.iso_c6_114x162mm\" = \"C6 busta\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 busta\";\n" "\"media.iso_c7_81x114mm\" = \"C7 busta\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6\";\n" "\"media.iso_c8_57x81mm\" = \"C8 busta\";\n" "\"media.iso_c9_40x57mm\" = \"C9 busta\";\n" "\"media.iso_dl_110x220mm\" = \"Busta DL\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Esecutivo\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Busta Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Busta Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Busta Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Busta Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Busta Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Busta Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Rispondi\";\n" "\"media.jpn_you4_105x235mm\" = \"Busta 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Busta A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Busta C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Esecutivo\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"Fanfold europeo\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"Fanfold USA\";\n" "\"media.na_foolscap_8.5x13in\" = \"Schiuma\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Dichiarazione\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"Legale USA\";\n" "\"media.na_letter-extra_9.5x12in\" = \"Lettera degli Stati Uniti (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"Lettera degli Stati Uniti (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"Lettera degli Stati Uniti\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Busta Monarch\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Busta #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Busta #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Busta #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Busta #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Busta #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Busta personale\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (Special)\";\n" "\"media.om_invite_220x220mm\" = \"Invito alla busta\";\n" "\"media.om_italian_110x230mm\" = \"Busta italiana\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180 mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389m m\";\n" "\"media.om_postfix_114x229mm\" = \"Postfix della busta\";\n" "\"media.prc_10_324x458mm\" = \"Busta cinese #10\";\n" "\"media.prc_16k_146x215mm\" = \"Cinese 16k\";\n" "\"media.prc_1_102x165mm\" = \"Busta cinese #1\";\n" "\"media.prc_2_102x176mm\" = \"Busta cinese #2\";\n" "\"media.prc_32k_97x151mm\" = \"Cinese 32k\";\n" "\"media.prc_3_125x176mm\" = \"Busta cinese #3\";\n" "\"media.prc_4_110x208mm\" = \"Busta cinese #4\";\n" "\"media.prc_5_110x220mm\" = \"Busta cinese #5\";\n" "\"media.prc_6_120x320mm\" = \"Busta cinese #6\";\n" "\"media.prc_7_160x230mm\" = \"Busta cinese #7\";\n" "\"media.prc_8_120x309mm\" = \"Busta cinese #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8.\";\n" "\"not configured\" = \"non configurato\";\n" "\"not visible\" = \"non visibile\";\n" "\"off\" = \"Fuori\";\n" "\"on\" = \"su\";\n" "\"orientation-requested\" = \"Orientamento\";\n" "\"orientation-requested.3\" = \"Ritratto\";\n" "\"orientation-requested.4\" = \"paesaggio paesaggio\";\n" "\"orientation-requested.5\" = \"Paesaggio inverso\";\n" "\"orientation-requested.6\" = \"Ritratto inverso\";\n" "\"orientation-requested.7\" = \"Nessuno\";\n" "\"output-bin\" = \"Vassoio di uscita\";\n" "\"output-bin.auto\" = \"Automatico\";\n" "\"output-bin.bottom\" = \"Fondo\";\n" "\"output-bin.center\" = \"Centro\";\n" "\"output-bin.face-down\" = \"Faccia a terra\";\n" "\"output-bin.face-up\" = \"Faccia in su\";\n" "\"output-bin.large-capacity\" = \"Grande capacità\";\n" "\"output-bin.left\" = \"Sinistra\";\n" "\"output-bin.mailbox-1\" = \"Mailbox 1\";\n" "\"output-bin.mailbox-10\" = \"Mailbox 10\";\n" "\"output-bin.mailbox-2\" = \"Mailbox 2\";\n" "\"output-bin.mailbox-3\" = \"Mailbox 3\";\n" "\"output-bin.mailbox-4\" = \"Mailbox 4\";\n" "\"output-bin.mailbox-5\" = \"Mailbox 5\";\n" "\"output-bin.mailbox-6\" = \"Mailbox 6\";\n" "\"output-bin.mailbox-7\" = \"Mailbox 7\";\n" "\"output-bin.mailbox-8\" = \"Mailbox 8\";\n" "\"output-bin.mailbox-9\" = \"Mailbox 9\";\n" "\"output-bin.middle\" = \"Medio\";\n" "\"output-bin.my-mailbox\" = \"La mia casella di posta\";\n" "\"output-bin.rear\" = \"Indietro\";\n" "\"output-bin.right\" = \"Giusto.\";\n" "\"output-bin.side\" = \"Lato\";\n" "\"output-bin.stacker-1\" = \"Stacker 1\";\n" "\"output-bin.stacker-10\" = \"Stacker 10\";\n" "\"output-bin.stacker-2\" = \"Stacker 2\";\n" "\"output-bin.stacker-3\" = \"Stacker 3\";\n" "\"output-bin.stacker-4\" = \"Stacker 4\";\n" "\"output-bin.stacker-5\" = \"Stacker 5\";\n" "\"output-bin.stacker-6\" = \"Stacker 6\";\n" "\"output-bin.stacker-7\" = \"Stacker 7\";\n" "\"output-bin.stacker-8\" = \"Stacker 8\";\n" "\"output-bin.stacker-9\" = \"Stacker 9\";\n" "\"output-bin.top\" = \"Top\";\n" "\"output-bin.tray-1\" = \"Vassoio 1\";\n" "\"output-bin.tray-10\" = \"Vassoio 10\";\n" "\"output-bin.tray-2\" = \"Vassoio 2\";\n" "\"output-bin.tray-3\" = \"Vassoio 3\";\n" "\"output-bin.tray-4\" = \"Vassoio 4\";\n" "\"output-bin.tray-5\" = \"Vassoio 5\";\n" "\"output-bin.tray-6\" = \"Vassoio 6\";\n" "\"output-bin.tray-7\" = \"Vassoio 7\";\n" "\"output-bin.tray-8\" = \"Vassoio 8\";\n" "\"output-bin.tray-9\" = \"Vassoio 9\";\n" "\"print-color-mode\" = \"Modalità di stampa\";\n" "\"print-color-mode.auto\" = \"Automatico\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monocromatica\";\n" "\"print-color-mode.bi-level\" = \"Testo\";\n" "\"print-color-mode.color\" = \"Colore\";\n" "\"print-color-mode.highlight\" = \"In evidenza\";\n" "\"print-color-mode.monochrome\" = \"Monocromatico\";\n" "\"print-color-mode.process-bi-level\" = \"Testo di processo\";\n" "\"print-color-mode.process-monochrome\" = \"Processo monocromatico\";\n" "\"print-content-optimize\" = \"Ottimizzazione per\";\n" "\"print-content-optimize.auto\" = \"Automatico\";\n" "\"print-content-optimize.graphic\" = \"Grafica\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Testo\";\n" "\"print-content-optimize.text-and-graphic\" = \"Testo e grafica\";\n" "\"print-darkness\" = \"Stampa Oscurità\";\n" "\"print-quality\" = \"Qualità della stampa\";\n" "\"print-quality.3\" = \"Progetto\";\n" "\"print-quality.4\" = \"Normale\";\n" "\"print-quality.5\" = \"Migliore\";\n" "\"print-scaling\" = \"Scala\";\n" "\"print-scaling.auto\" = \"Automatico\";\n" "\"print-scaling.auto-fit\" = \"Autofit\";\n" "\"print-scaling.fill\" = \"Riempi\";\n" "\"print-scaling.fit\" = \"Fit\";\n" "\"print-scaling.none\" = \"Nessuno\";\n" "\"print-speed\" = \"Velocità di stampa\";\n" "\"printer-resolution\" = \"Risoluzione\";\n" "\"printer-state-reasons.cover-open\" = \"Copertina aperta.\";\n" "\"printer-state-reasons.door-open\" = \"Porta aperta.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Identificare la stampante.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Vassoio di carta mancante.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Fuori dall'inchiostro.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Inchiostro basso.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Cestino quasi pieno.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Cestino pieno.\";\n" "\"printer-state-reasons.media-empty\" = \"Fuori carta.\";\n" "\"printer-state-reasons.media-jam\" = \"La marmellata di carta.\";\n" "\"printer-state-reasons.media-low\" = \"Sostituisci la carta presto.\";\n" "\"printer-state-reasons.media-needed\" = \"Carta di carico.\";\n" "\"printer-state-reasons.none\" = \"Pronti.\";\n" "\"printer-state-reasons.offline\" = \"Offline.\";\n" "\"printer-state-reasons.other\" = \"Vedi la stampante.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Stampante occupata.\";\n" "\"printer-state-reasons.toner-empty\" = \"Fuori dal toner.\";\n" "\"printer-state-reasons.toner-low\" = \"Toner basso.\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Trattamento\";\n" "\"printer-state.5\" = \"Fermata\";\n" "\"sides\" = \"Stampa a 2 posizioni\";\n" "\"sides.one-sided\" = \"Fuori\";\n" "\"sides.two-sided-long-edge\" = \"Su (portrait)\";\n" "\"sides.two-sided-short-edge\" = \"Su (paesaggio)\";\n" "\"unable to join\" = \"in grado di aderire\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Isole\";\n"; pappl-1.4.9/pappl/strings/ja.strings000066400000000000000000001527071476704353100175010ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a すべてのジョブをキャンセル (cancel)"; " -c COPIES" = " -c コピー"; " -d PRINTER Specify printer." = " -dプリンターを指定する"; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID ジョブ ID (cancel) を指定します。"; " -m DRIVER-NAME Specify driver (add/modify)." = " -m ドライバ名 ドライバーを指定(追加/変更)"; " -n COPIES Specify number of copies (submit)." = " -n COPIES コピーの数を指定します (submit)"; " -o %s=%s (default)" = " -o %s=%s (デフォルト)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o 名前=値 オプションを指定します (add,modify,server,submit.)"; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 から 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 から 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE、LONGITUDE"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZATION"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI ipp: または ipps: プリンタ/サーバーを指定します。"; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v デバイス URI ソケットを指定します: または usb: デバイス (add/modify.)"; " add PRINTER Add a printer." = " add PRINTERを追加 プリンターを追加"; " autoadd Automatically add supported printers." = " autoadd 自動追加 サポートされているプリンターを自動的に追加します。"; " cancel Cancel one or more jobs." = " cancel キャンセル 1 つ以上のジョブをキャンセルします。"; " default Set the default printer." = " default デフォルト デフォルトプリンタを設定します。"; " delete Delete a printer." = " delete プリンターを削除します。"; " devices List devices." = " devices デバイス リストデバイス。"; " drivers List drivers." = " drivers ドライバー リストドライバー。"; " jobs List jobs." = " jobs 求人情報 ジョブリスト"; " modify Modify a printer." = " modify プリンターを変更します。"; " options List printer options." = " options オプション プリンターオプションをリストします。"; " pause Pause printing for a printer." = " pause 一時停止 プリンターのプリント"; " printers List printers." = " printers プリンター プリンターリスト"; " resume Resume printing for a printer." = " resume プリンター用のResumeの印刷を再開します。"; " server Run a server." = " server サーバはサーバを実行します。"; " shutdown Shutdown a running server." = " shutdown 実行中のサーバーをシャットダウンします。"; " status Show server/printer/job status." = " status ステータス サーバ/プリンター/ジョブの状態を表示します。"; " submit Submit a file for printing." = " submit 印刷用のファイルを提出してください。"; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%dインチ/秒"; "%d job" = "%d ジョブ"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%dのdpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g \""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) から %s"; /* Source/Tray Media */ "%s Media" = "%s メディア"; "%s: Bad 'server-port' value." = "%s: 悪いサーバーポート値。"; "%s: Bad job ID." = "%s: 不良ジョブID"; "%s: Bad printer URI '%s'." = "%s: 悪いプリンター URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: 複数のサブコマンドを指定できません。"; "%s: Empty print file received on the standard input." = "%s:標準入力で受け取る空のプリントファイル。"; "%s: Failed to create a system." = "%s: システムの作成に失敗しました。"; "%s: Missing '-d PRINTER'." = "%s: '-d PRINTER を欠く お問い合わせ"; "%s: Missing '-m DRIVER-NAME'." = "%s: '-m DRIVER-NAME を欠く お問い合わせ"; "%s: Missing '-v DEVICE-URI'." = "%s: \"-v DEVICE-URI を欠く お問い合わせ"; "%s: Missing copy count after '-n'." = "%s: -n の後のコピーカウントを欠落させます。"; "%s: Missing device URI after '-v'." = "%s: -v の後のデバイス URI を欠く。"; "%s: Missing driver name after '-m'." = "%s: -m の後の運転者の名前を欠くこと。"; "%s: Missing filename after '--'." = "%s: '--' の後のファイル名を欠く。"; "%s: Missing hostname after '-h'." = "%s: -h の後のホスト名を欠く。"; "%s: Missing job ID after '-j'." = "%s: -j の後のジョブ ID を欠落させます。"; "%s: Missing option(s) after '-o'." = "%s: -o の後にオプションを欠く"; "%s: Missing printer URI after '-u'." = "%s: -u の後のプリンター URI を欠くこと。"; "%s: Missing printer name after '-d'." = "%s: -d の後のプリンター名を逃す。"; "%s: Missing space after '-o'." = "%s: -o の後のスペースを逃すこと。"; "%s: Missing title after '-t'." = "%s: -t の後のタイトルを欠く."; "%s: No default printer available." = "%s: デフォルトプリンタは使用できません。"; "%s: No files to print." = "%s: 印刷するファイルはありません。"; "%s: Server is not running." = "%s: サーバが稼働していません。"; "%s: Sub-command '%s' does not accept files." = "%s: サブコマンド '%s' はファイルを受け入れません。"; "%s: Sub-command 'autoadd' is not supported." = "%s: サブコマンドの自動追加はサポートされていません。"; "%s: Too many files." = "%s: あまりにも多くのファイル。"; "%s: Unable to access '%s': %s" = "%s: '%s': %s にアクセスできない"; "%s: Unable to add printer: %s" = "%s: プリンターを追加できません: %s"; "%s: Unable to cancel job: %s" = "%s: ジョブをキャンセルできません: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: プリンターに接続できない '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: サーバーに接続できません: %s"; "%s: Unable to create temporary file: %s" = "%s: 一時ファイルを作成することができません: %s"; "%s: Unable to delete printer: %s" = "%s: プリンターを削除できません: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: '%s': %s の情報を取得することができません"; "%s: Unable to get information for printer: %s" = "%s: プリンター情報を取得することができません: %s"; "%s: Unable to get printer options: %s" = "%s: プリンタのオプションを取得することができません: %s"; "%s: Unable to modify printer: %s" = "%s: プリンターの変更はできません: %s"; "%s: Unable to pause printer: %s" = "%s: プリンタを一時停止できません: %s"; "%s: Unable to print '%s': %s" = "%s: '%s': %s を印刷できません"; "%s: Unable to resume printer: %s" = "%s: プリンタを再開できません: %s"; "%s: Unable to set default printer: %s" = "%s: デフォルトプリンタを設定することができません: %s"; "%s: Unable to shutdown server: %s" = "%s: サーバをシャットダウンできない: %s"; "%s: Unable to start server: %s" = "%s: サーバーを起動できません: %s"; "%s: Unable to write to temporary file: %s" = "%s: 一時的なファイルに書き込むことができない: %s"; "%s: Unknown option '%s'." = "%s: 不明なオプション '%s'."; "%s: Unknown option '-%c'." = "%s: 不明なオプション '-%c'."; "%s: Unknown sub-command '%s'." = "%s: 未知のサブコマンド '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: サポートされていない URI スキーム '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: 警告 - ユーザ認証情報は URI でサポートされていません。"; ", Borderless" = ", ボーダーレス"; "A printer with that name already exists." = "既に存在している名前のプリンター。"; "Aborted %s" = "Aborted %s"; "Add Printer" = "プリンターを追加"; "Admin Group" = "管理者グループ"; "Afghanistan" = "アフガニスタン"; "Albania" = "アルバニア"; "Algeria" = "アルジェリア"; "American Samoa" = "アメリカ サモア"; "Andorra" = "アンドラ"; "Angola" = "アンゴラ"; "Anguilla" = "アンギラ"; "Antarctica" = "アナトリア"; "Antigua and Barbuda" = "アンティグア・バーブーダ"; "Argentina" = "アルゼンチン"; "Armenia" = "アルメニア"; "Aruba" = "アルバ"; "Australia" = "オーストラリア"; "Austria" = "オーストリア"; "Auto" = "自動車"; "Auto-Detect Driver" = "自動検出の運転者"; "Azerbaijan" = "アゼルバイジャン"; "Bad administration group." = "悪い管理グループ。"; "Bad port number." = "悪いポート番号。"; "Bad print group." = "悪いプリントグループ。"; "Bad printer defaults." = "悪いプリンタのデフォルト。"; "Bahamas" = "バハマ"; "Bahrain" = "バーレーン"; "Bangladesh" = "バングラデシュ"; "Barbados" = "バルバドス"; "Belarus" = "ベラルーシ"; "Belgium" = "ベルギー"; "Belize" = "ベリーズ"; "Benin" = "ログイン"; "Bermuda" = "バーミューダ"; "Bhutan" = "ブータン"; "Bolivia (Plurinational State of)" = "ボリビア(国)"; "Bonaire, Sint Eustatius and Saba" = "ボネール、シント・ユースタチウス、サバ"; "Borderless" = "ボーダーレス"; "Bosnia and Herzegovina" = "ボスニアとヘルツェゴビナ"; "Botswana" = "ボツワナ"; "Bouvet Island" = "ブーヴェ島"; "Brazil" = "ブラジル"; "British Indian Ocean Territory" = "イギリスのインド洋の領事"; "Brunei Darussalam" = "ブルネイ・ダルサラーム"; "Bulgaria" = "ブルガリア"; "Burkina Faso" = "ブルキナファソ"; "Burundi" = "ブルンディ"; "Cabo Verde" = "カボ・ヴェルデ"; "Cambodia" = "カンボジア"; "Cameroon" = "キャメルーン"; "Canada" = "カナダ"; "Cancel All Jobs" = "すべてのジョブをキャンセルする"; "Cancel Job" = "キャンセルジョブ"; "Canceled %s" = "Canceled %s"; "Canceling" = "キャンセル"; "Cayman Islands" = "ケイマン諸島"; "Central African Republic" = "中央アフリカ共和国"; "Certificate created." = "証明書作成。"; "Certificate installed." = "証明書は取付けました。"; "Certificate request created." = "証明書作成リクエスト"; "Chad" = "チャド"; "Change Access Password" = "アクセスパスワードの変更"; "Change Log Level" = "ログレベルを変更する"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Wi-Fiネットワークの変更"; "Changes Saved." = "保存された変更。"; "Changes saved." = "保存された変更。"; "Chile" = "チリ"; "China" = "中国の"; "Christmas Island" = "クリスマス島"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "ココス諸島(ケイリング)"; "Colombia" = "コロンビア"; "Comoros" = "コモロ"; "Completed %s" = "Completed %s"; "Configuration" = "コンテンツ"; "Configure Media" = "メディアの設定"; "Confirm Cancel All" = "キャンセル確認 すべて"; "Confirm Delete Printer" = "プリンターの削除を確認する"; "Congo" = "コンゴ"; "Congo, Democratic Republic of the" = "コンゴ、民主共和国"; "Contact" = "お問い合わせ"; "Cook Islands" = "クック諸島"; "Costa Rica" = "コスタリカ"; "Create Certificate Signing Request" = "証明書署名リクエストを作成する"; "Create New Certificate" = "新しい証明書を作成する"; "Create New TLS Certificate" = "新しい TLS 証明書を作成する"; "Create TLS Certificate Request" = "TLS の作成 証明書の要求"; "Croatia" = "クロアチア"; "Cuba" = "キューバ"; "Curaçao" = "キュラオ"; "Current Password" = "現在のパスワード"; "Custom Size" = "注文のサイズ"; "Cyprus" = "キプロス"; "Czechia" = "チェコ語"; "Côte d'Ivoire" = "Cte d'イボワール"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SDサービス名"; "Debugging" = "デバッギング"; "Default printer set." = "デフォルトプリンターセット。"; "Delete" = "削除"; "Delete Printer" = "プリンターの削除"; "Denmark" = "デンマーク"; "Djibouti" = "ジブチ"; "Domain Name" = "Domain Name"; "Dominica" = "ドミニカ"; "Dominican Republic" = "ドミニカ共和国"; "Download Certificate Request File" = "証明書の要求ファイルのダウンロード"; "Ecuador" = "エクアドル"; "Egypt" = "エジプト"; "El Salvador" = "エルサルバドール"; "Equatorial Guinea" = "エクトリアルギニア"; "Eritrea" = "エリトリア"; "Errors" = "エラー"; "Estonia" = "エストニア"; "Eswatini" = "エスカティーニ"; "Ethiopia" = "エチオピア"; "Falkland Islands (Malvinas)" = "フォークランド諸島 (Malvinas)"; "Faroe Islands" = "フェロー諸島"; "Fatal Errors/Conditions" = "致命的な間違い/条件"; "Fiji" = "フィジー"; "Finland" = "フィンランド"; "France" = "フランス"; "French Guiana" = "フランスのガイアナ"; "French Polynesia" = "フランスのポリネシア"; "French Southern Territories" = "フランスの南地域"; "Gabon" = "ガボン"; "Gambia" = "ガンビア"; "Georgia" = "ジョージア"; "Germany" = "ドイツ"; "Ghana" = "ガーナ"; "Gibraltar" = "ジブラルタル"; "Greece" = "ギリシャ"; "Greenland" = "グリーンランド"; "Grenada" = "グレナダ"; "Group changes saved." = "グループの変更を保存しました。"; "Guadeloupe" = "グアドルーペ"; "Guam" = "グアム"; "Guatemala" = "グアテマラ"; "Guernsey" = "グエルンシー"; "Guinea" = "ギニア"; "Guinea-Bissau" = "ギニア・ビサウ"; "Guyana" = "ガイアナ"; "Haiti" = "ハイチ"; "Heard Island and McDonald Islands" = "ヘアード島とマクドナルド諸島"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "聖なる参照"; "Honduras" = "ホンジュラス"; "Hong Kong" = "香港"; "Hostname" = "ホスト名"; "Human-Readable Location" = "人間可読の場所"; "Hungary" = "ハンガリー"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "アイスランド"; "Identify Printer" = "プリンターの識別"; "India" = "インド"; "Indonesia" = "インドネシア"; "Informational" = "インフォメーション"; "Install TLS Certificate" = "TLSをインストールする 証明書"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "無効なジョブID。"; "Invalid certificate or private key." = "無効な証明書か秘密鍵。"; "Invalid form data." = "無効なフォームデータ。"; "Invalid form submission." = "無効なフォーム送信。"; "Invalid job ID." = "無効なジョブID。"; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "イラン(イスラム共和国)"; "Iraq" = "イラク"; "Ireland" = "アイルランド"; "Isle of Man" = "男の島"; "Israel" = "イスラエル"; "Italy" = "イタリア"; "Jamaica" = "ジャマイカ"; "Japan" = "ジャパンジャパン"; "Jersey" = "ジャージー"; "Job #" = "求人番号"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "求人情報"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "ヨルダン"; "Kazakhstan" = "カザフスタン"; "Kenya" = "ケニア"; "Kiribati" = "キリバティ"; "Korea (Democratic People's Republic of)" = "韓国(デモクラティック・ピープルズ・リパブリック)"; "Korea, Republic of" = "韓国、共和国"; "Kuwait" = "クウェート"; "Kyrgyzstan" = "キルギススタン"; "Landscape" = "ニュース"; "Lao People's Democratic Republic" = "ラオス人民主共和国"; "Latvia" = "ラトビア"; "Lebanon" = "レバノン"; "Lesotho" = "レソト"; "Level" = "レベル"; "Liberia" = "リベリア"; "Libya" = "リビエラ"; "Liechtenstein" = "リヒテンシュタイン"; "Lithuania" = "リトアニア"; "Location" = "アクセス"; "Log Level" = "ログレベル"; "Logging" = "ログイン"; "Logs" = "ログイン"; "Luxembourg" = "ルクセンブルク"; "Macao" = "マカオ"; "Madagascar" = "マダガスカル"; "Malawi" = "マラウイ"; "Malaysia" = "マレーシア"; "Maldives" = "モルディブ"; "Mali" = "マリ"; "Malta" = "マルタ"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "マーシャル諸島"; "Martinique" = "マルティニーク"; "Mauritania" = "モーリタニア"; "Mauritius" = "モーリシャス"; "Mayotte" = "マヨッテ"; "Media" = "メディア"; "Mexico" = "メキシコ"; "Micronesia (Federated States of)" = "マイクロネシア(連邦)"; "Missing action." = "行動を欠く。"; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "プライベートキーを欠く。"; "Moldova, Republic of" = "モルドバ共和国"; "Monaco" = "メニュー"; "Mongolia" = "モンゴル"; "Montenegro" = "モンテネグロ"; "Montserrat" = "モンセラット"; "Morocco" = "モロッコ"; "Mozambique" = "モザンビーク"; "Myanmar" = "ミャンマー"; "Name" = "お名前 (必須)"; "Namibia" = "ナミビア"; "Nauru" = "ナウル"; "Nepal" = "ネパール"; "Netherlands" = "オランダ"; "Network" = "ネットワーク"; "Network Printer" = "ネットワークプリンター"; "Networking" = "ネットワーク"; "New Caledonia" = "ニューカレドニア"; "New Zealand" = "ニュージーランド"; "Nicaragua" = "ニカラグア"; "Niger" = "ニジェール"; "Nigeria" = "ナイジェリア"; "Niue" = "ログイン"; "No default printer set." = "デフォルトのプリンタセットはありません。"; "No jobs in history." = "履歴のジョブはありません。"; "Norfolk Island" = "ノーフォーク島"; "North Macedonia" = "北マケドニア"; "Northern Mariana Islands" = "北マリアナ諸島"; "Norway" = "ノルウェー"; "Not set" = "セットなし"; "Off" = "Off"; "Offset" = "オフセット"; "Oman" = "オマーン"; "Options:" = "オプション:"; "Organization" = "社会招聘"; "Organization Name" = "組織名称"; "Other Settings" = "その他の設定"; "Pakistan" = "パキスタン"; "Palau" = "パラオ"; "Palestine, State of" = "パレスチナ、州"; "Panama" = "パナマ"; "Papua New Guinea" = "パプアニューギニア"; "Paraguay" = "パラグアイ"; "Password" = "パスワード"; "Password changed." = "パスワードが変更されました。"; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "パスワードは、少なくとも8文字以上で、少なくとも1つの大文字、小文字、および1つの数字を含む必要があります。"; "Passwords do not match." = "パスワードは一致しません。"; "Pause Printing" = "ペーパー印刷"; "Peru" = "ペルー"; "Philippines" = "フィリピン"; "Pitcairn" = "ピッツケアン"; "Please enter a hostname or IP address for the printer." = "プリンターのホスト名またはIPアドレスを入力してください。"; "Please enter a printer name." = "プリンター名を入力してください。"; "Please select a device." = "デバイスを選択してください。"; "Please select a driver." = "ドライバーをお選びください。"; "Please select a valid log level." = "有効なログレベルを選択してください。"; "Poland" = "ポーランド"; "Portrait" = "ポートレート"; "Portugal" = "ポルトガル"; "Primary DNS" = "Primary DNS"; "Print Group" = "プリントグループ"; "Print Test Page" = "プリントテストページ"; "Print job options:" = "ジョブオプションを印刷:"; "Printer identified." = "識別されるプリンター。"; "Printer is currently active." = "プリンターは現在有効です。"; "Printer names must start with a letter or underscore and cannot contain special characters." = "プリンター名は、文字またはアンダースコアで始まり、特別な文字を含むことはできません。"; "Printer options:" = "プリンター選択:"; "Printer paused." = "プリンターはpaused。"; "Printer pausing." = "プリンター ペーパー。"; "Printer resuming." = "プリンター再開。"; "Printers" = "プリンター"; "Printing Defaults" = "印刷のデフォルト"; "Puerto Rico" = "プエルトリコ"; "Qatar" = "カタール"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "再印刷ジョブ"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "再開の印刷"; "Reverse Landscape" = "逆の風景"; "Reverse Portrait" = "逆の肖像"; "Romania" = "ルーマニア"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "%s %s以来のランニング、%s。"; "Russian Federation" = "ロシア連邦"; "Rwanda" = "ルワンダ"; "Réunion" = "ログイン"; "Saint Barthélemy" = "サン・バルトレミー"; "Saint Helena, Ascension and Tristan da Cunha" = "セントヘレナ、アセンション、トリスタン・ダ・クンハ"; "Saint Kitts and Nevis" = "セントキッツとネイビス"; "Saint Lucia" = "セントルシア"; "Saint Martin (French part)" = "聖マーティン(フランス部分)"; "Saint Pierre and Miquelon" = "サンピエールとミクロン"; "Saint Vincent and the Grenadines" = "セントビンセントとグレナディーン諸島"; "Samoa" = "サモア"; "San Marino" = "サンマリノ"; "Sao Tome and Principe" = "トームとプリンシペ"; "Saudi Arabia" = "サウジアラビア"; "Save Changes" = "変更を保存"; "Secondary DNS" = "Secondary DNS"; "Security" = "セキュリティ"; "Select Driver" = "ドライバーの選択"; "Senegal" = "セネガル"; "Serbia" = "セルビア"; "Server is not running." = "サーバが稼働していません。"; "Set Access Password" = "アクセスパスワードを設定する"; "Set as Default" = "デフォルトで設定"; "Seychelles" = "セイシェル"; "Sierra Leone" = "シエラレオネ"; "Singapore" = "シンガポール"; "Sint Maarten (Dutch part)" = "シント・マールテン(オランダ)"; "Slovakia" = "スロバキア"; "Slovenia" = "スワッピング"; "Solomon Islands" = "ソロモン諸島"; "Somalia" = "ソマリア"; "South Africa" = "南アフリカ"; "South Georgia and the South Sandwich Islands" = "南ジョージアと南サンドイッチ諸島"; "South Sudan" = "南スーダン"; "Spain" = "スペイン"; "Sri Lanka" = "スリランカ"; "Started %s" = "Started %s"; "Status" = "ステータス"; "Sub-commands:" = "サブコマンド:"; "Sudan" = "スーダン"; "Supplies" = "アクセサリー"; "Suriname" = "スリナム"; "Svalbard and Jan Mayen" = "Svalbardと1月マレン"; "Sweden" = "スウェーデン"; "Switzerland" = "スイス"; "Syrian Arab Republic" = "シリア アラブ共和国"; "Taiwan, Province of China" = "台湾、中国省"; "Tajikistan" = "タジキスタン"; "Tanzania, United Republic of" = "タンザニア, United Kingdom"; "Test page printed." = "印刷されたテストページ。"; "Thailand" = "タイ"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "このフォームは、認証機関(CA)に送信できる証明書署名(CSR)を作成して、信頼できるTLS証明書を入手します。 秘密鍵は、CAから取得する証明書と使用するために別途保存されます。"; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "このフォームは、安全な印刷のために新しい自己署名のTLS証明書を作成します。 自己署名証明書は、Webブラウザによって自動的に信頼されません。"; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "このフォームは、認証機関(CA)から入手した信頼できるTLS証明書をインストールします。 インストール後すぐに利用します。"; "Timor-Leste" = "ティモール・レステ"; "Togo" = "トーゴ"; "Tokelau" = "トケラウ"; "Tonga" = "トンガ"; "Trinidad and Tobago" = "トリニダードとトバゴ"; "Tunisia" = "チュニジア"; "Turkey" = "トルコ"; "Turkmenistan" = "トルクメニスタン"; "Turks and Caicos Islands" = "タークス・カイコス諸島"; "Tuvalu" = "ツバル"; "Uganda" = "ウガンダ"; "Ukraine" = "ウクライナ"; "Unable to access test print file." = "テストプリントファイルにアクセスできません。"; "Unable to copy print job." = "印刷ジョブをコピーできません。"; "Unable to create certificate request." = "証明書のリクエストを作成することができません。"; "Unable to create certificate." = "証明書を作成することができません。"; "Unable to create test print job." = "テストプリントジョブを作成することができません。"; "Unable to identify printer." = "プリンターを識別できません。"; "Unable to lookup address." = "アドレスを調べることができません。"; "Unable to use that driver." = "そのドライバを使用できません。"; "United Arab Emirates" = "アラブ首長国連邦"; "United Kingdom" = "イギリス"; "United Kingdom of Great Britain and Northern Ireland" = "イギリス・北アイルランド王国"; "United States Minor Outlying Islands" = "アメリカ合衆国 Minor Outlying Islands"; "United States of America" = "アメリカ合衆国"; "Unknown" = "未知の"; "Unknown action." = "未知のアクション。"; "Unknown form action." = "未知のフォームアクション。"; "Unknown form request." = "不明なフォームリクエスト"; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "ウルグアイ"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "使用法: %s サブコマンド [操作] [ユーザー名]\n"; "Use My Position" = "マイポジションを使用する"; "Users" = "ユーザ名"; "Uzbekistan" = "ウズベキスタン"; "Vanuatu" = "バヌアツ"; "Venezuela (Bolivarian Republic of)" = "ベネズエラ(ボリビア共和国)"; "Version %s" = "バージョン %s"; "Viet Nam" = "ベトナム"; "View Logs" = "ログを表示"; "Virgin Islands (British)" = "バージン諸島(イギリス)"; "Virgin Islands (U.S.)" = "バージン諸島(米国)"; "Wallis and Futuna" = "ウォリスとフツナ"; "Warning" = "インフォメーション"; "Western Sahara" = "西サハラ"; "Wi-Fi Configuration" = "Wi-Fiの設定"; "Wi-Fi Network" = "Wi-Fiネットワーク"; "Width" = "アクセス"; "Wrong old password." = "古いパスワードが間違っています。"; "Yemen" = "イエメン"; "Zambia" = "ザンビア"; "Zimbabwe" = "ジンバブエ"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "コピーの数"; "default printer" = "デフォルトプリンタ"; "finishings" = "フィニッシャー"; "finishings.10" = "フォールド"; "finishings.100" = "Z の折目"; "finishings.101" = "工学Zの折目"; "finishings.11" = "カット"; "finishings.12" = "ベール"; "finishings.13" = "ブックレットメーカー"; "finishings.15" = "コーティング"; "finishings.16" = "ラミネート"; "finishings.20" = "スタプルトップ左"; "finishings.21" = "ステープルボトム左"; "finishings.22" = "右上のステープルトップ"; "finishings.23" = "右上のステープル"; "finishings.24" = "エッジステッチ左"; "finishings.25" = "エッジステッチトップ"; "finishings.26" = "エッジステッチ右"; "finishings.27" = "エッジステッチボトム"; "finishings.28" = "左に2つのステープル"; "finishings.29" = "2 トップにステープル"; "finishings.3" = "なし"; "finishings.30" = "2 右にステープル"; "finishings.31" = "底に2つのステープル"; "finishings.32" = "3 左にステープル"; "finishings.33" = "トップ3のステープル"; "finishings.34" = "3 右上のステープル"; "finishings.35" = "底の3つのステープル"; "finishings.4" = "スタプル"; "finishings.5" = "パンチング"; "finishings.50" = "左ビン"; "finishings.51" = "ビントップ"; "finishings.52" = "ビンド右"; "finishings.53" = "ビン底"; "finishings.6" = "カバー"; "finishings.60" = "すべてのページを閉じる"; "finishings.61" = "すべての文書の後にカット"; "finishings.62" = "すべてのセットの後で切れて下さい"; "finishings.63" = "ジョブ後のカット"; "finishings.7" = "ログイン"; "finishings.70" = "パンチトップ左"; "finishings.71" = "パンチボトム左"; "finishings.72" = "パンチトップ右"; "finishings.73" = "右下のパンチ"; "finishings.74" = "2穴パンチ左"; "finishings.75" = "2穴パンチトップ"; "finishings.76" = "2穴パンチ右"; "finishings.77" = "2穴パンチボトム"; "finishings.78" = "3穴パンチ左"; "finishings.79" = "3穴パンチトップ"; "finishings.8" = "サドルステッチ"; "finishings.80" = "3穴パンチ右"; "finishings.81" = "3穴パンチボトム"; "finishings.82" = "4穴パンチ左"; "finishings.83" = "4穴パンチトップ"; "finishings.84" = "4穴パンチ右"; "finishings.85" = "4穴パンチボトム"; "finishings.86" = "多穴パンチ左"; "finishings.87" = "マルチホールパンチトップ"; "finishings.88" = "多穴パンチ右"; "finishings.89" = "多穴パンチ底"; "finishings.9" = "エッジステッチ"; "finishings.90" = "アコーディオンの折目"; "finishings.91" = "二重ゲートの折目"; "finishings.92" = "ゲートの折目"; "finishings.93" = "ハーフフォールド"; "finishings.94" = "ハーフZフォールド"; "finishings.95" = "左ゲートの折目"; "finishings.96" = "手紙の折目"; "finishings.97" = "平行折目"; "finishings.98" = "ポスター折り目"; "finishings.99" = "右ゲートの折目"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "停止。"; "job-state-reasons.compression-error" = "圧縮エラー。"; "job-state-reasons.document-format-error" = "ドキュメントフォーマットエラー。"; "job-state-reasons.document-password-error" = "ドキュメントパスワードエラー。"; "job-state-reasons.document-permission-error" = "ドキュメント許可エラー。"; "job-state-reasons.document-unprintable-error" = "印刷不能なエラーを文書化します。"; "job-state-reasons.errors-detected" = "検出されたエラー。"; "job-state-reasons.job-canceled-at-device" = "プリンターでのキャンセル"; "job-state-reasons.job-canceled-by-user" = "ユーザーによるキャンセル"; "job-state-reasons.job-completed-successfully" = "印刷される。"; "job-state-reasons.job-completed-with-errors" = "エラーで印刷。"; "job-state-reasons.job-completed-with-warnings" = "警告で印刷。"; "job-state-reasons.job-data-insufficient" = "十分なデータ。"; "job-state-reasons.job-fetchable" = "取得可能。"; "job-state-reasons.job-incoming" = "お問い合わせ"; "job-state-reasons.job-printing" = "印刷。"; "job-state-reasons.job-queued" = "印刷する準備。"; "job-state-reasons.job-spooling" = "スプール。"; "job-state-reasons.none" = "終わり。"; "job-state-reasons.printer-stopped" = "プリンターオフライン。"; "job-state-reasons.printer-stopped-partly" = "プリンター部分的に停止。"; "job-state-reasons.processing-to-stop-point" = "停止。"; "job-state-reasons.queued-in-device" = "レディ。"; "job-state-reasons.warnings-detected" = "検出された警告。"; "job-state.3" = "ペンディング"; "job-state.4" = "開催概要"; "job-state.5" = "プロセス"; "job-state.6" = "停止"; "job-state.7" = "キャンセル"; "job-state.8" = "アボラ"; "job-state.9" = "完了しました"; "joining" = "エントリー"; "media" = "メディア"; "media-col" = "メディア"; "media-size" = "メディア サイズ"; "media-size-name" = "メディア サイズ"; "media-source" = "入力トレイ"; "media-source.alternate" = "オルタナティブ"; "media-source.alternate-roll" = "代替ロール"; "media-source.auto" = "オートマチック"; "media-source.bottom" = "ボトム"; "media-source.by-pass-tray" = "多目的トレイ"; "media-source.center" = "センター"; "media-source.disc" = "ディスク"; "media-source.envelope" = "エンベロープ"; "media-source.hagaki" = "ハガキ"; "media-source.large-capacity" = "大容量"; "media-source.left" = "ふりがな"; "media-source.main" = "メインページ"; "media-source.main-roll" = "主要なロール"; "media-source.manual" = "マニュアル"; "media-source.middle" = "ミドル"; "media-source.photo" = "プロフィール"; "media-source.rear" = "リア"; "media-source.right" = "アクセス"; "media-source.roll-1" = "ロール 1"; "media-source.roll-10" = "ロール 10"; "media-source.roll-2" = "ロール2"; "media-source.roll-3" = "ロール3"; "media-source.roll-4" = "ロール4"; "media-source.roll-5" = "ロール5"; "media-source.roll-6" = "ロール 6"; "media-source.roll-7" = "ロール 7"; "media-source.roll-8" = "ロール8"; "media-source.roll-9" = "ロール9"; "media-source.side" = "サイド"; "media-source.top" = "トップページ"; "media-source.tray-1" = "トレイ 1"; "media-source.tray-10" = "トレイ 10"; "media-source.tray-11" = "トレイ 11"; "media-source.tray-12" = "トレイ 12"; "media-source.tray-13" = "トレイ 13"; "media-source.tray-14" = "トレイ 14"; "media-source.tray-15" = "トレイ 15"; "media-source.tray-16" = "トレイ 16"; "media-source.tray-17" = "トレイ 17"; "media-source.tray-18" = "トレイ 18"; "media-source.tray-19" = "トレイ 19"; "media-source.tray-2" = "トレイ2"; "media-source.tray-20" = "トレイ 20"; "media-source.tray-3" = "トレイ 3"; "media-source.tray-4" = "トレイ 4"; "media-source.tray-5" = "トレイ 5"; "media-source.tray-6" = "トレイ 6"; "media-source.tray-7" = "トレイ 7"; "media-source.tray-8" = "トレイ 8"; "media-source.tray-9" = "トレイ 9"; "media-tracking" = "メディアトラッキング"; "media-tracking.continuous" = "連続的な"; "media-tracking.gap" = "ギャップ"; "media-tracking.mark" = "ログイン"; "media-tracking.web" = "サイトマップ"; "media-type" = "メディアタイプ"; "media-type.aluminum" = "アルミ"; "media-type.auto" = "オートマチック"; "media-type.back-print-film" = "バックプリントフィルム"; "media-type.cardboard" = "段ボール"; "media-type.cardstock" = "カードストック"; "media-type.cd" = "アルバム"; "media-type.continuous" = "連続的な"; "media-type.continuous-long" = "連続ロング"; "media-type.continuous-short" = "連続ショート"; "media-type.corrugated-board" = "波形板"; "media-type.disc" = "光学ディスク"; "media-type.disc-glossy" = "光沢のある光学ディスク"; "media-type.disc-high-gloss" = "高い光沢の光学ディスク"; "media-type.disc-matte" = "マット光学ディスク"; "media-type.disc-satin" = "サテン光学ディスク"; "media-type.disc-semi-gloss" = "セミグロス光学ディスク"; "media-type.double-wall" = "二重壁"; "media-type.dry-film" = "ドライフィルム"; "media-type.dvd" = "DVD机"; "media-type.embossing-foil" = "浮彫りになるホイル"; "media-type.end-board" = "エンドボード"; "media-type.envelope" = "エンベロープ"; "media-type.envelope-archival" = "アーカイバル封筒"; "media-type.envelope-bond" = "ボンド封筒"; "media-type.envelope-coated" = "上塗を施してある封筒"; "media-type.envelope-cotton" = "コットン封筒"; "media-type.envelope-fine" = "良い封筒"; "media-type.envelope-heavyweight" = "ヘビー級封筒"; "media-type.envelope-inkjet" = "インクジェット封筒"; "media-type.envelope-lightweight" = "軽量封筒"; "media-type.envelope-plain" = "平野封筒"; "media-type.envelope-preprinted" = "事前印刷された封筒"; "media-type.envelope-window" = "窓の封筒"; "media-type.fabric" = "ファブリック"; "media-type.fabric-archival" = "アーカイバルファブリック"; "media-type.fabric-glossy" = "光沢のある生地"; "media-type.fabric-high-gloss" = "高い光沢の生地"; "media-type.fabric-matte" = "マットの生地"; "media-type.fabric-semi-gloss" = "半光沢の生地"; "media-type.fabric-waterproof" = "防水生地"; "media-type.film" = "フィルム"; "media-type.flexo-base" = "フレキソベース"; "media-type.flexo-photo-polymer" = "フレキソフォトポリマー"; "media-type.flute" = "フルート"; "media-type.foil" = "ホイル"; "media-type.full-cut-tabs" = "フルカットタブ"; "media-type.glass" = "ガラス"; "media-type.glass-colored" = "ガラス色"; "media-type.glass-opaque" = "ガラスオパク"; "media-type.glass-surfaced" = "ガラス面"; "media-type.glass-textured" = "ガラステクスチャード"; "media-type.gravure-cylinder" = "グラビアシリンダー"; "media-type.image-setter-paper" = "イメージのセッターのペーパー"; "media-type.imaging-cylinder" = "イメージングシリンダー"; "media-type.labels" = "ラベル"; "media-type.labels-colored" = "着色されたラベル"; "media-type.labels-glossy" = "光沢のあるラベル"; "media-type.labels-high-gloss" = "高い光沢のラベル"; "media-type.labels-inkjet" = "インクジェットラベル"; "media-type.labels-matte" = "マットラベル"; "media-type.labels-permanent" = "永久的なラベル"; "media-type.labels-satin" = "サテンラベル"; "media-type.labels-security" = "セキュリティラベル"; "media-type.labels-semi-gloss" = "半光沢のラベル"; "media-type.laminating-foil" = "ラミネート箔"; "media-type.letterhead" = "レターヘッド"; "media-type.metal" = "ログイン"; "media-type.metal-glossy" = "金属の光沢のある"; "media-type.metal-high-gloss" = "金属の高い光沢"; "media-type.metal-matte" = "メタルマット"; "media-type.metal-satin" = "金属サテン"; "media-type.metal-semi-gloss" = "金属の半光沢"; "media-type.mounting-tape" = "土台テープ"; "media-type.multi-layer" = "多層層層"; "media-type.multi-part-form" = "多部分の形態"; "media-type.other" = "その他"; "media-type.paper" = "ペーパー"; "media-type.photographic" = "フォトペーパー"; "media-type.photographic-archival" = "撮影アーカイブ"; "media-type.photographic-film" = "フォトフィルム"; "media-type.photographic-glossy" = "光沢のある写真のペーパー"; "media-type.photographic-high-gloss" = "高い光沢の写真のペーパー"; "media-type.photographic-matte" = "マットフォトペーパー"; "media-type.photographic-satin" = "サテンフォトペーパー"; "media-type.photographic-semi-gloss" = "半光沢の写真のペーパー"; "media-type.plastic" = "プラスチック"; "media-type.plastic-archival" = "プラスチック アーカイブ"; "media-type.plastic-colored" = "プラスチック着色される"; "media-type.plastic-glossy" = "プラスチック光沢のある"; "media-type.plastic-high-gloss" = "プラスチック高い光沢"; "media-type.plastic-matte" = "プラスチックマット"; "media-type.plastic-satin" = "プラスチックサテン"; "media-type.plastic-semi-gloss" = "プラスチック半光沢"; "media-type.plate" = "プレート"; "media-type.polyester" = "ポリエステル"; "media-type.pre-cut-tabs" = "プリカットタブ"; "media-type.roll" = "ロール"; "media-type.screen" = "スクリーン"; "media-type.screen-paged" = "サイトマップ"; "media-type.self-adhesive" = "自己接着"; "media-type.self-adhesive-film" = "自己接着フィルム"; "media-type.shrink-foil" = "収縮ホイル"; "media-type.single-face" = "シングル"; "media-type.single-wall" = "単一の壁"; "media-type.sleeve" = "ジャケット"; "media-type.stationery" = "ステーショナリー"; "media-type.stationery-archival" = "文房具のアーカイブ"; "media-type.stationery-coated" = "塗被紙"; "media-type.stationery-cotton" = "文具の綿"; "media-type.stationery-fine" = "ベルラム紙"; "media-type.stationery-heavyweight" = "ヘビー級紙"; "media-type.stationery-heavyweight-coated" = "ステーショナリーヘビー級コーティング"; "media-type.stationery-inkjet" = "文具インクジェットペーパー"; "media-type.stationery-letterhead" = "レターヘッド"; "media-type.stationery-lightweight" = "軽量紙"; "media-type.stationery-preprinted" = "印刷されたペーパー"; "media-type.stationery-prepunched" = "パンチングペーパー"; "media-type.tab-stock" = "タブストック"; "media-type.tractor" = "トラクター"; "media-type.transfer" = "アクセス"; "media-type.transparency" = "透明性"; "media-type.triple-wall" = "トリプルウォール"; "media-type.wet-film" = "ウェットフィルム"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4または米国手紙"; "media.iso_2a0_1189x1682mm" = "2a0の"; "media.iso_a0_841x1189mm" = "ツイート"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10の特長"; "media.iso_a1_594x841mm" = "A1の"; "media.iso_a1x3_841x1783mm" = "A1x3の特長"; "media.iso_a1x4_841x2378mm" = "A1x4の特長"; "media.iso_a2_420x594mm" = "A2について"; "media.iso_a2x3_594x1261mm" = "A2x3の特長"; "media.iso_a2x4_594x1682mm" = "A2x4の特長"; "media.iso_a2x5_594x2102mm" = "A2x5の特長"; "media.iso_a3-extra_322x445mm" = "A3(エクストラ)"; "media.iso_a3_297x420mm" = "A3の特長"; "media.iso_a3x3_420x891mm" = "A3x3の特長"; "media.iso_a3x4_420x1189mm" = "A3x4の特長"; "media.iso_a3x5_420x1486mm" = "A3x5の特長"; "media.iso_a3x6_420x1783mm" = "A3x6の特長"; "media.iso_a3x7_420x2080mm" = "A3x7の特長"; "media.iso_a4-extra_235.5x322.3mm" = "A4(エクストラ)"; "media.iso_a4-tab_225x297mm" = "A4(タブ)"; "media.iso_a4_210x297mm" = "A4の特長"; "media.iso_a4x3_297x630mm" = "A4x3の特長"; "media.iso_a4x4_297x841mm" = "A4x4の特長"; "media.iso_a4x5_297x1051mm" = "A4x5の特長"; "media.iso_a4x6_297x1261mm" = "A4x6の特長"; "media.iso_a4x7_297x1471mm" = "A4x7の特長"; "media.iso_a4x8_297x1682mm" = "A4x8の特長"; "media.iso_a4x9_297x1892mm" = "A4x9の特長"; "media.iso_a5-extra_174x235mm" = "A5(エクストラ)"; "media.iso_a5_148x210mm" = "A5の特長"; "media.iso_a6_105x148mm" = "A6の特長"; "media.iso_a7_74x105mm" = "A7の"; "media.iso_a8_52x74mm" = "A8の特長"; "media.iso_a9_37x52mm" = "A9の特長"; "media.iso_b0_1000x1414mm" = "ツイート"; "media.iso_b10_31x44mm" = "B10の特長"; "media.iso_b1_707x1000mm" = "B1の"; "media.iso_b2_500x707mm" = "B2の"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4の特長"; "media.iso_b5-extra_201x276mm" = "B5(エクストラ)"; "media.iso_b5_176x250mm" = "B5封筒"; "media.iso_b6_125x176mm" = "B6の特長"; "media.iso_b6c4_125x324mm" = "B6/C4エンベロープ"; "media.iso_b7_88x125mm" = "B7の"; "media.iso_b8_62x88mm" = "B8の特長"; "media.iso_b9_44x62mm" = "B9の特長"; "media.iso_c0_917x1297mm" = "C0封筒"; "media.iso_c10_28x40mm" = "C10封筒"; "media.iso_c1_648x917mm" = "C1封筒"; "media.iso_c2_458x648mm" = "C2封筒"; "media.iso_c3_324x458mm" = "C3封筒"; "media.iso_c4_229x324mm" = "C4封筒"; "media.iso_c5_162x229mm" = "C5封筒"; "media.iso_c6_114x162mm" = "C6封筒"; "media.iso_c6c5_114x229mm" = "C6/C5封筒"; "media.iso_c7_81x114mm" = "C7封筒"; "media.iso_c7c6_81x162mm" = "C7/C6 封筒"; "media.iso_c8_57x81mm" = "C8封筒"; "media.iso_c9_40x57mm" = "C9封筒"; "media.iso_dl_110x220mm" = "DL封筒"; "media.iso_ra0_860x1220mm" = "ISOのRA0"; "media.iso_ra1_610x860mm" = "ISOのRA1"; "media.iso_ra2_430x610mm" = "ISOのRA2"; "media.iso_ra3_305x430mm" = "ISOのRA3"; "media.iso_ra4_215x305mm" = "ISOのRA4"; "media.iso_sra0_900x1280mm" = "ISOのSRA0"; "media.iso_sra1_640x900mm" = "ISOのSRA1"; "media.iso_sra2_450x640mm" = "ISOのSRA2"; "media.iso_sra3_320x450mm" = "ISOのSRA3"; "media.iso_sra4_225x320mm" = "ISOのSRA4"; "media.jis_b0_1030x1456mm" = "三菱 B0"; "media.jis_b10_32x45mm" = "JIS B10の特長"; "media.jis_b1_728x1030mm" = "JIS B1の特長"; "media.jis_b2_515x728mm" = "JIS B2の特長"; "media.jis_b3_364x515mm" = "JIS B3の特長"; "media.jis_b4_257x364mm" = "JIS B4の特長"; "media.jis_b5_182x257mm" = "JIS B5の特長"; "media.jis_b6_128x182mm" = "JIS B6の特長"; "media.jis_b7_91x128mm" = "JIS B7の特長"; "media.jis_b8_64x91mm" = "JIS B8の特長"; "media.jis_b9_45x64mm" = "JIS B9の特長"; "media.jis_exec_216x330mm" = "ステンレス エグゼクティブ"; "media.jpn_chou2_111.1x146mm" = "エンベロープカウ 2"; "media.jpn_chou3_120x235mm" = "エンベロープカウ 3"; "media.jpn_chou40_90x225mm" = "エンベロープカウ 40"; "media.jpn_chou4_90x205mm" = "エンベロープカウ 4"; "media.jpn_hagaki_100x148mm" = "ハガキ"; "media.jpn_kahu_240x322.1mm" = "エンベロープカウ"; "media.jpn_kaku2_240x332mm" = "封筒 カウ 2"; "media.jpn_oufuku_148x200mm" = "Oufuku 返信 ポストカード"; "media.jpn_you4_105x235mm" = "エンベロープ あなた 4"; "media.na_a2_4.375x5.75in" = "封筒 A2"; "media.na_c5_6.5x9.5in" = "封筒 C5"; "media.na_executive_7.25x10.5in" = "エグゼクティブ"; "media.na_fanfold-eur_8.5x12in" = "ヨーロッパのファンフォールド"; "media.na_fanfold-us_11x14.875in" = "アメリカのファンフォールド"; "media.na_foolscap_8.5x13in" = "フットキャップ"; "media.na_invoice_5.5x8.5in" = "ニュース"; "media.na_legal-extra_9.5x15in" = "米国の法律(エクストラ)"; "media.na_legal_8.5x14in" = "米国法"; "media.na_letter-extra_9.5x12in" = "米国の手紙(元)"; "media.na_letter-plus_8.5x12.69in" = "米国の手紙(プラス)"; "media.na_letter_8.5x11in" = "米国の手紙"; "media.na_monarch_3.875x7.5in" = "Envelope モンアーチ"; "media.na_number-10_4.125x9.5in" = "封筒 #10"; "media.na_number-11_4.5x10.375in" = "封筒 #11"; "media.na_number-12_4.75x11in" = "封筒 #12"; "media.na_number-14_5x11.5in" = "封筒 #14"; "media.na_number-9_3.875x8.875in" = "封筒 #9"; "media.na_personal_3.625x6.5in" = "封筒 個人"; "media.na_quarto_8.5x10.83in" = "クアルト"; "media.om_folio-sp_215x315mm" = "フォリオ"; "media.om_folio_210x330mm" = "フォリオ(スペシャル)"; "media.om_invite_220x220mm" = "封筒の招待状"; "media.om_italian_110x230mm" = "イタリア"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200×300"; "media.om_medium-photo_130x180mm" = "130 x 180mmの"; "media.om_pa-kai_267x389mm" = "267×389m m 点"; "media.om_postfix_114x229mm" = "封筒 Postfix"; "media.prc_10_324x458mm" = "封筒の中国 #10"; "media.prc_16k_146x215mm" = "中国語 16k"; "media.prc_1_102x165mm" = "封筒 中国人 #1"; "media.prc_2_102x176mm" = "封筒 中国人 #2"; "media.prc_32k_97x151mm" = "中国語 32k"; "media.prc_3_125x176mm" = "封筒中国 #3"; "media.prc_4_110x208mm" = "封筒中国 #4"; "media.prc_5_110x220mm" = "封筒中国 #5"; "media.prc_6_120x320mm" = "封筒中国 #6"; "media.prc_7_160x230mm" = "封筒中国 #7"; "media.prc_8_120x309mm" = "封筒の中国 #8"; "media.roc_16k_7.75x10.75in" = "ROC 16Kの特長"; "media.roc_8k_10.75x15.5in" = "ロッコ 8Kの"; "not configured" = "設定されていない"; "not visible" = "見えない"; "off" = "オフ"; "on" = "お問い合わせ"; "orientation-requested" = "オリエンテーション"; "orientation-requested.3" = "ポートレート"; "orientation-requested.4" = "ニュース"; "orientation-requested.5" = "逆の風景"; "orientation-requested.6" = "逆の肖像画"; "orientation-requested.7" = "なし"; "output-bin" = "出力トレイ"; "output-bin.auto" = "オートマチック"; "output-bin.bottom" = "ボトム"; "output-bin.center" = "センター"; "output-bin.face-down" = "フェイスダウン"; "output-bin.face-up" = "フェイスアップ"; "output-bin.large-capacity" = "大容量"; "output-bin.left" = "ふりがな"; "output-bin.mailbox-1" = "メールボックス 1"; "output-bin.mailbox-10" = "メールボックス10"; "output-bin.mailbox-2" = "メールボックス2"; "output-bin.mailbox-3" = "メールボックス3"; "output-bin.mailbox-4" = "メールボックス 4"; "output-bin.mailbox-5" = "メールボックス 5"; "output-bin.mailbox-6" = "メールボックス 6"; "output-bin.mailbox-7" = "メールボックス 7"; "output-bin.mailbox-8" = "メールボックス 8"; "output-bin.mailbox-9" = "メールボックス 9"; "output-bin.middle" = "ミドル"; "output-bin.my-mailbox" = "メールボックス"; "output-bin.rear" = "リア"; "output-bin.right" = "アクセス"; "output-bin.side" = "サイド"; "output-bin.stacker-1" = "スタッカー 1"; "output-bin.stacker-10" = "スタッカー 10"; "output-bin.stacker-2" = "スタッカー 2"; "output-bin.stacker-3" = "スタッカー 3"; "output-bin.stacker-4" = "スタッカー 4"; "output-bin.stacker-5" = "スタッカー 5"; "output-bin.stacker-6" = "スタッカー 6"; "output-bin.stacker-7" = "スタッカー 7"; "output-bin.stacker-8" = "スタッカー 8"; "output-bin.stacker-9" = "スタッカー 9"; "output-bin.top" = "トップページ"; "output-bin.tray-1" = "トレイ 1"; "output-bin.tray-10" = "トレイ 10"; "output-bin.tray-2" = "トレイ2"; "output-bin.tray-3" = "トレイ 3"; "output-bin.tray-4" = "トレイ 4"; "output-bin.tray-5" = "トレイ 5"; "output-bin.tray-6" = "トレイ 6"; "output-bin.tray-7" = "トレイ 7"; "output-bin.tray-8" = "トレイ 8"; "output-bin.tray-9" = "トレイ 9"; "print-color-mode" = "プリントモード"; "print-color-mode.auto" = "オートマチック"; "print-color-mode.auto-monochrome" = "自動モノクロ"; "print-color-mode.bi-level" = "テキスト"; "print-color-mode.color" = "カラー"; "print-color-mode.highlight" = "ハイライト"; "print-color-mode.monochrome" = "モノクロ"; "print-color-mode.process-bi-level" = "プロセステキスト"; "print-color-mode.process-monochrome" = "プロセスモノクロ"; "print-content-optimize" = "最適化"; "print-content-optimize.auto" = "オートマチック"; "print-content-optimize.graphic" = "グラフィック"; "print-content-optimize.photo" = "プロフィール"; "print-content-optimize.text" = "テキスト"; "print-content-optimize.text-and-graphic" = "テキストとグラフィック"; "print-darkness" = "プリントダークネス"; "print-quality" = "印刷物の質"; "print-quality.3" = "ドラフト"; "print-quality.4" = "ノーマル"; "print-quality.5" = "ベストベスト"; "print-scaling" = "スケーリング"; "print-scaling.auto" = "オートマチック"; "print-scaling.auto-fit" = "自動フィット"; "print-scaling.fill" = "お問い合わせ"; "print-scaling.fit" = "フィット"; "print-scaling.none" = "なし"; "print-speed" = "プリント速度"; "printer-resolution" = "ソリューション"; "printer-state-reasons.cover-open" = "カバーは開きます。"; "printer-state-reasons.door-open" = "ドアを開けて下さい。"; "printer-state-reasons.identify-printer-requested" = "プリンターを識別します。"; "printer-state-reasons.input-tray-missing" = "ペーパー皿の欠落。"; "printer-state-reasons.marker-supply-empty" = "インクから。"; "printer-state-reasons.marker-supply-low" = "低いインク。"; "printer-state-reasons.marker-waste-almost-full" = "廃棄物の大箱はほぼ満たします。"; "printer-state-reasons.marker-waste-full" = "廃棄物の箱の完全。"; "printer-state-reasons.media-empty" = "ペーパーから。"; "printer-state-reasons.media-jam" = "ペーパー ジャム。"; "printer-state-reasons.media-low" = "ペーパーをすぐに取り替えて下さい。"; "printer-state-reasons.media-needed" = "ペーパーを荷を積んで下さい。"; "printer-state-reasons.none" = "レディ。"; "printer-state-reasons.offline" = "オフライン"; "printer-state-reasons.other" = "プリンターを見る"; "printer-state-reasons.spool-area-full" = "プリンターの忙しい。"; "printer-state-reasons.toner-empty" = "トナー。"; "printer-state-reasons.toner-low" = "トナーの低い。"; "printer-state.3" = "アイドル"; "printer-state.4" = "プロセス"; "printer-state.5" = "停止"; "sides" = "2-被覆印刷"; "sides.one-sided" = "オフ"; "sides.two-sided-long-edge" = "(ポートレート)"; "sides.two-sided-short-edge" = "オン(ランドスケープ)"; "unable to join" = "参加できません"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "土地の島"; pappl-1.4.9/pappl/strings/ja_strings.h000066400000000000000000001734001476704353100200010ustar00rootroot00000000000000static const char *ja_strings = "\" -a Cancel all jobs (cancel).\" = \" -a すべてのジョブをキャンセル (cancel)\";\n" "\" -c COPIES\" = \" -c コピー\";\n" "\" -d PRINTER Specify printer.\" = \" -dプリンターを指定する\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID ジョブ ID (cancel) を指定します。\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m ドライバ名 ドライバーを指定(追加/変更)\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES コピーの数を指定します (submit)\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (デフォルト)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o 名前=値 オプションを指定します (add,modify,server,submit.)\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 から 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 から 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE、LONGITUDE\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOCATION\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZATION\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI ipp: または ipps: プリンタ/サーバーを指定します。\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v デバイス URI ソケットを指定します: または usb: デバイス (add/modify.)\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTERを追加 プリンターを追加\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd 自動追加 サポートされているプリンターを自動的に追加します。\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel キャンセル 1 つ以上のジョブをキャンセルします。\";\n" "\" default Set the default printer.\" = \" default デフォルト デフォルトプリンタを設定します。\";\n" "\" delete Delete a printer.\" = \" delete プリンターを削除します。\";\n" "\" devices List devices.\" = \" devices デバイス リストデバイス。\";\n" "\" drivers List drivers.\" = \" drivers ドライバー リストドライバー。\";\n" "\" jobs List jobs.\" = \" jobs 求人情報 ジョブリスト\";\n" "\" modify Modify a printer.\" = \" modify プリンターを変更します。\";\n" "\" options List printer options.\" = \" options オプション プリンターオプションをリストします。\";\n" "\" pause Pause printing for a printer.\" = \" pause 一時停止 プリンターのプリント\";\n" "\" printers List printers.\" = \" printers プリンター プリンターリスト\";\n" "\" resume Resume printing for a printer.\" = \" resume プリンター用のResumeの印刷を再開します。\";\n" "\" server Run a server.\" = \" server サーバはサーバを実行します。\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown 実行中のサーバーをシャットダウンします。\";\n" "\" status Show server/printer/job status.\" = \" status ステータス サーバ/プリンター/ジョブの状態を表示します。\";\n" "\" submit Submit a file for printing.\" = \" submit 印刷用のファイルを提出してください。\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%dインチ/秒\";\n" "\"%d job\" = \"%d ジョブ\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%dのdpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g \\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s (%s%s)\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) から %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s メディア\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: 悪いサーバーポート値。\";\n" "\"%s: Bad job ID.\" = \"%s: 不良ジョブID\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: 悪いプリンター URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: 複数のサブコマンドを指定できません。\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s:標準入力で受け取る空のプリントファイル。\";\n" "\"%s: Failed to create a system.\" = \"%s: システムの作成に失敗しました。\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: '-d PRINTER を欠く お問い合わせ\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: '-m DRIVER-NAME を欠く お問い合わせ\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: \\\"-v DEVICE-URI を欠く お問い合わせ\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: -n の後のコピーカウントを欠落させます。\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: -v の後のデバイス URI を欠く。\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: -m の後の運転者の名前を欠くこと。\";\n" "\"%s: Missing filename after '--'.\" = \"%s: '--' の後のファイル名を欠く。\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: -h の後のホスト名を欠く。\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: -j の後のジョブ ID を欠落させます。\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: -o の後にオプションを欠く\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: -u の後のプリンター URI を欠くこと。\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: -d の後のプリンター名を逃す。\";\n" "\"%s: Missing space after '-o'.\" = \"%s: -o の後のスペースを逃すこと。\";\n" "\"%s: Missing title after '-t'.\" = \"%s: -t の後のタイトルを欠く.\";\n" "\"%s: No default printer available.\" = \"%s: デフォルトプリンタは使用できません。\";\n" "\"%s: No files to print.\" = \"%s: 印刷するファイルはありません。\";\n" "\"%s: Server is not running.\" = \"%s: サーバが稼働していません。\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: サブコマンド '%s' はファイルを受け入れません。\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: サブコマンドの自動追加はサポートされていません。\";\n" "\"%s: Too many files.\" = \"%s: あまりにも多くのファイル。\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: '%s': %s にアクセスできない\";\n" "\"%s: Unable to add printer: %s\" = \"%s: プリンターを追加できません: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: ジョブをキャンセルできません: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: プリンターに接続できない '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: サーバーに接続できません: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: 一時ファイルを作成することができません: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: プリンターを削除できません: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: '%s': %s の情報を取得することができません\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: プリンター情報を取得することができません: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: プリンタのオプションを取得することができません: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: プリンターの変更はできません: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: プリンタを一時停止できません: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: '%s': %s を印刷できません\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: プリンタを再開できません: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: デフォルトプリンタを設定することができません: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: サーバをシャットダウンできない: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: サーバーを起動できません: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: 一時的なファイルに書き込むことができない: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: 不明なオプション '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: 不明なオプション '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: 未知のサブコマンド '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: サポートされていない URI スキーム '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: 警告 - ユーザ認証情報は URI でサポートされていません。\";\n" "\", Borderless\" = \", ボーダーレス\";\n" "\"A printer with that name already exists.\" = \"既に存在している名前のプリンター。\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"プリンターを追加\";\n" "\"Admin Group\" = \"管理者グループ\";\n" "\"Afghanistan\" = \"アフガニスタン\";\n" "\"Albania\" = \"アルバニア\";\n" "\"Algeria\" = \"アルジェリア\";\n" "\"American Samoa\" = \"アメリカ サモア\";\n" "\"Andorra\" = \"アンドラ\";\n" "\"Angola\" = \"アンゴラ\";\n" "\"Anguilla\" = \"アンギラ\";\n" "\"Antarctica\" = \"アナトリア\";\n" "\"Antigua and Barbuda\" = \"アンティグア・バーブーダ\";\n" "\"Argentina\" = \"アルゼンチン\";\n" "\"Armenia\" = \"アルメニア\";\n" "\"Aruba\" = \"アルバ\";\n" "\"Australia\" = \"オーストラリア\";\n" "\"Austria\" = \"オーストリア\";\n" "\"Auto\" = \"自動車\";\n" "\"Auto-Detect Driver\" = \"自動検出の運転者\";\n" "\"Azerbaijan\" = \"アゼルバイジャン\";\n" "\"Bad administration group.\" = \"悪い管理グループ。\";\n" "\"Bad port number.\" = \"悪いポート番号。\";\n" "\"Bad print group.\" = \"悪いプリントグループ。\";\n" "\"Bad printer defaults.\" = \"悪いプリンタのデフォルト。\";\n" "\"Bahamas\" = \"バハマ\";\n" "\"Bahrain\" = \"バーレーン\";\n" "\"Bangladesh\" = \"バングラデシュ\";\n" "\"Barbados\" = \"バルバドス\";\n" "\"Belarus\" = \"ベラルーシ\";\n" "\"Belgium\" = \"ベルギー\";\n" "\"Belize\" = \"ベリーズ\";\n" "\"Benin\" = \"ログイン\";\n" "\"Bermuda\" = \"バーミューダ\";\n" "\"Bhutan\" = \"ブータン\";\n" "\"Bolivia (Plurinational State of)\" = \"ボリビア(国)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"ボネール、シント・ユースタチウス、サバ\";\n" "\"Borderless\" = \"ボーダーレス\";\n" "\"Bosnia and Herzegovina\" = \"ボスニアとヘルツェゴビナ\";\n" "\"Botswana\" = \"ボツワナ\";\n" "\"Bouvet Island\" = \"ブーヴェ島\";\n" "\"Brazil\" = \"ブラジル\";\n" "\"British Indian Ocean Territory\" = \"イギリスのインド洋の領事\";\n" "\"Brunei Darussalam\" = \"ブルネイ・ダルサラーム\";\n" "\"Bulgaria\" = \"ブルガリア\";\n" "\"Burkina Faso\" = \"ブルキナファソ\";\n" "\"Burundi\" = \"ブルンディ\";\n" "\"Cabo Verde\" = \"カボ・ヴェルデ\";\n" "\"Cambodia\" = \"カンボジア\";\n" "\"Cameroon\" = \"キャメルーン\";\n" "\"Canada\" = \"カナダ\";\n" "\"Cancel All Jobs\" = \"すべてのジョブをキャンセルする\";\n" "\"Cancel Job\" = \"キャンセルジョブ\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"キャンセル\";\n" "\"Cayman Islands\" = \"ケイマン諸島\";\n" "\"Central African Republic\" = \"中央アフリカ共和国\";\n" "\"Certificate created.\" = \"証明書作成。\";\n" "\"Certificate installed.\" = \"証明書は取付けました。\";\n" "\"Certificate request created.\" = \"証明書作成リクエスト\";\n" "\"Chad\" = \"チャド\";\n" "\"Change Access Password\" = \"アクセスパスワードの変更\";\n" "\"Change Log Level\" = \"ログレベルを変更する\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"Wi-Fiネットワークの変更\";\n" "\"Changes Saved.\" = \"保存された変更。\";\n" "\"Changes saved.\" = \"保存された変更。\";\n" "\"Chile\" = \"チリ\";\n" "\"China\" = \"中国の\";\n" "\"Christmas Island\" = \"クリスマス島\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"ココス諸島(ケイリング)\";\n" "\"Colombia\" = \"コロンビア\";\n" "\"Comoros\" = \"コモロ\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"コンテンツ\";\n" "\"Configure Media\" = \"メディアの設定\";\n" "\"Confirm Cancel All\" = \"キャンセル確認 すべて\";\n" "\"Confirm Delete Printer\" = \"プリンターの削除を確認する\";\n" "\"Congo\" = \"コンゴ\";\n" "\"Congo, Democratic Republic of the\" = \"コンゴ、民主共和国\";\n" "\"Contact\" = \"お問い合わせ\";\n" "\"Cook Islands\" = \"クック諸島\";\n" "\"Costa Rica\" = \"コスタリカ\";\n" "\"Create Certificate Signing Request\" = \"証明書署名リクエストを作成する\";\n" "\"Create New Certificate\" = \"新しい証明書を作成する\";\n" "\"Create New TLS Certificate\" = \"新しい TLS 証明書を作成する\";\n" "\"Create TLS Certificate Request\" = \"TLS の作成 証明書の要求\";\n" "\"Croatia\" = \"クロアチア\";\n" "\"Cuba\" = \"キューバ\";\n" "\"Curaçao\" = \"キュラオ\";\n" "\"Current Password\" = \"現在のパスワード\";\n" "\"Custom Size\" = \"注文のサイズ\";\n" "\"Cyprus\" = \"キプロス\";\n" "\"Czechia\" = \"チェコ語\";\n" "\"Côte d'Ivoire\" = \"Cte d'イボワール\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"DNS-SDサービス名\";\n" "\"Debugging\" = \"デバッギング\";\n" "\"Default printer set.\" = \"デフォルトプリンターセット。\";\n" "\"Delete\" = \"削除\";\n" "\"Delete Printer\" = \"プリンターの削除\";\n" "\"Denmark\" = \"デンマーク\";\n" "\"Djibouti\" = \"ジブチ\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"ドミニカ\";\n" "\"Dominican Republic\" = \"ドミニカ共和国\";\n" "\"Download Certificate Request File\" = \"証明書の要求ファイルのダウンロード\";\n" "\"Ecuador\" = \"エクアドル\";\n" "\"Egypt\" = \"エジプト\";\n" "\"El Salvador\" = \"エルサルバドール\";\n" "\"Equatorial Guinea\" = \"エクトリアルギニア\";\n" "\"Eritrea\" = \"エリトリア\";\n" "\"Errors\" = \"エラー\";\n" "\"Estonia\" = \"エストニア\";\n" "\"Eswatini\" = \"エスカティーニ\";\n" "\"Ethiopia\" = \"エチオピア\";\n" "\"Falkland Islands (Malvinas)\" = \"フォークランド諸島 (Malvinas)\";\n" "\"Faroe Islands\" = \"フェロー諸島\";\n" "\"Fatal Errors/Conditions\" = \"致命的な間違い/条件\";\n" "\"Fiji\" = \"フィジー\";\n" "\"Finland\" = \"フィンランド\";\n" "\"France\" = \"フランス\";\n" "\"French Guiana\" = \"フランスのガイアナ\";\n" "\"French Polynesia\" = \"フランスのポリネシア\";\n" "\"French Southern Territories\" = \"フランスの南地域\";\n" "\"Gabon\" = \"ガボン\";\n" "\"Gambia\" = \"ガンビア\";\n" "\"Georgia\" = \"ジョージア\";\n" "\"Germany\" = \"ドイツ\";\n" "\"Ghana\" = \"ガーナ\";\n" "\"Gibraltar\" = \"ジブラルタル\";\n" "\"Greece\" = \"ギリシャ\";\n" "\"Greenland\" = \"グリーンランド\";\n" "\"Grenada\" = \"グレナダ\";\n" "\"Group changes saved.\" = \"グループの変更を保存しました。\";\n" "\"Guadeloupe\" = \"グアドルーペ\";\n" "\"Guam\" = \"グアム\";\n" "\"Guatemala\" = \"グアテマラ\";\n" "\"Guernsey\" = \"グエルンシー\";\n" "\"Guinea\" = \"ギニア\";\n" "\"Guinea-Bissau\" = \"ギニア・ビサウ\";\n" "\"Guyana\" = \"ガイアナ\";\n" "\"Haiti\" = \"ハイチ\";\n" "\"Heard Island and McDonald Islands\" = \"ヘアード島とマクドナルド諸島\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"聖なる参照\";\n" "\"Honduras\" = \"ホンジュラス\";\n" "\"Hong Kong\" = \"香港\";\n" "\"Hostname\" = \"ホスト名\";\n" "\"Human-Readable Location\" = \"人間可読の場所\";\n" "\"Hungary\" = \"ハンガリー\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"アイスランド\";\n" "\"Identify Printer\" = \"プリンターの識別\";\n" "\"India\" = \"インド\";\n" "\"Indonesia\" = \"インドネシア\";\n" "\"Informational\" = \"インフォメーション\";\n" "\"Install TLS Certificate\" = \"TLSをインストールする 証明書\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"無効なジョブID。\";\n" "\"Invalid certificate or private key.\" = \"無効な証明書か秘密鍵。\";\n" "\"Invalid form data.\" = \"無効なフォームデータ。\";\n" "\"Invalid form submission.\" = \"無効なフォーム送信。\";\n" "\"Invalid job ID.\" = \"無効なジョブID。\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"イラン(イスラム共和国)\";\n" "\"Iraq\" = \"イラク\";\n" "\"Ireland\" = \"アイルランド\";\n" "\"Isle of Man\" = \"男の島\";\n" "\"Israel\" = \"イスラエル\";\n" "\"Italy\" = \"イタリア\";\n" "\"Jamaica\" = \"ジャマイカ\";\n" "\"Japan\" = \"ジャパンジャパン\";\n" "\"Jersey\" = \"ジャージー\";\n" "\"Job #\" = \"求人番号\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"求人情報\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"ヨルダン\";\n" "\"Kazakhstan\" = \"カザフスタン\";\n" "\"Kenya\" = \"ケニア\";\n" "\"Kiribati\" = \"キリバティ\";\n" "\"Korea (Democratic People's Republic of)\" = \"韓国(デモクラティック・ピープルズ・リパブリック)\";\n" "\"Korea, Republic of\" = \"韓国、共和国\";\n" "\"Kuwait\" = \"クウェート\";\n" "\"Kyrgyzstan\" = \"キルギススタン\";\n" "\"Landscape\" = \"ニュース\";\n" "\"Lao People's Democratic Republic\" = \"ラオス人民主共和国\";\n" "\"Latvia\" = \"ラトビア\";\n" "\"Lebanon\" = \"レバノン\";\n" "\"Lesotho\" = \"レソト\";\n" "\"Level\" = \"レベル\";\n" "\"Liberia\" = \"リベリア\";\n" "\"Libya\" = \"リビエラ\";\n" "\"Liechtenstein\" = \"リヒテンシュタイン\";\n" "\"Lithuania\" = \"リトアニア\";\n" "\"Location\" = \"アクセス\";\n" "\"Log Level\" = \"ログレベル\";\n" "\"Logging\" = \"ログイン\";\n" "\"Logs\" = \"ログイン\";\n" "\"Luxembourg\" = \"ルクセンブルク\";\n" "\"Macao\" = \"マカオ\";\n" "\"Madagascar\" = \"マダガスカル\";\n" "\"Malawi\" = \"マラウイ\";\n" "\"Malaysia\" = \"マレーシア\";\n" "\"Maldives\" = \"モルディブ\";\n" "\"Mali\" = \"マリ\";\n" "\"Malta\" = \"マルタ\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"マーシャル諸島\";\n" "\"Martinique\" = \"マルティニーク\";\n" "\"Mauritania\" = \"モーリタニア\";\n" "\"Mauritius\" = \"モーリシャス\";\n" "\"Mayotte\" = \"マヨッテ\";\n" "\"Media\" = \"メディア\";\n" "\"Mexico\" = \"メキシコ\";\n" "\"Micronesia (Federated States of)\" = \"マイクロネシア(連邦)\";\n" "\"Missing action.\" = \"行動を欠く。\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"プライベートキーを欠く。\";\n" "\"Moldova, Republic of\" = \"モルドバ共和国\";\n" "\"Monaco\" = \"メニュー\";\n" "\"Mongolia\" = \"モンゴル\";\n" "\"Montenegro\" = \"モンテネグロ\";\n" "\"Montserrat\" = \"モンセラット\";\n" "\"Morocco\" = \"モロッコ\";\n" "\"Mozambique\" = \"モザンビーク\";\n" "\"Myanmar\" = \"ミャンマー\";\n" "\"Name\" = \"お名前 (必須)\";\n" "\"Namibia\" = \"ナミビア\";\n" "\"Nauru\" = \"ナウル\";\n" "\"Nepal\" = \"ネパール\";\n" "\"Netherlands\" = \"オランダ\";\n" "\"Network\" = \"ネットワーク\";\n" "\"Network Printer\" = \"ネットワークプリンター\";\n" "\"Networking\" = \"ネットワーク\";\n" "\"New Caledonia\" = \"ニューカレドニア\";\n" "\"New Zealand\" = \"ニュージーランド\";\n" "\"Nicaragua\" = \"ニカラグア\";\n" "\"Niger\" = \"ニジェール\";\n" "\"Nigeria\" = \"ナイジェリア\";\n" "\"Niue\" = \"ログイン\";\n" "\"No default printer set.\" = \"デフォルトのプリンタセットはありません。\";\n" "\"No jobs in history.\" = \"履歴のジョブはありません。\";\n" "\"Norfolk Island\" = \"ノーフォーク島\";\n" "\"North Macedonia\" = \"北マケドニア\";\n" "\"Northern Mariana Islands\" = \"北マリアナ諸島\";\n" "\"Norway\" = \"ノルウェー\";\n" "\"Not set\" = \"セットなし\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"オフセット\";\n" "\"Oman\" = \"オマーン\";\n" "\"Options:\" = \"オプション:\";\n" "\"Organization\" = \"社会招聘\";\n" "\"Organization Name\" = \"組織名称\";\n" "\"Other Settings\" = \"その他の設定\";\n" "\"Pakistan\" = \"パキスタン\";\n" "\"Palau\" = \"パラオ\";\n" "\"Palestine, State of\" = \"パレスチナ、州\";\n" "\"Panama\" = \"パナマ\";\n" "\"Papua New Guinea\" = \"パプアニューギニア\";\n" "\"Paraguay\" = \"パラグアイ\";\n" "\"Password\" = \"パスワード\";\n" "\"Password changed.\" = \"パスワードが変更されました。\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"パスワードは、少なくとも8文字以上で、少なくとも1つの大文字、小文字、および1つの数字を含む必要があります。\";\n" "\"Passwords do not match.\" = \"パスワードは一致しません。\";\n" "\"Pause Printing\" = \"ペーパー印刷\";\n" "\"Peru\" = \"ペルー\";\n" "\"Philippines\" = \"フィリピン\";\n" "\"Pitcairn\" = \"ピッツケアン\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"プリンターのホスト名またはIPアドレスを入力してください。\";\n" "\"Please enter a printer name.\" = \"プリンター名を入力してください。\";\n" "\"Please select a device.\" = \"デバイスを選択してください。\";\n" "\"Please select a driver.\" = \"ドライバーをお選びください。\";\n" "\"Please select a valid log level.\" = \"有効なログレベルを選択してください。\";\n" "\"Poland\" = \"ポーランド\";\n" "\"Portrait\" = \"ポートレート\";\n" "\"Portugal\" = \"ポルトガル\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"プリントグループ\";\n" "\"Print Test Page\" = \"プリントテストページ\";\n" "\"Print job options:\" = \"ジョブオプションを印刷:\";\n" "\"Printer identified.\" = \"識別されるプリンター。\";\n" "\"Printer is currently active.\" = \"プリンターは現在有効です。\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"プリンター名は、文字またはアンダースコアで始まり、特別な文字を含むことはできません。\";\n" "\"Printer options:\" = \"プリンター選択:\";\n" "\"Printer paused.\" = \"プリンターはpaused。\";\n" "\"Printer pausing.\" = \"プリンター ペーパー。\";\n" "\"Printer resuming.\" = \"プリンター再開。\";\n" "\"Printers\" = \"プリンター\";\n" "\"Printing Defaults\" = \"印刷のデフォルト\";\n" "\"Puerto Rico\" = \"プエルトリコ\";\n" "\"Qatar\" = \"カタール\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"再印刷ジョブ\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"再開の印刷\";\n" "\"Reverse Landscape\" = \"逆の風景\";\n" "\"Reverse Portrait\" = \"逆の肖像\";\n" "\"Romania\" = \"ルーマニア\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"%s %s以来のランニング、%s。\";\n" "\"Russian Federation\" = \"ロシア連邦\";\n" "\"Rwanda\" = \"ルワンダ\";\n" "\"Réunion\" = \"ログイン\";\n" "\"Saint Barthélemy\" = \"サン・バルトレミー\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"セントヘレナ、アセンション、トリスタン・ダ・クンハ\";\n" "\"Saint Kitts and Nevis\" = \"セントキッツとネイビス\";\n" "\"Saint Lucia\" = \"セントルシア\";\n" "\"Saint Martin (French part)\" = \"聖マーティン(フランス部分)\";\n" "\"Saint Pierre and Miquelon\" = \"サンピエールとミクロン\";\n" "\"Saint Vincent and the Grenadines\" = \"セントビンセントとグレナディーン諸島\";\n" "\"Samoa\" = \"サモア\";\n" "\"San Marino\" = \"サンマリノ\";\n" "\"Sao Tome and Principe\" = \"トームとプリンシペ\";\n" "\"Saudi Arabia\" = \"サウジアラビア\";\n" "\"Save Changes\" = \"変更を保存\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"セキュリティ\";\n" "\"Select Driver\" = \"ドライバーの選択\";\n" "\"Senegal\" = \"セネガル\";\n" "\"Serbia\" = \"セルビア\";\n" "\"Server is not running.\" = \"サーバが稼働していません。\";\n" "\"Set Access Password\" = \"アクセスパスワードを設定する\";\n" "\"Set as Default\" = \"デフォルトで設定\";\n" "\"Seychelles\" = \"セイシェル\";\n" "\"Sierra Leone\" = \"シエラレオネ\";\n" "\"Singapore\" = \"シンガポール\";\n" "\"Sint Maarten (Dutch part)\" = \"シント・マールテン(オランダ)\";\n" "\"Slovakia\" = \"スロバキア\";\n" "\"Slovenia\" = \"スワッピング\";\n" "\"Solomon Islands\" = \"ソロモン諸島\";\n" "\"Somalia\" = \"ソマリア\";\n" "\"South Africa\" = \"南アフリカ\";\n" "\"South Georgia and the South Sandwich Islands\" = \"南ジョージアと南サンドイッチ諸島\";\n" "\"South Sudan\" = \"南スーダン\";\n" "\"Spain\" = \"スペイン\";\n" "\"Sri Lanka\" = \"スリランカ\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"ステータス\";\n" "\"Sub-commands:\" = \"サブコマンド:\";\n" "\"Sudan\" = \"スーダン\";\n" "\"Supplies\" = \"アクセサリー\";\n" "\"Suriname\" = \"スリナム\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbardと1月マレン\";\n" "\"Sweden\" = \"スウェーデン\";\n" "\"Switzerland\" = \"スイス\";\n" "\"Syrian Arab Republic\" = \"シリア アラブ共和国\";\n" "\"Taiwan, Province of China\" = \"台湾、中国省\";\n" "\"Tajikistan\" = \"タジキスタン\";\n" "\"Tanzania, United Republic of\" = \"タンザニア, United Kingdom\";\n" "\"Test page printed.\" = \"印刷されたテストページ。\";\n" "\"Thailand\" = \"タイ\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"このフォームは、認証機関(CA)に送信できる証明書署名(CSR)を作成して、信頼できるTLS証明書を入手します。 秘密鍵は、CAから取得する証明書と使用するために別途保存されます。\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"このフォームは、安全な印刷のために新しい自己署名のTLS証明書を作成します。 自己署名証明書は、Webブラウザによって自動的に信頼されません。\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"このフォームは、認証機関(CA)から入手した信頼できるTLS証明書をインストールします。 インストール後すぐに利用します。\";\n" "\"Timor-Leste\" = \"ティモール・レステ\";\n" "\"Togo\" = \"トーゴ\";\n" "\"Tokelau\" = \"トケラウ\";\n" "\"Tonga\" = \"トンガ\";\n" "\"Trinidad and Tobago\" = \"トリニダードとトバゴ\";\n" "\"Tunisia\" = \"チュニジア\";\n" "\"Turkey\" = \"トルコ\";\n" "\"Turkmenistan\" = \"トルクメニスタン\";\n" "\"Turks and Caicos Islands\" = \"タークス・カイコス諸島\";\n" "\"Tuvalu\" = \"ツバル\";\n" "\"Uganda\" = \"ウガンダ\";\n" "\"Ukraine\" = \"ウクライナ\";\n" "\"Unable to access test print file.\" = \"テストプリントファイルにアクセスできません。\";\n" "\"Unable to copy print job.\" = \"印刷ジョブをコピーできません。\";\n" "\"Unable to create certificate request.\" = \"証明書のリクエストを作成することができません。\";\n" "\"Unable to create certificate.\" = \"証明書を作成することができません。\";\n" "\"Unable to create test print job.\" = \"テストプリントジョブを作成することができません。\";\n" "\"Unable to identify printer.\" = \"プリンターを識別できません。\";\n" "\"Unable to lookup address.\" = \"アドレスを調べることができません。\";\n" "\"Unable to use that driver.\" = \"そのドライバを使用できません。\";\n" "\"United Arab Emirates\" = \"アラブ首長国連邦\";\n" "\"United Kingdom\" = \"イギリス\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"イギリス・北アイルランド王国\";\n" "\"United States Minor Outlying Islands\" = \"アメリカ合衆国 Minor Outlying Islands\";\n" "\"United States of America\" = \"アメリカ合衆国\";\n" "\"Unknown\" = \"未知の\";\n" "\"Unknown action.\" = \"未知のアクション。\";\n" "\"Unknown form action.\" = \"未知のフォームアクション。\";\n" "\"Unknown form request.\" = \"不明なフォームリクエスト\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"ウルグアイ\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"使用法: %s サブコマンド [操作] [ユーザー名]\\n\";\n" "\"Use My Position\" = \"マイポジションを使用する\";\n" "\"Users\" = \"ユーザ名\";\n" "\"Uzbekistan\" = \"ウズベキスタン\";\n" "\"Vanuatu\" = \"バヌアツ\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"ベネズエラ(ボリビア共和国)\";\n" "\"Version %s\" = \"バージョン %s\";\n" "\"Viet Nam\" = \"ベトナム\";\n" "\"View Logs\" = \"ログを表示\";\n" "\"Virgin Islands (British)\" = \"バージン諸島(イギリス)\";\n" "\"Virgin Islands (U.S.)\" = \"バージン諸島(米国)\";\n" "\"Wallis and Futuna\" = \"ウォリスとフツナ\";\n" "\"Warning\" = \"インフォメーション\";\n" "\"Western Sahara\" = \"西サハラ\";\n" "\"Wi-Fi Configuration\" = \"Wi-Fiの設定\";\n" "\"Wi-Fi Network\" = \"Wi-Fiネットワーク\";\n" "\"Width\" = \"アクセス\";\n" "\"Wrong old password.\" = \"古いパスワードが間違っています。\";\n" "\"Yemen\" = \"イエメン\";\n" "\"Zambia\" = \"ザンビア\";\n" "\"Zimbabwe\" = \"ジンバブエ\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"コピーの数\";\n" "\"default printer\" = \"デフォルトプリンタ\";\n" "\"finishings\" = \"フィニッシャー\";\n" "\"finishings.10\" = \"フォールド\";\n" "\"finishings.100\" = \"Z の折目\";\n" "\"finishings.101\" = \"工学Zの折目\";\n" "\"finishings.11\" = \"カット\";\n" "\"finishings.12\" = \"ベール\";\n" "\"finishings.13\" = \"ブックレットメーカー\";\n" "\"finishings.15\" = \"コーティング\";\n" "\"finishings.16\" = \"ラミネート\";\n" "\"finishings.20\" = \"スタプルトップ左\";\n" "\"finishings.21\" = \"ステープルボトム左\";\n" "\"finishings.22\" = \"右上のステープルトップ\";\n" "\"finishings.23\" = \"右上のステープル\";\n" "\"finishings.24\" = \"エッジステッチ左\";\n" "\"finishings.25\" = \"エッジステッチトップ\";\n" "\"finishings.26\" = \"エッジステッチ右\";\n" "\"finishings.27\" = \"エッジステッチボトム\";\n" "\"finishings.28\" = \"左に2つのステープル\";\n" "\"finishings.29\" = \"2 トップにステープル\";\n" "\"finishings.3\" = \"なし\";\n" "\"finishings.30\" = \"2 右にステープル\";\n" "\"finishings.31\" = \"底に2つのステープル\";\n" "\"finishings.32\" = \"3 左にステープル\";\n" "\"finishings.33\" = \"トップ3のステープル\";\n" "\"finishings.34\" = \"3 右上のステープル\";\n" "\"finishings.35\" = \"底の3つのステープル\";\n" "\"finishings.4\" = \"スタプル\";\n" "\"finishings.5\" = \"パンチング\";\n" "\"finishings.50\" = \"左ビン\";\n" "\"finishings.51\" = \"ビントップ\";\n" "\"finishings.52\" = \"ビンド右\";\n" "\"finishings.53\" = \"ビン底\";\n" "\"finishings.6\" = \"カバー\";\n" "\"finishings.60\" = \"すべてのページを閉じる\";\n" "\"finishings.61\" = \"すべての文書の後にカット\";\n" "\"finishings.62\" = \"すべてのセットの後で切れて下さい\";\n" "\"finishings.63\" = \"ジョブ後のカット\";\n" "\"finishings.7\" = \"ログイン\";\n" "\"finishings.70\" = \"パンチトップ左\";\n" "\"finishings.71\" = \"パンチボトム左\";\n" "\"finishings.72\" = \"パンチトップ右\";\n" "\"finishings.73\" = \"右下のパンチ\";\n" "\"finishings.74\" = \"2穴パンチ左\";\n" "\"finishings.75\" = \"2穴パンチトップ\";\n" "\"finishings.76\" = \"2穴パンチ右\";\n" "\"finishings.77\" = \"2穴パンチボトム\";\n" "\"finishings.78\" = \"3穴パンチ左\";\n" "\"finishings.79\" = \"3穴パンチトップ\";\n" "\"finishings.8\" = \"サドルステッチ\";\n" "\"finishings.80\" = \"3穴パンチ右\";\n" "\"finishings.81\" = \"3穴パンチボトム\";\n" "\"finishings.82\" = \"4穴パンチ左\";\n" "\"finishings.83\" = \"4穴パンチトップ\";\n" "\"finishings.84\" = \"4穴パンチ右\";\n" "\"finishings.85\" = \"4穴パンチボトム\";\n" "\"finishings.86\" = \"多穴パンチ左\";\n" "\"finishings.87\" = \"マルチホールパンチトップ\";\n" "\"finishings.88\" = \"多穴パンチ右\";\n" "\"finishings.89\" = \"多穴パンチ底\";\n" "\"finishings.9\" = \"エッジステッチ\";\n" "\"finishings.90\" = \"アコーディオンの折目\";\n" "\"finishings.91\" = \"二重ゲートの折目\";\n" "\"finishings.92\" = \"ゲートの折目\";\n" "\"finishings.93\" = \"ハーフフォールド\";\n" "\"finishings.94\" = \"ハーフZフォールド\";\n" "\"finishings.95\" = \"左ゲートの折目\";\n" "\"finishings.96\" = \"手紙の折目\";\n" "\"finishings.97\" = \"平行折目\";\n" "\"finishings.98\" = \"ポスター折り目\";\n" "\"finishings.99\" = \"右ゲートの折目\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"停止。\";\n" "\"job-state-reasons.compression-error\" = \"圧縮エラー。\";\n" "\"job-state-reasons.document-format-error\" = \"ドキュメントフォーマットエラー。\";\n" "\"job-state-reasons.document-password-error\" = \"ドキュメントパスワードエラー。\";\n" "\"job-state-reasons.document-permission-error\" = \"ドキュメント許可エラー。\";\n" "\"job-state-reasons.document-unprintable-error\" = \"印刷不能なエラーを文書化します。\";\n" "\"job-state-reasons.errors-detected\" = \"検出されたエラー。\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"プリンターでのキャンセル\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"ユーザーによるキャンセル\";\n" "\"job-state-reasons.job-completed-successfully\" = \"印刷される。\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"エラーで印刷。\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"警告で印刷。\";\n" "\"job-state-reasons.job-data-insufficient\" = \"十分なデータ。\";\n" "\"job-state-reasons.job-fetchable\" = \"取得可能。\";\n" "\"job-state-reasons.job-incoming\" = \"お問い合わせ\";\n" "\"job-state-reasons.job-printing\" = \"印刷。\";\n" "\"job-state-reasons.job-queued\" = \"印刷する準備。\";\n" "\"job-state-reasons.job-spooling\" = \"スプール。\";\n" "\"job-state-reasons.none\" = \"終わり。\";\n" "\"job-state-reasons.printer-stopped\" = \"プリンターオフライン。\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"プリンター部分的に停止。\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"停止。\";\n" "\"job-state-reasons.queued-in-device\" = \"レディ。\";\n" "\"job-state-reasons.warnings-detected\" = \"検出された警告。\";\n" "\"job-state.3\" = \"ペンディング\";\n" "\"job-state.4\" = \"開催概要\";\n" "\"job-state.5\" = \"プロセス\";\n" "\"job-state.6\" = \"停止\";\n" "\"job-state.7\" = \"キャンセル\";\n" "\"job-state.8\" = \"アボラ\";\n" "\"job-state.9\" = \"完了しました\";\n" "\"joining\" = \"エントリー\";\n" "\"media\" = \"メディア\";\n" "\"media-col\" = \"メディア\";\n" "\"media-size\" = \"メディア サイズ\";\n" "\"media-size-name\" = \"メディア サイズ\";\n" "\"media-source\" = \"入力トレイ\";\n" "\"media-source.alternate\" = \"オルタナティブ\";\n" "\"media-source.alternate-roll\" = \"代替ロール\";\n" "\"media-source.auto\" = \"オートマチック\";\n" "\"media-source.bottom\" = \"ボトム\";\n" "\"media-source.by-pass-tray\" = \"多目的トレイ\";\n" "\"media-source.center\" = \"センター\";\n" "\"media-source.disc\" = \"ディスク\";\n" "\"media-source.envelope\" = \"エンベロープ\";\n" "\"media-source.hagaki\" = \"ハガキ\";\n" "\"media-source.large-capacity\" = \"大容量\";\n" "\"media-source.left\" = \"ふりがな\";\n" "\"media-source.main\" = \"メインページ\";\n" "\"media-source.main-roll\" = \"主要なロール\";\n" "\"media-source.manual\" = \"マニュアル\";\n" "\"media-source.middle\" = \"ミドル\";\n" "\"media-source.photo\" = \"プロフィール\";\n" "\"media-source.rear\" = \"リア\";\n" "\"media-source.right\" = \"アクセス\";\n" "\"media-source.roll-1\" = \"ロール 1\";\n" "\"media-source.roll-10\" = \"ロール 10\";\n" "\"media-source.roll-2\" = \"ロール2\";\n" "\"media-source.roll-3\" = \"ロール3\";\n" "\"media-source.roll-4\" = \"ロール4\";\n" "\"media-source.roll-5\" = \"ロール5\";\n" "\"media-source.roll-6\" = \"ロール 6\";\n" "\"media-source.roll-7\" = \"ロール 7\";\n" "\"media-source.roll-8\" = \"ロール8\";\n" "\"media-source.roll-9\" = \"ロール9\";\n" "\"media-source.side\" = \"サイド\";\n" "\"media-source.top\" = \"トップページ\";\n" "\"media-source.tray-1\" = \"トレイ 1\";\n" "\"media-source.tray-10\" = \"トレイ 10\";\n" "\"media-source.tray-11\" = \"トレイ 11\";\n" "\"media-source.tray-12\" = \"トレイ 12\";\n" "\"media-source.tray-13\" = \"トレイ 13\";\n" "\"media-source.tray-14\" = \"トレイ 14\";\n" "\"media-source.tray-15\" = \"トレイ 15\";\n" "\"media-source.tray-16\" = \"トレイ 16\";\n" "\"media-source.tray-17\" = \"トレイ 17\";\n" "\"media-source.tray-18\" = \"トレイ 18\";\n" "\"media-source.tray-19\" = \"トレイ 19\";\n" "\"media-source.tray-2\" = \"トレイ2\";\n" "\"media-source.tray-20\" = \"トレイ 20\";\n" "\"media-source.tray-3\" = \"トレイ 3\";\n" "\"media-source.tray-4\" = \"トレイ 4\";\n" "\"media-source.tray-5\" = \"トレイ 5\";\n" "\"media-source.tray-6\" = \"トレイ 6\";\n" "\"media-source.tray-7\" = \"トレイ 7\";\n" "\"media-source.tray-8\" = \"トレイ 8\";\n" "\"media-source.tray-9\" = \"トレイ 9\";\n" "\"media-tracking\" = \"メディアトラッキング\";\n" "\"media-tracking.continuous\" = \"連続的な\";\n" "\"media-tracking.gap\" = \"ギャップ\";\n" "\"media-tracking.mark\" = \"ログイン\";\n" "\"media-tracking.web\" = \"サイトマップ\";\n" "\"media-type\" = \"メディアタイプ\";\n" "\"media-type.aluminum\" = \"アルミ\";\n" "\"media-type.auto\" = \"オートマチック\";\n" "\"media-type.back-print-film\" = \"バックプリントフィルム\";\n" "\"media-type.cardboard\" = \"段ボール\";\n" "\"media-type.cardstock\" = \"カードストック\";\n" "\"media-type.cd\" = \"アルバム\";\n" "\"media-type.continuous\" = \"連続的な\";\n" "\"media-type.continuous-long\" = \"連続ロング\";\n" "\"media-type.continuous-short\" = \"連続ショート\";\n" "\"media-type.corrugated-board\" = \"波形板\";\n" "\"media-type.disc\" = \"光学ディスク\";\n" "\"media-type.disc-glossy\" = \"光沢のある光学ディスク\";\n" "\"media-type.disc-high-gloss\" = \"高い光沢の光学ディスク\";\n" "\"media-type.disc-matte\" = \"マット光学ディスク\";\n" "\"media-type.disc-satin\" = \"サテン光学ディスク\";\n" "\"media-type.disc-semi-gloss\" = \"セミグロス光学ディスク\";\n" "\"media-type.double-wall\" = \"二重壁\";\n" "\"media-type.dry-film\" = \"ドライフィルム\";\n" "\"media-type.dvd\" = \"DVD机\";\n" "\"media-type.embossing-foil\" = \"浮彫りになるホイル\";\n" "\"media-type.end-board\" = \"エンドボード\";\n" "\"media-type.envelope\" = \"エンベロープ\";\n" "\"media-type.envelope-archival\" = \"アーカイバル封筒\";\n" "\"media-type.envelope-bond\" = \"ボンド封筒\";\n" "\"media-type.envelope-coated\" = \"上塗を施してある封筒\";\n" "\"media-type.envelope-cotton\" = \"コットン封筒\";\n" "\"media-type.envelope-fine\" = \"良い封筒\";\n" "\"media-type.envelope-heavyweight\" = \"ヘビー級封筒\";\n" "\"media-type.envelope-inkjet\" = \"インクジェット封筒\";\n" "\"media-type.envelope-lightweight\" = \"軽量封筒\";\n" "\"media-type.envelope-plain\" = \"平野封筒\";\n" "\"media-type.envelope-preprinted\" = \"事前印刷された封筒\";\n" "\"media-type.envelope-window\" = \"窓の封筒\";\n" "\"media-type.fabric\" = \"ファブリック\";\n" "\"media-type.fabric-archival\" = \"アーカイバルファブリック\";\n" "\"media-type.fabric-glossy\" = \"光沢のある生地\";\n" "\"media-type.fabric-high-gloss\" = \"高い光沢の生地\";\n" "\"media-type.fabric-matte\" = \"マットの生地\";\n" "\"media-type.fabric-semi-gloss\" = \"半光沢の生地\";\n" "\"media-type.fabric-waterproof\" = \"防水生地\";\n" "\"media-type.film\" = \"フィルム\";\n" "\"media-type.flexo-base\" = \"フレキソベース\";\n" "\"media-type.flexo-photo-polymer\" = \"フレキソフォトポリマー\";\n" "\"media-type.flute\" = \"フルート\";\n" "\"media-type.foil\" = \"ホイル\";\n" "\"media-type.full-cut-tabs\" = \"フルカットタブ\";\n" "\"media-type.glass\" = \"ガラス\";\n" "\"media-type.glass-colored\" = \"ガラス色\";\n" "\"media-type.glass-opaque\" = \"ガラスオパク\";\n" "\"media-type.glass-surfaced\" = \"ガラス面\";\n" "\"media-type.glass-textured\" = \"ガラステクスチャード\";\n" "\"media-type.gravure-cylinder\" = \"グラビアシリンダー\";\n" "\"media-type.image-setter-paper\" = \"イメージのセッターのペーパー\";\n" "\"media-type.imaging-cylinder\" = \"イメージングシリンダー\";\n" "\"media-type.labels\" = \"ラベル\";\n" "\"media-type.labels-colored\" = \"着色されたラベル\";\n" "\"media-type.labels-glossy\" = \"光沢のあるラベル\";\n" "\"media-type.labels-high-gloss\" = \"高い光沢のラベル\";\n" "\"media-type.labels-inkjet\" = \"インクジェットラベル\";\n" "\"media-type.labels-matte\" = \"マットラベル\";\n" "\"media-type.labels-permanent\" = \"永久的なラベル\";\n" "\"media-type.labels-satin\" = \"サテンラベル\";\n" "\"media-type.labels-security\" = \"セキュリティラベル\";\n" "\"media-type.labels-semi-gloss\" = \"半光沢のラベル\";\n" "\"media-type.laminating-foil\" = \"ラミネート箔\";\n" "\"media-type.letterhead\" = \"レターヘッド\";\n" "\"media-type.metal\" = \"ログイン\";\n" "\"media-type.metal-glossy\" = \"金属の光沢のある\";\n" "\"media-type.metal-high-gloss\" = \"金属の高い光沢\";\n" "\"media-type.metal-matte\" = \"メタルマット\";\n" "\"media-type.metal-satin\" = \"金属サテン\";\n" "\"media-type.metal-semi-gloss\" = \"金属の半光沢\";\n" "\"media-type.mounting-tape\" = \"土台テープ\";\n" "\"media-type.multi-layer\" = \"多層層層\";\n" "\"media-type.multi-part-form\" = \"多部分の形態\";\n" "\"media-type.other\" = \"その他\";\n" "\"media-type.paper\" = \"ペーパー\";\n" "\"media-type.photographic\" = \"フォトペーパー\";\n" "\"media-type.photographic-archival\" = \"撮影アーカイブ\";\n" "\"media-type.photographic-film\" = \"フォトフィルム\";\n" "\"media-type.photographic-glossy\" = \"光沢のある写真のペーパー\";\n" "\"media-type.photographic-high-gloss\" = \"高い光沢の写真のペーパー\";\n" "\"media-type.photographic-matte\" = \"マットフォトペーパー\";\n" "\"media-type.photographic-satin\" = \"サテンフォトペーパー\";\n" "\"media-type.photographic-semi-gloss\" = \"半光沢の写真のペーパー\";\n" "\"media-type.plastic\" = \"プラスチック\";\n" "\"media-type.plastic-archival\" = \"プラスチック アーカイブ\";\n" "\"media-type.plastic-colored\" = \"プラスチック着色される\";\n" "\"media-type.plastic-glossy\" = \"プラスチック光沢のある\";\n" "\"media-type.plastic-high-gloss\" = \"プラスチック高い光沢\";\n" "\"media-type.plastic-matte\" = \"プラスチックマット\";\n" "\"media-type.plastic-satin\" = \"プラスチックサテン\";\n" "\"media-type.plastic-semi-gloss\" = \"プラスチック半光沢\";\n" "\"media-type.plate\" = \"プレート\";\n" "\"media-type.polyester\" = \"ポリエステル\";\n" "\"media-type.pre-cut-tabs\" = \"プリカットタブ\";\n" "\"media-type.roll\" = \"ロール\";\n" "\"media-type.screen\" = \"スクリーン\";\n" "\"media-type.screen-paged\" = \"サイトマップ\";\n" "\"media-type.self-adhesive\" = \"自己接着\";\n" "\"media-type.self-adhesive-film\" = \"自己接着フィルム\";\n" "\"media-type.shrink-foil\" = \"収縮ホイル\";\n" "\"media-type.single-face\" = \"シングル\";\n" "\"media-type.single-wall\" = \"単一の壁\";\n" "\"media-type.sleeve\" = \"ジャケット\";\n" "\"media-type.stationery\" = \"ステーショナリー\";\n" "\"media-type.stationery-archival\" = \"文房具のアーカイブ\";\n" "\"media-type.stationery-coated\" = \"塗被紙\";\n" "\"media-type.stationery-cotton\" = \"文具の綿\";\n" "\"media-type.stationery-fine\" = \"ベルラム紙\";\n" "\"media-type.stationery-heavyweight\" = \"ヘビー級紙\";\n" "\"media-type.stationery-heavyweight-coated\" = \"ステーショナリーヘビー級コーティング\";\n" "\"media-type.stationery-inkjet\" = \"文具インクジェットペーパー\";\n" "\"media-type.stationery-letterhead\" = \"レターヘッド\";\n" "\"media-type.stationery-lightweight\" = \"軽量紙\";\n" "\"media-type.stationery-preprinted\" = \"印刷されたペーパー\";\n" "\"media-type.stationery-prepunched\" = \"パンチングペーパー\";\n" "\"media-type.tab-stock\" = \"タブストック\";\n" "\"media-type.tractor\" = \"トラクター\";\n" "\"media-type.transfer\" = \"アクセス\";\n" "\"media-type.transparency\" = \"透明性\";\n" "\"media-type.triple-wall\" = \"トリプルウォール\";\n" "\"media-type.wet-film\" = \"ウェットフィルム\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4または米国手紙\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0の\";\n" "\"media.iso_a0_841x1189mm\" = \"ツイート\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10の特長\";\n" "\"media.iso_a1_594x841mm\" = \"A1の\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3の特長\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4の特長\";\n" "\"media.iso_a2_420x594mm\" = \"A2について\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3の特長\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4の特長\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5の特長\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3(エクストラ)\";\n" "\"media.iso_a3_297x420mm\" = \"A3の特長\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3の特長\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4の特長\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5の特長\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6の特長\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7の特長\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4(エクストラ)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4(タブ)\";\n" "\"media.iso_a4_210x297mm\" = \"A4の特長\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3の特長\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4の特長\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5の特長\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6の特長\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7の特長\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8の特長\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9の特長\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5(エクストラ)\";\n" "\"media.iso_a5_148x210mm\" = \"A5の特長\";\n" "\"media.iso_a6_105x148mm\" = \"A6の特長\";\n" "\"media.iso_a7_74x105mm\" = \"A7の\";\n" "\"media.iso_a8_52x74mm\" = \"A8の特長\";\n" "\"media.iso_a9_37x52mm\" = \"A9の特長\";\n" "\"media.iso_b0_1000x1414mm\" = \"ツイート\";\n" "\"media.iso_b10_31x44mm\" = \"B10の特長\";\n" "\"media.iso_b1_707x1000mm\" = \"B1の\";\n" "\"media.iso_b2_500x707mm\" = \"B2の\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4の特長\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5(エクストラ)\";\n" "\"media.iso_b5_176x250mm\" = \"B5封筒\";\n" "\"media.iso_b6_125x176mm\" = \"B6の特長\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4エンベロープ\";\n" "\"media.iso_b7_88x125mm\" = \"B7の\";\n" "\"media.iso_b8_62x88mm\" = \"B8の特長\";\n" "\"media.iso_b9_44x62mm\" = \"B9の特長\";\n" "\"media.iso_c0_917x1297mm\" = \"C0封筒\";\n" "\"media.iso_c10_28x40mm\" = \"C10封筒\";\n" "\"media.iso_c1_648x917mm\" = \"C1封筒\";\n" "\"media.iso_c2_458x648mm\" = \"C2封筒\";\n" "\"media.iso_c3_324x458mm\" = \"C3封筒\";\n" "\"media.iso_c4_229x324mm\" = \"C4封筒\";\n" "\"media.iso_c5_162x229mm\" = \"C5封筒\";\n" "\"media.iso_c6_114x162mm\" = \"C6封筒\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5封筒\";\n" "\"media.iso_c7_81x114mm\" = \"C7封筒\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 封筒\";\n" "\"media.iso_c8_57x81mm\" = \"C8封筒\";\n" "\"media.iso_c9_40x57mm\" = \"C9封筒\";\n" "\"media.iso_dl_110x220mm\" = \"DL封筒\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISOのRA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISOのRA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISOのRA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISOのRA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISOのRA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISOのSRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISOのSRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISOのSRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISOのSRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISOのSRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"三菱 B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10の特長\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1の特長\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2の特長\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3の特長\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4の特長\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5の特長\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6の特長\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7の特長\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8の特長\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9の特長\";\n" "\"media.jis_exec_216x330mm\" = \"ステンレス エグゼクティブ\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"エンベロープカウ 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"エンベロープカウ 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"エンベロープカウ 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"エンベロープカウ 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"ハガキ\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"エンベロープカウ\";\n" "\"media.jpn_kaku2_240x332mm\" = \"封筒 カウ 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku 返信 ポストカード\";\n" "\"media.jpn_you4_105x235mm\" = \"エンベロープ あなた 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"封筒 A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"封筒 C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"エグゼクティブ\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"ヨーロッパのファンフォールド\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"アメリカのファンフォールド\";\n" "\"media.na_foolscap_8.5x13in\" = \"フットキャップ\";\n" "\"media.na_invoice_5.5x8.5in\" = \"ニュース\";\n" "\"media.na_legal-extra_9.5x15in\" = \"米国の法律(エクストラ)\";\n" "\"media.na_legal_8.5x14in\" = \"米国法\";\n" "\"media.na_letter-extra_9.5x12in\" = \"米国の手紙(元)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"米国の手紙(プラス)\";\n" "\"media.na_letter_8.5x11in\" = \"米国の手紙\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Envelope モンアーチ\";\n" "\"media.na_number-10_4.125x9.5in\" = \"封筒 #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"封筒 #11\";\n" "\"media.na_number-12_4.75x11in\" = \"封筒 #12\";\n" "\"media.na_number-14_5x11.5in\" = \"封筒 #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"封筒 #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"封筒 個人\";\n" "\"media.na_quarto_8.5x10.83in\" = \"クアルト\";\n" "\"media.om_folio-sp_215x315mm\" = \"フォリオ\";\n" "\"media.om_folio_210x330mm\" = \"フォリオ(スペシャル)\";\n" "\"media.om_invite_220x220mm\" = \"封筒の招待状\";\n" "\"media.om_italian_110x230mm\" = \"イタリア\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200×300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mmの\";\n" "\"media.om_pa-kai_267x389mm\" = \"267×389m m 点\";\n" "\"media.om_postfix_114x229mm\" = \"封筒 Postfix\";\n" "\"media.prc_10_324x458mm\" = \"封筒の中国 #10\";\n" "\"media.prc_16k_146x215mm\" = \"中国語 16k\";\n" "\"media.prc_1_102x165mm\" = \"封筒 中国人 #1\";\n" "\"media.prc_2_102x176mm\" = \"封筒 中国人 #2\";\n" "\"media.prc_32k_97x151mm\" = \"中国語 32k\";\n" "\"media.prc_3_125x176mm\" = \"封筒中国 #3\";\n" "\"media.prc_4_110x208mm\" = \"封筒中国 #4\";\n" "\"media.prc_5_110x220mm\" = \"封筒中国 #5\";\n" "\"media.prc_6_120x320mm\" = \"封筒中国 #6\";\n" "\"media.prc_7_160x230mm\" = \"封筒中国 #7\";\n" "\"media.prc_8_120x309mm\" = \"封筒の中国 #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16Kの特長\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ロッコ 8Kの\";\n" "\"not configured\" = \"設定されていない\";\n" "\"not visible\" = \"見えない\";\n" "\"off\" = \"オフ\";\n" "\"on\" = \"お問い合わせ\";\n" "\"orientation-requested\" = \"オリエンテーション\";\n" "\"orientation-requested.3\" = \"ポートレート\";\n" "\"orientation-requested.4\" = \"ニュース\";\n" "\"orientation-requested.5\" = \"逆の風景\";\n" "\"orientation-requested.6\" = \"逆の肖像画\";\n" "\"orientation-requested.7\" = \"なし\";\n" "\"output-bin\" = \"出力トレイ\";\n" "\"output-bin.auto\" = \"オートマチック\";\n" "\"output-bin.bottom\" = \"ボトム\";\n" "\"output-bin.center\" = \"センター\";\n" "\"output-bin.face-down\" = \"フェイスダウン\";\n" "\"output-bin.face-up\" = \"フェイスアップ\";\n" "\"output-bin.large-capacity\" = \"大容量\";\n" "\"output-bin.left\" = \"ふりがな\";\n" "\"output-bin.mailbox-1\" = \"メールボックス 1\";\n" "\"output-bin.mailbox-10\" = \"メールボックス10\";\n" "\"output-bin.mailbox-2\" = \"メールボックス2\";\n" "\"output-bin.mailbox-3\" = \"メールボックス3\";\n" "\"output-bin.mailbox-4\" = \"メールボックス 4\";\n" "\"output-bin.mailbox-5\" = \"メールボックス 5\";\n" "\"output-bin.mailbox-6\" = \"メールボックス 6\";\n" "\"output-bin.mailbox-7\" = \"メールボックス 7\";\n" "\"output-bin.mailbox-8\" = \"メールボックス 8\";\n" "\"output-bin.mailbox-9\" = \"メールボックス 9\";\n" "\"output-bin.middle\" = \"ミドル\";\n" "\"output-bin.my-mailbox\" = \"メールボックス\";\n" "\"output-bin.rear\" = \"リア\";\n" "\"output-bin.right\" = \"アクセス\";\n" "\"output-bin.side\" = \"サイド\";\n" "\"output-bin.stacker-1\" = \"スタッカー 1\";\n" "\"output-bin.stacker-10\" = \"スタッカー 10\";\n" "\"output-bin.stacker-2\" = \"スタッカー 2\";\n" "\"output-bin.stacker-3\" = \"スタッカー 3\";\n" "\"output-bin.stacker-4\" = \"スタッカー 4\";\n" "\"output-bin.stacker-5\" = \"スタッカー 5\";\n" "\"output-bin.stacker-6\" = \"スタッカー 6\";\n" "\"output-bin.stacker-7\" = \"スタッカー 7\";\n" "\"output-bin.stacker-8\" = \"スタッカー 8\";\n" "\"output-bin.stacker-9\" = \"スタッカー 9\";\n" "\"output-bin.top\" = \"トップページ\";\n" "\"output-bin.tray-1\" = \"トレイ 1\";\n" "\"output-bin.tray-10\" = \"トレイ 10\";\n" "\"output-bin.tray-2\" = \"トレイ2\";\n" "\"output-bin.tray-3\" = \"トレイ 3\";\n" "\"output-bin.tray-4\" = \"トレイ 4\";\n" "\"output-bin.tray-5\" = \"トレイ 5\";\n" "\"output-bin.tray-6\" = \"トレイ 6\";\n" "\"output-bin.tray-7\" = \"トレイ 7\";\n" "\"output-bin.tray-8\" = \"トレイ 8\";\n" "\"output-bin.tray-9\" = \"トレイ 9\";\n" "\"print-color-mode\" = \"プリントモード\";\n" "\"print-color-mode.auto\" = \"オートマチック\";\n" "\"print-color-mode.auto-monochrome\" = \"自動モノクロ\";\n" "\"print-color-mode.bi-level\" = \"テキスト\";\n" "\"print-color-mode.color\" = \"カラー\";\n" "\"print-color-mode.highlight\" = \"ハイライト\";\n" "\"print-color-mode.monochrome\" = \"モノクロ\";\n" "\"print-color-mode.process-bi-level\" = \"プロセステキスト\";\n" "\"print-color-mode.process-monochrome\" = \"プロセスモノクロ\";\n" "\"print-content-optimize\" = \"最適化\";\n" "\"print-content-optimize.auto\" = \"オートマチック\";\n" "\"print-content-optimize.graphic\" = \"グラフィック\";\n" "\"print-content-optimize.photo\" = \"プロフィール\";\n" "\"print-content-optimize.text\" = \"テキスト\";\n" "\"print-content-optimize.text-and-graphic\" = \"テキストとグラフィック\";\n" "\"print-darkness\" = \"プリントダークネス\";\n" "\"print-quality\" = \"印刷物の質\";\n" "\"print-quality.3\" = \"ドラフト\";\n" "\"print-quality.4\" = \"ノーマル\";\n" "\"print-quality.5\" = \"ベストベスト\";\n" "\"print-scaling\" = \"スケーリング\";\n" "\"print-scaling.auto\" = \"オートマチック\";\n" "\"print-scaling.auto-fit\" = \"自動フィット\";\n" "\"print-scaling.fill\" = \"お問い合わせ\";\n" "\"print-scaling.fit\" = \"フィット\";\n" "\"print-scaling.none\" = \"なし\";\n" "\"print-speed\" = \"プリント速度\";\n" "\"printer-resolution\" = \"ソリューション\";\n" "\"printer-state-reasons.cover-open\" = \"カバーは開きます。\";\n" "\"printer-state-reasons.door-open\" = \"ドアを開けて下さい。\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"プリンターを識別します。\";\n" "\"printer-state-reasons.input-tray-missing\" = \"ペーパー皿の欠落。\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"インクから。\";\n" "\"printer-state-reasons.marker-supply-low\" = \"低いインク。\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"廃棄物の大箱はほぼ満たします。\";\n" "\"printer-state-reasons.marker-waste-full\" = \"廃棄物の箱の完全。\";\n" "\"printer-state-reasons.media-empty\" = \"ペーパーから。\";\n" "\"printer-state-reasons.media-jam\" = \"ペーパー ジャム。\";\n" "\"printer-state-reasons.media-low\" = \"ペーパーをすぐに取り替えて下さい。\";\n" "\"printer-state-reasons.media-needed\" = \"ペーパーを荷を積んで下さい。\";\n" "\"printer-state-reasons.none\" = \"レディ。\";\n" "\"printer-state-reasons.offline\" = \"オフライン\";\n" "\"printer-state-reasons.other\" = \"プリンターを見る\";\n" "\"printer-state-reasons.spool-area-full\" = \"プリンターの忙しい。\";\n" "\"printer-state-reasons.toner-empty\" = \"トナー。\";\n" "\"printer-state-reasons.toner-low\" = \"トナーの低い。\";\n" "\"printer-state.3\" = \"アイドル\";\n" "\"printer-state.4\" = \"プロセス\";\n" "\"printer-state.5\" = \"停止\";\n" "\"sides\" = \"2-被覆印刷\";\n" "\"sides.one-sided\" = \"オフ\";\n" "\"sides.two-sided-long-edge\" = \"(ポートレート)\";\n" "\"sides.two-sided-short-edge\" = \"オン(ランドスケープ)\";\n" "\"unable to join\" = \"参加できません\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"土地の島\";\n"; pappl-1.4.9/pappl/strings/nb-NO.strings000066400000000000000000001326731476704353100200200ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Avbryt alle jobber."; " -c COPIES" = " -c Kopier"; " -d PRINTER Specify printer." = " -d PRINTER Angi skriver."; " -j JOB-ID Specify job ID (cancel)." = " -j JOB-ID Specify job ID (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m DRIVER-NAME Specify driver (add/modify)."; " -n COPIES Specify number of copies (submit)." = " -n COPIES Specify number of copies (submit)."; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAME=VALUE Specify option (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 til 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 til 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:LATITUDE,LONGITUDE'"; " -o printer-location='LOCATION'" = " -o printer-location='LOCATION'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZATION'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='UNIT/SECTION'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Specify ipp: or ipps: printer/server."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v DEVICE-URI Specify socket: or usb: device (add/modify)."; " add PRINTER Add a printer." = " add PRINTER Add a printer."; " autoadd Automatically add supported printers." = " autoadd Automatically add supported printers."; " cancel Cancel one or more jobs." = " cancel Cancel one or more jobs."; " default Set the default printer." = " default Set the default printer."; " delete Delete a printer." = " delete Delete a printer."; " devices List devices." = " devices List devices."; " drivers List drivers." = " drivers List drivers."; " jobs List jobs." = " jobs List jobs."; " modify Modify a printer." = " modify Modify a printer."; " options List printer options." = " options List printer options."; " pause Pause printing for a printer." = " pause Pause printing for a printer."; " printers List printers." = " printers List printers."; " resume Resume printing for a printer." = " resume Resume printing for a printer."; " server Run a server." = " server Run a server."; " shutdown Shutdown a running server." = " shutdown Shutdown a running server."; " status Show server/printer/job status." = " status Show server/printer/job status."; " submit Submit a file for printing." = " submit Submit a file for printing."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d at %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d days ago at %02d:%02d:%02d"; "%d inches/sec" = "%d inches/sec"; "%d job" = "%d job"; /* Media size in millimeters */ "%d x %dmm" = "%d x %dmm"; "%ddpi" = "%ddpi"; "%dx%ddpi" = "%dx%ddpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) from %s"; /* Source/Tray Media */ "%s Media" = "%s Media"; "%s: Bad 'server-port' value." = "%s: Bad 'server-port' value."; "%s: Bad job ID." = "%s: Bad job ID."; "%s: Bad printer URI '%s'." = "%s: Bad printer URI '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Cannot specify more than one sub-command."; "%s: Empty print file received on the standard input." = "%s: Empty print file received on the standard input."; "%s: Failed to create a system." = "%s: Failed to create a system."; "%s: Missing '-d PRINTER'." = "%s: Missing '-d PRINTER'."; "%s: Missing '-m DRIVER-NAME'." = "%s: Missing '-m DRIVER-NAME'."; "%s: Missing '-v DEVICE-URI'." = "%s: Missing '-v DEVICE-URI'."; "%s: Missing copy count after '-n'." = "%s: Missing copy count after '-n'."; "%s: Missing device URI after '-v'." = "%s: Missing device URI after '-v'."; "%s: Missing driver name after '-m'." = "%s: Missing driver name after '-m'."; "%s: Missing filename after '--'." = "%s: Missing filename after '--'."; "%s: Missing hostname after '-h'." = "%s: Missing hostname after '-h'."; "%s: Missing job ID after '-j'." = "%s: Missing job ID after '-j'."; "%s: Missing option(s) after '-o'." = "%s: Missing option(s) after '-o'."; "%s: Missing printer URI after '-u'." = "%s: Missing printer URI after '-u'."; "%s: Missing printer name after '-d'." = "%s: Missing printer name after '-d'."; "%s: Missing space after '-o'." = "%s: Missing space after '-o'."; "%s: Missing title after '-t'." = "%s: Missing title after '-t'."; "%s: No default printer available." = "%s: No default printer available."; "%s: No files to print." = "%s: No files to print."; "%s: Server is not running." = "%s: Server is not running."; "%s: Sub-command '%s' does not accept files." = "%s: Sub-command '%s' does not accept files."; "%s: Sub-command 'autoadd' is not supported." = "%s: Sub-command 'autoadd' is not supported."; "%s: Too many files." = "%s: Too many files."; "%s: Unable to access '%s': %s" = "%s: Unable to access '%s': %s"; "%s: Unable to add printer: %s" = "%s: Unable to add printer: %s"; "%s: Unable to cancel job: %s" = "%s: Unable to cancel job: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Unable to connect to printer at '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Unable to connect to server: %s"; "%s: Unable to create temporary file: %s" = "%s: Unable to create temporary file: %s"; "%s: Unable to delete printer: %s" = "%s: Unable to delete printer: %s"; "%s: Unable to get available devices: %s" = "%s: Unable to get available devices: %s"; "%s: Unable to get information for '%s': %s" = "%s: Unable to get information for '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Unable to get information for printer: %s"; "%s: Unable to get printer options: %s" = "%s: Unable to get printer options: %s"; "%s: Unable to modify printer: %s" = "%s: Unable to modify printer: %s"; "%s: Unable to pause printer: %s" = "%s: Unable to pause printer: %s"; "%s: Unable to print '%s': %s" = "%s: Unable to print '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Unable to resume printer: %s"; "%s: Unable to set default printer: %s" = "%s: Unable to set default printer: %s"; "%s: Unable to shutdown server: %s" = "%s: Unable to shutdown server: %s"; "%s: Unable to start server: %s" = "%s: Unable to start server: %s"; "%s: Unable to write to temporary file: %s" = "%s: Unable to write to temporary file: %s"; "%s: Unknown option '%s'." = "%s: Unknown option '%s'."; "%s: Unknown option '-%c'." = "%s: Unknown option '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Unknown sub-command '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Unsupported URI scheme '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Warning - user credentials are not supported in URIs."; ", Borderless" = ", Borderless"; "A printer with that name already exists." = "A printer with that name already exists."; "Aborted %s" = "Aborted %s"; "Add Printer" = "Legg til skriver"; "Admin Group" = "Administratorgruppe"; "Afghanistan" = "Afghanistan"; "Albania" = "Albania"; "Algeria" = "Algerie"; "American Samoa" = "American Samoa"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarctica"; "Antigua and Barbuda" = "Antigua and Barbuda"; "Argentina" = "Argentina"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Auto"; "Auto-Detect Driver" = "Auto-Detect Driver"; "Azerbaijan" = "Azerbaijan"; "Bad administration group." = "Bad administration group."; "Bad port number." = "Bad port number."; "Bad print group." = "Bad print group."; "Bad printer defaults." = "Bad printer defaults."; "Bahamas" = "Bahamas"; "Bahrain" = "Bahrain"; "Bangladesh" = "Bangladesh"; "Barbados" = "Barbados"; "Belarus" = "Belarus"; "Belgium" = "Belgium"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivia (Plurinational State of)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius and Saba"; "Borderless" = "Borderless"; "Bosnia and Herzegovina" = "Bosnia and Herzegovina"; "Botswana" = "Botswana"; "Bouvet Island" = "Bouvet Island"; "Brazil" = "Brazil"; "British Indian Ocean Territory" = "British Indian Ocean Territory"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bulgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Cabo Verde"; "Cambodia" = "Cambodia"; "Cameroon" = "Cameroon"; "Canada" = "Canada"; "Cancel All Jobs" = "Avbryt alle jobber"; "Cancel Job" = "Avbryt jobb"; "Canceled %s" = "Canceled %s"; "Canceling" = "Canceling"; "Cayman Islands" = "Cayman Islands"; "Central African Republic" = "Central African Republic"; "Certificate created." = "Certificate created."; "Certificate installed." = "Certificate installed."; "Certificate request created." = "Certificate request created."; "Chad" = "Chad"; "Change Access Password" = "Endre administratorpassord"; "Change Log Level" = "Endre loggføringsnivå"; "Change Network Settings" = "Change Network Settings"; "Change Wi-Fi Network" = "Endre Wi-Fi-nettverk"; "Changes Saved." = "Endringer lagret."; "Changes saved." = "Endringer lagret."; "Chile" = "Chile"; "China" = "Kina"; "Christmas Island" = "Christmas Island"; "City/Locality" = "City/Locality"; "Cocos (Keeling) Islands" = "Cocos (Keeling) Islands"; "Colombia" = "Colombia"; "Comoros" = "Comoros"; "Completed %s" = "Completed %s"; "Configuration" = "Oppsett"; "Configure Media" = "Configure Media"; "Confirm Cancel All" = "Confirm Cancel All"; "Confirm Delete Printer" = "Confirm Delete Printer"; "Congo" = "Congo"; "Congo, Democratic Republic of the" = "Congo, Democratic Republic of the"; "Contact" = "Kontakt"; "Cook Islands" = "Cook Islands"; "Costa Rica" = "Costa Rica"; "Create Certificate Signing Request" = "Create Certificate Signing Request"; "Create New Certificate" = "Opprett nytt sertifikat"; "Create New TLS Certificate" = "Create New TLS Certificate"; "Create TLS Certificate Request" = "Create TLS Certificate Request"; "Croatia" = "Kroatia"; "Cuba" = "Kuba"; "Curaçao" = "Curaçao"; "Current Password" = "Nåværende passord"; "Custom Size" = "Egendefinert størrelse"; "Cyprus" = "Kypros"; "Czechia" = "Czechia"; "Côte d'Ivoire" = "Côte d'Ivoire"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP w/Manual Address"; "DNS-SD Service Name" = "DNS-SD Service Name"; "Debugging" = "Debugging"; "Default printer set." = "Default printer set."; "Delete" = "Slett"; "Delete Printer" = "Slett skriver"; "Denmark" = "Danmark"; "Djibouti" = "Djibouti"; "Domain Name" = "Domain Name"; "Dominica" = "Dominica"; "Dominican Republic" = "Dominican Republic"; "Download Certificate Request File" = "Download Certificate Request File"; "Ecuador" = "Ecuador"; "Egypt" = "Egypt"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Equatorial Guinea"; "Eritrea" = "Eritrea"; "Errors" = "Errors"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Ethiopia"; "Falkland Islands (Malvinas)" = "Falkland Islands (Malvinas)"; "Faroe Islands" = "Faroe Islands"; "Fatal Errors/Conditions" = "Fatal Errors/Conditions"; "Fiji" = "Fiji"; "Finland" = "Finland"; "France" = "France"; "French Guiana" = "French Guiana"; "French Polynesia" = "French Polynesia"; "French Southern Territories" = "French Southern Territories"; "Gabon" = "Gabon"; "Gambia" = "Gambia"; "Georgia" = "Georgia"; "Germany" = "Germany"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Greece"; "Greenland" = "Greenland"; "Grenada" = "Grenada"; "Group changes saved." = "Group changes saved."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Guinea"; "Guinea-Bissau" = "Guinea-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Island and McDonald Islands"; "Hidden SSID" = "Hidden SSID"; "Hold Job" = "Hold Job"; "Hold New Jobs" = "Hold New Jobs"; "Holding new jobs." = "Holding new jobs."; "Holy See" = "Holy See"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Hostname"; "Human-Readable Location" = "Human-Readable Location"; "Hungary" = "Hungary"; "IPv4 Address" = "IPv4 Address"; "IPv4 Configuration" = "IPv4 Configuration"; "IPv4 Gateway" = "IPv4 Gateway"; "IPv4 Netmask" = "IPv4 Netmask"; "IPv6 Address" = "IPv6 Address"; "IPv6 Configuration" = "IPv6 Configuration"; "IPv6 Link-Local" = "IPv6 Link-Local"; "IPv6 Prefix Length" = "IPv6 Prefix Length"; "Iceland" = "Iceland"; "Identify Printer" = "Identify Printer"; "India" = "India"; "Indonesia" = "Indonesia"; "Informational" = "Informational"; "Install TLS Certificate" = "Installer TLS-sertifikat"; "Invalid IPv4 address." = "Invalid IPv4 address."; "Invalid IPv4 netmask." = "Invalid IPv4 netmask."; "Invalid IPv6 address." = "Invalid IPv6 address."; "Invalid IPv6 prefix length." = "Invalid IPv6 prefix length."; "Invalid Job ID." = "Invalid Job ID."; "Invalid certificate or private key." = "Ugyldig sertifikat eller privat nøkkel."; "Invalid form data." = "Ugyldig skjemadata."; "Invalid form submission." = "Ugyldig skjemainnsendelse."; "Invalid job ID." = "Ugyldig jobb-ID."; "Invalid network configuration." = "Invalid network configuration."; "Iran (Islamic Republic of)" = "Iran (Islamic Republic of)"; "Iraq" = "Irak"; "Ireland" = "Irland"; "Isle of Man" = "Isle of Man"; "Israel" = "Israel"; "Italy" = "Italia"; "Jamaica" = "Jamaica"; "Japan" = "Japan"; "Jersey" = "Jersey"; "Job #" = "Jobb #"; "Job canceled." = "Job canceled."; "Job held." = "Job held."; "Job released." = "Job released."; "Jobs" = "Jobber"; "Joining Wi-Fi Network" = "Joining Wi-Fi Network"; "Jordan" = "Jordan"; "Kazakhstan" = "Kazakhstan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Korea (Democratic People's Republic of)"; "Korea, Republic of" = "Korea, Republic of"; "Kuwait" = "Kuwait"; "Kyrgyzstan" = "Kyrgyzstan"; "Landscape" = "Liggende"; "Lao People's Democratic Republic" = "Lao People's Democratic Republic"; "Latvia" = "Latvia"; "Lebanon" = "Lebanon"; "Lesotho" = "Lesotho"; "Level" = "Nivå"; "Liberia" = "Liberia"; "Libya" = "Libya"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Lithuania"; "Location" = "Location"; "Log Level" = "Loggføringsnivå"; "Logging" = "Logging"; "Logs" = "Logger"; "Luxembourg" = "Luxembourg"; "Macao" = "Macao"; "Madagascar" = "Madagascar"; "Malawi" = "Malawi"; "Malaysia" = "Malaysia"; "Maldives" = "Maldives"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Manual Configuration"; "Marshall Islands" = "Marshall Islands"; "Martinique" = "Martinique"; "Mauritania" = "Mauritania"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Media"; "Mexico" = "Mexico"; "Micronesia (Federated States of)" = "Micronesia (Federated States of)"; "Missing action." = "Missing action."; "Missing job ID." = "Missing job ID."; "Missing network name." = "Missing network name."; "Missing private key." = "Mangler privat nøkkel."; "Moldova, Republic of" = "Moldova, Republic of"; "Monaco" = "Monaco"; "Mongolia" = "Mongolia"; "Montenegro" = "Montenegro"; "Montserrat" = "Montserrat"; "Morocco" = "Marokko"; "Mozambique" = "Mozambique"; "Myanmar" = "Myanmar"; "Name" = "Navn"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Nederland"; "Network" = "Nettverk"; "Network Printer" = "Nettverksskriver"; "Networking" = "Networking"; "New Caledonia" = "New Caledonia"; "New Zealand" = "New Zealand"; "Nicaragua" = "Nicaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "No default printer set."; "No jobs in history." = "Ingen jobber i historikk."; "Norfolk Island" = "Norfolk Island"; "North Macedonia" = "North Macedonia"; "Northern Mariana Islands" = "Northern Mariana Islands"; "Norway" = "Norway"; "Not set" = "Not set"; "Off" = "Off"; "Offset" = "Offset"; "Oman" = "Oman"; "Options:" = "Options:"; "Organization" = "Organisasjon"; "Organization Name" = "Organisasjonsnavn"; "Other Settings" = "Andre innstillinger"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palestine, State of"; "Panama" = "Panama"; "Papua New Guinea" = "Papua New Guinea"; "Paraguay" = "Paraguay"; "Password" = "Passord"; "Password changed." = "Passord endret."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit."; "Passwords do not match." = "Passordene samsvarer ikke."; "Pause Printing" = "Pause Printing"; "Peru" = "Peru"; "Philippines" = "Philippines"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Skriv inn vertsnavnet eller IP-adressen til skriveren."; "Please enter a printer name." = "Skriv inn et skrivernavn."; "Please select a device." = "Velg en enhet."; "Please select a driver." = "Please select a driver."; "Please select a valid log level." = "Velg et gyldig loggføringsnivå."; "Poland" = "Polen"; "Portrait" = "Stående"; "Portugal" = "Portugal"; "Primary DNS" = "Primary DNS"; "Print Group" = "Skrivergruppe"; "Print Test Page" = "Skriv ut testside"; "Print job options:" = "Print job options:"; "Printer identified." = "Skriver identifisert."; "Printer is currently active." = "Skriveren er i bruk."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Printer names must start with a letter or underscore and cannot contain special characters."; "Printer options:" = "Skriverinnstillinger:"; "Printer paused." = "Skriver satt på pause."; "Printer pausing." = "Skriver tar pause."; "Printer resuming." = "Skriver gjenopptar utskrift."; "Printers" = "Skrivere"; "Printing Defaults" = "Utskriftsforvalg"; "Puerto Rico" = "Puerto Rico"; "Qatar" = "Qatar"; "Queued %s" = "Queued %s"; "Release Held New Jobs" = "Release Held New Jobs"; "Release Job" = "Release Job"; "Released held new jobs." = "Released held new jobs."; "Reprint Job" = "Skriv ut jobb igjen"; "Reprinted job." = "Reprinted job."; "Resume Printing" = "Fortsett utskrift"; "Reverse Landscape" = "Omvendt liggende"; "Reverse Portrait" = "Omvendt stående"; "Romania" = "Romania"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Running, %s since %s%s."; "Russian Federation" = "Russian Federation"; "Rwanda" = "Rwanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Saint Helena, Ascension and Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts and Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (French part)"; "Saint Pierre and Miquelon" = "Saint Pierre and Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent and the Grenadines"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome and Principe"; "Saudi Arabia" = "Saudi Arabia"; "Save Changes" = "Save Changes"; "Secondary DNS" = "Secondary DNS"; "Security" = "Security"; "Select Driver" = "Select Driver"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "Tjeneren kjører ikke."; "Set Access Password" = "Sett tilgangspassord"; "Set as Default" = "Sett som forvalg"; "Seychelles" = "Seychelles"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapore"; "Sint Maarten (Dutch part)" = "Sint Maarten (Dutch part)"; "Slovakia" = "Slovakia"; "Slovenia" = "Slovenia"; "Solomon Islands" = "Solomon Islands"; "Somalia" = "Somalia"; "South Africa" = "South Africa"; "South Georgia and the South Sandwich Islands" = "South Georgia and the South Sandwich Islands"; "South Sudan" = "South Sudan"; "Spain" = "Spain"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Started %s"; "Status" = "Status"; "Sub-commands:" = "Sub-commands:"; "Sudan" = "Sudan"; "Supplies" = "Supplies"; "Suriname" = "Suriname"; "Svalbard and Jan Mayen" = "Svalbard and Jan Mayen"; "Sweden" = "Sweden"; "Switzerland" = "Switzerland"; "Syrian Arab Republic" = "Syrian Arab Republic"; "Taiwan, Province of China" = "Taiwan, Province of China"; "Tajikistan" = "Tajikistan"; "Tanzania, United Republic of" = "Tanzania, United Republic of"; "Test page printed." = "Test page printed."; "Thailand" = "Thailand"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad and Tobago"; "Tunisia" = "Tunisia"; "Turkey" = "Turkey"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Turks and Caicos Islands"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukraine"; "Unable to access test print file." = "Unable to access test print file."; "Unable to copy print job." = "Unable to copy print job."; "Unable to create certificate request." = "Unable to create certificate request."; "Unable to create certificate." = "Kunne ikke opprette sertifikat."; "Unable to create test print job." = "Unable to create test print job."; "Unable to identify printer." = "Unable to identify printer."; "Unable to lookup address." = "Unable to lookup address."; "Unable to use that driver." = "Unable to use that driver."; "United Arab Emirates" = "United Arab Emirates"; "United Kingdom" = "United Kingdom"; "United Kingdom of Great Britain and Northern Ireland" = "United Kingdom of Great Britain and Northern Ireland"; "United States Minor Outlying Islands" = "United States Minor Outlying Islands"; "United States of America" = "United States of America"; "Unknown" = "Ukjent"; "Unknown action." = "Ukjent handling."; "Unknown form action." = "Ukjent skjemahandling."; "Unknown form request." = "Ukjent skjemaforespørsel."; "Updating Network Configuration" = "Updating Network Configuration"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n"; "Use My Position" = "Use My Position"; "Users" = "Brukere"; "Uzbekistan" = "Uzbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela (Bolivarian Republic of)"; "Version %s" = "Version %s"; "Viet Nam" = "Viet Nam"; "View Logs" = "Vis loggføring"; "Virgin Islands (British)" = "Virgin Islands (British)"; "Virgin Islands (U.S.)" = "Virgin Islands (U.S.)"; "Wallis and Futuna" = "Wallis and Futuna"; "Warning" = "Advarsel"; "Western Sahara" = "Western Sahara"; "Wi-Fi Configuration" = "Wi-Fi-oppsett"; "Wi-Fi Network" = "Wi-Fi-nettverk"; "Width" = "Bredde"; "Wrong old password." = "Feil gammelt passord."; "Yemen" = "Yemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "at %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Antall kopier"; "default printer" = "forvalgt skriver"; "finishings" = "Finisher"; "finishings.10" = "Fold"; "finishings.100" = "Z fold"; "finishings.101" = "Engineering Z fold"; "finishings.11" = "Cut"; "finishings.12" = "Bale"; "finishings.13" = "Booklet maker"; "finishings.15" = "Coat"; "finishings.16" = "Laminate"; "finishings.20" = "Staple top left"; "finishings.21" = "Staple bottom left"; "finishings.22" = "Staple top right"; "finishings.23" = "Staple bottom right"; "finishings.24" = "Edge stitch left"; "finishings.25" = "Edge stitch top"; "finishings.26" = "Edge stitch right"; "finishings.27" = "Edge stitch bottom"; "finishings.28" = "2 staples on left"; "finishings.29" = "2 staples on top"; "finishings.3" = "None"; "finishings.30" = "2 staples on right"; "finishings.31" = "2 staples on bottom"; "finishings.32" = "3 staples on left"; "finishings.33" = "3 staples on top"; "finishings.34" = "3 staples on right"; "finishings.35" = "3 staples on bottom"; "finishings.4" = "Staple"; "finishings.5" = "Punch"; "finishings.50" = "Bind left"; "finishings.51" = "Bind top"; "finishings.52" = "Bind right"; "finishings.53" = "Bind bottom"; "finishings.6" = "Cover"; "finishings.60" = "Cut after every page"; "finishings.61" = "Cut after every document"; "finishings.62" = "Cut after every set"; "finishings.63" = "Cut after job"; "finishings.7" = "Bind"; "finishings.70" = "Punch top left"; "finishings.71" = "Punch bottom left"; "finishings.72" = "Punch top right"; "finishings.73" = "Punch bottom right"; "finishings.74" = "2-hole punch left"; "finishings.75" = "2-hole punch top"; "finishings.76" = "2-hole punch right"; "finishings.77" = "2-hole punch bottom"; "finishings.78" = "3-hole punch left"; "finishings.79" = "3-hole punch top"; "finishings.8" = "Saddle stitch"; "finishings.80" = "3-hole punch right"; "finishings.81" = "3-hole punch bottom"; "finishings.82" = "4-hole punch left"; "finishings.83" = "4-hole punch top"; "finishings.84" = "4-hole punch right"; "finishings.85" = "4-hole punch bottom"; "finishings.86" = "Multi-hole punch left"; "finishings.87" = "Multi-hole punch top"; "finishings.88" = "Multi-hole punch right"; "finishings.89" = "Multi-hole punch bottom"; "finishings.9" = "Edge stitch"; "finishings.90" = "Accordion fold"; "finishings.91" = "Double gate fold"; "finishings.92" = "Gate fold"; "finishings.93" = "Half fold"; "finishings.94" = "Half Z fold"; "finishings.95" = "Left gate fold"; "finishings.96" = "Letter fold"; "finishings.97" = "Parallel fold"; "finishings.98" = "Poster fold"; "finishings.99" = "Right gate fold"; "holding new jobs" = "holding new jobs"; "job-state-reasons.aborted-by-system" = "Stopping."; "job-state-reasons.compression-error" = "Decompression error."; "job-state-reasons.document-format-error" = "Document format error."; "job-state-reasons.document-password-error" = "Document password error."; "job-state-reasons.document-permission-error" = "Document permission error."; "job-state-reasons.document-unprintable-error" = "Document unprintable error."; "job-state-reasons.errors-detected" = "Errors detected."; "job-state-reasons.job-canceled-at-device" = "Canceled at printer."; "job-state-reasons.job-canceled-by-user" = "Canceled by user."; "job-state-reasons.job-completed-successfully" = "Printed."; "job-state-reasons.job-completed-with-errors" = "Printed with errors."; "job-state-reasons.job-completed-with-warnings" = "Printed with warnings."; "job-state-reasons.job-data-insufficient" = "Insufficient data."; "job-state-reasons.job-fetchable" = "Fetchable."; "job-state-reasons.job-incoming" = "Incoming."; "job-state-reasons.job-printing" = "Printing."; "job-state-reasons.job-queued" = "Preparing to print."; "job-state-reasons.job-spooling" = "Spooling."; "job-state-reasons.none" = "Pending."; "job-state-reasons.printer-stopped" = "Printer offline."; "job-state-reasons.printer-stopped-partly" = "Printer partially stopped."; "job-state-reasons.processing-to-stop-point" = "Stopping."; "job-state-reasons.queued-in-device" = "Ready."; "job-state-reasons.warnings-detected" = "Warnings detected."; "job-state.3" = "Pending"; "job-state.4" = "Held"; "job-state.5" = "Processing"; "job-state.6" = "Stopped"; "job-state.7" = "Canceled"; "job-state.8" = "Aborted"; "job-state.9" = "Completed"; "joining" = "joining"; "media" = "Media"; "media-col" = "Media"; "media-size" = "Media Size"; "media-size-name" = "Media Size"; "media-source" = "Input Tray"; "media-source.alternate" = "Alternate"; "media-source.alternate-roll" = "Alternate roll"; "media-source.auto" = "Automatic"; "media-source.bottom" = "Bottom"; "media-source.by-pass-tray" = "Multipurpose tray"; "media-source.center" = "Center"; "media-source.disc" = "Disc"; "media-source.envelope" = "Envelope"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Large capacity"; "media-source.left" = "Left"; "media-source.main" = "Main"; "media-source.main-roll" = "Main roll"; "media-source.manual" = "Manual"; "media-source.middle" = "Middle"; "media-source.photo" = "Photo"; "media-source.rear" = "Rear"; "media-source.right" = "Right"; "media-source.roll-1" = "Roll 1"; "media-source.roll-10" = "Roll 10"; "media-source.roll-2" = "Roll 2"; "media-source.roll-3" = "Roll 3"; "media-source.roll-4" = "Roll 4"; "media-source.roll-5" = "Roll 5"; "media-source.roll-6" = "Roll 6"; "media-source.roll-7" = "Roll 7"; "media-source.roll-8" = "Roll 8"; "media-source.roll-9" = "Roll 9"; "media-source.side" = "Side"; "media-source.top" = "Top"; "media-source.tray-1" = "Tray 1"; "media-source.tray-10" = "Tray 10"; "media-source.tray-11" = "Tray 11"; "media-source.tray-12" = "Tray 12"; "media-source.tray-13" = "Tray 13"; "media-source.tray-14" = "Tray 14"; "media-source.tray-15" = "Tray 15"; "media-source.tray-16" = "Tray 16"; "media-source.tray-17" = "Tray 17"; "media-source.tray-18" = "Tray 18"; "media-source.tray-19" = "Tray 19"; "media-source.tray-2" = "Tray 2"; "media-source.tray-20" = "Tray 20"; "media-source.tray-3" = "Tray 3"; "media-source.tray-4" = "Tray 4"; "media-source.tray-5" = "Tray 5"; "media-source.tray-6" = "Tray 6"; "media-source.tray-7" = "Tray 7"; "media-source.tray-8" = "Tray 8"; "media-source.tray-9" = "Tray 9"; "media-tracking" = "Media Tracking"; "media-tracking.continuous" = "Continuous"; "media-tracking.gap" = "Gap"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web"; "media-type" = "Media Type"; "media-type.aluminum" = "Aluminum"; "media-type.auto" = "Automatic"; "media-type.back-print-film" = "Back print film"; "media-type.cardboard" = "Cardboard"; "media-type.cardstock" = "Cardstock"; "media-type.cd" = "CD"; "media-type.continuous" = "Continuous"; "media-type.continuous-long" = "Continuous long"; "media-type.continuous-short" = "Continuous short"; "media-type.corrugated-board" = "Corrugated board"; "media-type.disc" = "Optical disc"; "media-type.disc-glossy" = "Glossy optical disc"; "media-type.disc-high-gloss" = "High gloss optical disc"; "media-type.disc-matte" = "Matte optical disc"; "media-type.disc-satin" = "Satin optical disc"; "media-type.disc-semi-gloss" = "Semi-gloss optical disc"; "media-type.double-wall" = "Double wall"; "media-type.dry-film" = "Dry film"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Embossing foil"; "media-type.end-board" = "End board"; "media-type.envelope" = "Envelope"; "media-type.envelope-archival" = "Archival envelope"; "media-type.envelope-bond" = "Bond envelope"; "media-type.envelope-coated" = "Coated envelope"; "media-type.envelope-cotton" = "Cotton envelope"; "media-type.envelope-fine" = "Fine envelope"; "media-type.envelope-heavyweight" = "Heavyweight envelope"; "media-type.envelope-inkjet" = "Inkjet envelope"; "media-type.envelope-lightweight" = "Lightweight envelope"; "media-type.envelope-plain" = "Plain envelope"; "media-type.envelope-preprinted" = "Preprinted envelope"; "media-type.envelope-window" = "Windowed envelope"; "media-type.fabric" = "Fabric"; "media-type.fabric-archival" = "Archival fabric"; "media-type.fabric-glossy" = "Glossy fabric"; "media-type.fabric-high-gloss" = "High gloss fabric"; "media-type.fabric-matte" = "Matte fabric"; "media-type.fabric-semi-gloss" = "Semi-gloss fabric"; "media-type.fabric-waterproof" = "Waterproof fabric"; "media-type.film" = "Film"; "media-type.flexo-base" = "Flexo base"; "media-type.flexo-photo-polymer" = "Flexo photo polymer"; "media-type.flute" = "Flute"; "media-type.foil" = "Foil"; "media-type.full-cut-tabs" = "Full cut tabs"; "media-type.glass" = "Glass"; "media-type.glass-colored" = "Glass colored"; "media-type.glass-opaque" = "Glass opaque"; "media-type.glass-surfaced" = "Glass surfaced"; "media-type.glass-textured" = "Glass textured"; "media-type.gravure-cylinder" = "Gravure cylinder"; "media-type.image-setter-paper" = "Image setter paper"; "media-type.imaging-cylinder" = "Imaging cylinder"; "media-type.labels" = "Labels"; "media-type.labels-colored" = "Colored labels"; "media-type.labels-glossy" = "Glossy labels"; "media-type.labels-high-gloss" = "High gloss labels"; "media-type.labels-inkjet" = "Inkjet labels"; "media-type.labels-matte" = "Matte labels"; "media-type.labels-permanent" = "Permanent labels"; "media-type.labels-satin" = "Satin labels"; "media-type.labels-security" = "Security labels"; "media-type.labels-semi-gloss" = "Semi-gloss labels"; "media-type.laminating-foil" = "Laminating foil"; "media-type.letterhead" = "Letterhead"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal glossy"; "media-type.metal-high-gloss" = "Metal high gloss"; "media-type.metal-matte" = "Metal matte"; "media-type.metal-satin" = "Metal satin"; "media-type.metal-semi-gloss" = "Metal semi gloss"; "media-type.mounting-tape" = "Mounting tape"; "media-type.multi-layer" = "Multi layer"; "media-type.multi-part-form" = "Multi part form"; "media-type.other" = "Other"; "media-type.paper" = "Paper"; "media-type.photographic" = "Photo paper"; "media-type.photographic-archival" = "Photographic archival"; "media-type.photographic-film" = "Photo film"; "media-type.photographic-glossy" = "Glossy photo paper"; "media-type.photographic-high-gloss" = "High gloss photo paper"; "media-type.photographic-matte" = "Matte photo paper"; "media-type.photographic-satin" = "Satin photo paper"; "media-type.photographic-semi-gloss" = "Semi-gloss photo paper"; "media-type.plastic" = "Plastic"; "media-type.plastic-archival" = "Plastic archival"; "media-type.plastic-colored" = "Plastic colored"; "media-type.plastic-glossy" = "Plastic glossy"; "media-type.plastic-high-gloss" = "Plastic high gloss"; "media-type.plastic-matte" = "Plastic matte"; "media-type.plastic-satin" = "Plastic satin"; "media-type.plastic-semi-gloss" = "Plastic semi gloss"; "media-type.plate" = "Plate"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "Pre cut tabs"; "media-type.roll" = "Roll"; "media-type.screen" = "Screen"; "media-type.screen-paged" = "Screen paged"; "media-type.self-adhesive" = "Self adhesive"; "media-type.self-adhesive-film" = "Self adhesive film"; "media-type.shrink-foil" = "Shrink foil"; "media-type.single-face" = "Single face"; "media-type.single-wall" = "Single wall"; "media-type.sleeve" = "Sleeve"; "media-type.stationery" = "Stationery"; "media-type.stationery-archival" = "Stationery archival"; "media-type.stationery-coated" = "Coated paper"; "media-type.stationery-cotton" = "Stationery cotton"; "media-type.stationery-fine" = "Vellum paper"; "media-type.stationery-heavyweight" = "Heavyweight paper"; "media-type.stationery-heavyweight-coated" = "Stationery heavyweight coated"; "media-type.stationery-inkjet" = "Stationery inkjet paper"; "media-type.stationery-letterhead" = "Letterhead"; "media-type.stationery-lightweight" = "Lightweight paper"; "media-type.stationery-preprinted" = "Preprinted paper"; "media-type.stationery-prepunched" = "Punched paper"; "media-type.tab-stock" = "Tab stock"; "media-type.tractor" = "Tractor"; "media-type.transfer" = "Transfer"; "media-type.transparency" = "Transparency"; "media-type.triple-wall" = "Triple wall"; "media-type.wet-film" = "Wet film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 or US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Envelope"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Envelope"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Envelope"; "media.iso_c10_28x40mm" = "C10 Envelope"; "media.iso_c1_648x917mm" = "C1 Envelope"; "media.iso_c2_458x648mm" = "C2 Envelope"; "media.iso_c3_324x458mm" = "C3 Envelope"; "media.iso_c4_229x324mm" = "C4 Envelope"; "media.iso_c5_162x229mm" = "C5 Envelope"; "media.iso_c6_114x162mm" = "C6 Envelope"; "media.iso_c6c5_114x229mm" = "C6/C5 Envelope"; "media.iso_c7_81x114mm" = "C7 Envelope"; "media.iso_c7c6_81x162mm" = "C7/C6 Envelope"; "media.iso_c8_57x81mm" = "C8 Envelope"; "media.iso_c9_40x57mm" = "C9 Envelope"; "media.iso_dl_110x220mm" = "DL Envelope"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Envelope Chou 2"; "media.jpn_chou3_120x235mm" = "Envelope Chou 3"; "media.jpn_chou40_90x225mm" = "Envelope Chou 40"; "media.jpn_chou4_90x205mm" = "Envelope Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Envelope Kahu"; "media.jpn_kaku2_240x332mm" = "Envelope Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Reply Postcard"; "media.jpn_you4_105x235mm" = "Envelope You 4"; "media.na_a2_4.375x5.75in" = "Envelope A2"; "media.na_c5_6.5x9.5in" = "Envelope C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "European Fanfold"; "media.na_fanfold-us_11x14.875in" = "US Fanfold"; "media.na_foolscap_8.5x13in" = "Foolscap"; "media.na_invoice_5.5x8.5in" = "Statement"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US Letter (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US Letter (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Envelope Monarch"; "media.na_number-10_4.125x9.5in" = "Envelope #10"; "media.na_number-11_4.5x10.375in" = "Envelope #11"; "media.na_number-12_4.75x11in" = "Envelope #12"; "media.na_number-14_5x11.5in" = "Envelope #14"; "media.na_number-9_3.875x8.875in" = "Envelope #9"; "media.na_personal_3.625x6.5in" = "Envelope Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Envelope Invitation"; "media.om_italian_110x230mm" = "Envelope Italian"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389mm"; "media.om_postfix_114x229mm" = "Envelope Postfix"; "media.prc_10_324x458mm" = "Envelope chinese #10"; "media.prc_16k_146x215mm" = "Chinese 16k"; "media.prc_1_102x165mm" = "Envelope chinese #1"; "media.prc_2_102x176mm" = "Envelope chinese #2"; "media.prc_32k_97x151mm" = "Chinese 32k"; "media.prc_3_125x176mm" = "Envelope chinese #3"; "media.prc_4_110x208mm" = "Envelope chinese #4"; "media.prc_5_110x220mm" = "Envelope chinese #5"; "media.prc_6_120x320mm" = "Envelope chinese #6"; "media.prc_7_160x230mm" = "Envelope chinese #7"; "media.prc_8_120x309mm" = "Envelope chinese #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "not configured"; "not visible" = "not visible"; "off" = "off"; "on" = "on"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Landscape"; "orientation-requested.5" = "Reverse landscape"; "orientation-requested.6" = "Reverse portrait"; "orientation-requested.7" = "None"; "output-bin" = "Output Tray"; "output-bin.auto" = "Automatic"; "output-bin.bottom" = "Bottom"; "output-bin.center" = "Center"; "output-bin.face-down" = "Face down"; "output-bin.face-up" = "Face up"; "output-bin.large-capacity" = "Large capacity"; "output-bin.left" = "Left"; "output-bin.mailbox-1" = "Mailbox 1"; "output-bin.mailbox-10" = "Mailbox 10"; "output-bin.mailbox-2" = "Mailbox 2"; "output-bin.mailbox-3" = "Mailbox 3"; "output-bin.mailbox-4" = "Mailbox 4"; "output-bin.mailbox-5" = "Mailbox 5"; "output-bin.mailbox-6" = "Mailbox 6"; "output-bin.mailbox-7" = "Mailbox 7"; "output-bin.mailbox-8" = "Mailbox 8"; "output-bin.mailbox-9" = "Mailbox 9"; "output-bin.middle" = "Middle"; "output-bin.my-mailbox" = "My mailbox"; "output-bin.rear" = "Rear"; "output-bin.right" = "Right"; "output-bin.side" = "Side"; "output-bin.stacker-1" = "Stacker 1"; "output-bin.stacker-10" = "Stacker 10"; "output-bin.stacker-2" = "Stacker 2"; "output-bin.stacker-3" = "Stacker 3"; "output-bin.stacker-4" = "Stacker 4"; "output-bin.stacker-5" = "Stacker 5"; "output-bin.stacker-6" = "Stacker 6"; "output-bin.stacker-7" = "Stacker 7"; "output-bin.stacker-8" = "Stacker 8"; "output-bin.stacker-9" = "Stacker 9"; "output-bin.top" = "Top"; "output-bin.tray-1" = "Tray 1"; "output-bin.tray-10" = "Tray 10"; "output-bin.tray-2" = "Tray 2"; "output-bin.tray-3" = "Tray 3"; "output-bin.tray-4" = "Tray 4"; "output-bin.tray-5" = "Tray 5"; "output-bin.tray-6" = "Tray 6"; "output-bin.tray-7" = "Tray 7"; "output-bin.tray-8" = "Tray 8"; "output-bin.tray-9" = "Tray 9"; "print-color-mode" = "Print Mode"; "print-color-mode.auto" = "Automatic"; "print-color-mode.auto-monochrome" = "Auto monochrome"; "print-color-mode.bi-level" = "Text"; "print-color-mode.color" = "Color"; "print-color-mode.highlight" = "Highlight"; "print-color-mode.monochrome" = "Monochrome"; "print-color-mode.process-bi-level" = "Process Text"; "print-color-mode.process-monochrome" = "Process monochrome"; "print-content-optimize" = "Optimize For"; "print-content-optimize.auto" = "Automatic"; "print-content-optimize.graphic" = "Graphics"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text and graphics"; "print-darkness" = "Print Darkness"; "print-quality" = "Print Quality"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Best"; "print-scaling" = "Scaling"; "print-scaling.auto" = "Automatic"; "print-scaling.auto-fit" = "Auto-fit"; "print-scaling.fill" = "Fill"; "print-scaling.fit" = "Fit"; "print-scaling.none" = "None"; "print-speed" = "Print Speed"; "printer-resolution" = "Resolution"; "printer-state-reasons.cover-open" = "Cover open."; "printer-state-reasons.door-open" = "Door open."; "printer-state-reasons.identify-printer-requested" = "Identify printer."; "printer-state-reasons.input-tray-missing" = "Paper tray missing."; "printer-state-reasons.marker-supply-empty" = "Out of ink."; "printer-state-reasons.marker-supply-low" = "Low ink."; "printer-state-reasons.marker-waste-almost-full" = "Waste bin almost full."; "printer-state-reasons.marker-waste-full" = "Waste bin full."; "printer-state-reasons.media-empty" = "Out of paper."; "printer-state-reasons.media-jam" = "Paper jam."; "printer-state-reasons.media-low" = "Replace paper soon."; "printer-state-reasons.media-needed" = "Load paper."; "printer-state-reasons.none" = "Ready."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "See printer."; "printer-state-reasons.spool-area-full" = "Printer busy."; "printer-state-reasons.toner-empty" = "Out of toner."; "printer-state-reasons.toner-low" = "Toner low."; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "sides" = "2-Sided Printing"; "sides.one-sided" = "Off"; "sides.two-sided-long-edge" = "On (portrait)"; "sides.two-sided-short-edge" = "On (landscape)"; "unable to join" = "unable to join"; "yesterday at %02d:%02d:%02d" = "yesterday at %02d:%02d:%02d"; "Åland Islands" = "Åland Islands"; pappl-1.4.9/pappl/strings/nb-NO_strings.h000066400000000000000000001533651476704353100203300ustar00rootroot00000000000000static const char *nb_NO_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Avbryt alle jobber.\";\n" "\" -c COPIES\" = \" -c Kopier\";\n" "\" -d PRINTER Specify printer.\" = \" -d PRINTER Angi skriver.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j JOB-ID Specify job ID (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m DRIVER-NAME Specify driver (add/modify).\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n COPIES Specify number of copies (submit).\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (default)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAME=VALUE Specify option (add,modify,server,submit).\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 til 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 til 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOCATION'\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZATION'\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='UNIT/SECTION'\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Specify ipp: or ipps: printer/server.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v DEVICE-URI Specify socket: or usb: device (add/modify).\";\n" "\" add PRINTER Add a printer.\" = \" add PRINTER Add a printer.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Automatically add supported printers.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Cancel one or more jobs.\";\n" "\" default Set the default printer.\" = \" default Set the default printer.\";\n" "\" delete Delete a printer.\" = \" delete Delete a printer.\";\n" "\" devices List devices.\" = \" devices List devices.\";\n" "\" drivers List drivers.\" = \" drivers List drivers.\";\n" "\" jobs List jobs.\" = \" jobs List jobs.\";\n" "\" modify Modify a printer.\" = \" modify Modify a printer.\";\n" "\" options List printer options.\" = \" options List printer options.\";\n" "\" pause Pause printing for a printer.\" = \" pause Pause printing for a printer.\";\n" "\" printers List printers.\" = \" printers List printers.\";\n" "\" resume Resume printing for a printer.\" = \" resume Resume printing for a printer.\";\n" "\" server Run a server.\" = \" server Run a server.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Shutdown a running server.\";\n" "\" status Show server/printer/job status.\" = \" status Show server/printer/job status.\";\n" "\" submit Submit a file for printing.\" = \" submit Submit a file for printing.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d at %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d days ago at %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d inches/sec\";\n" "\"%d job\" = \"%d job\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %dmm\";\n" "\"%ddpi\" = \"%ddpi\";\n" "\"%dx%ddpi\" = \"%dx%ddpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g\\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s (%s%s)\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) from %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Media\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Bad 'server-port' value.\";\n" "\"%s: Bad job ID.\" = \"%s: Bad job ID.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Bad printer URI '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Cannot specify more than one sub-command.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Empty print file received on the standard input.\";\n" "\"%s: Failed to create a system.\" = \"%s: Failed to create a system.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Missing '-d PRINTER'.\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Missing '-m DRIVER-NAME'.\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Missing '-v DEVICE-URI'.\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Missing copy count after '-n'.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Missing device URI after '-v'.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Missing driver name after '-m'.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Missing filename after '--'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Missing hostname after '-h'.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Missing job ID after '-j'.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: Missing option(s) after '-o'.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Missing printer URI after '-u'.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Missing printer name after '-d'.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Missing space after '-o'.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Missing title after '-t'.\";\n" "\"%s: No default printer available.\" = \"%s: No default printer available.\";\n" "\"%s: No files to print.\" = \"%s: No files to print.\";\n" "\"%s: Server is not running.\" = \"%s: Server is not running.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Sub-command '%s' does not accept files.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Sub-command 'autoadd' is not supported.\";\n" "\"%s: Too many files.\" = \"%s: Too many files.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Unable to access '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Unable to add printer: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Unable to cancel job: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Unable to connect to printer at '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Unable to connect to server: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Unable to create temporary file: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Unable to delete printer: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Unable to get available devices: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Unable to get information for '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Unable to get information for printer: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Unable to get printer options: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Unable to modify printer: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Unable to pause printer: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Unable to print '%s': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Unable to resume printer: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Unable to set default printer: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Unable to shutdown server: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Unable to start server: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Unable to write to temporary file: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Unknown option '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Unknown option '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Unknown sub-command '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Unsupported URI scheme '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Warning - user credentials are not supported in URIs.\";\n" "\", Borderless\" = \", Borderless\";\n" "\"A printer with that name already exists.\" = \"A printer with that name already exists.\";\n" "\"Aborted %s\" = \"Aborted %s\";\n" "\"Add Printer\" = \"Legg til skriver\";\n" "\"Admin Group\" = \"Administratorgruppe\";\n" "\"Afghanistan\" = \"Afghanistan\";\n" "\"Albania\" = \"Albania\";\n" "\"Algeria\" = \"Algerie\";\n" "\"American Samoa\" = \"American Samoa\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarctica\";\n" "\"Antigua and Barbuda\" = \"Antigua and Barbuda\";\n" "\"Argentina\" = \"Argentina\";\n" "\"Armenia\" = \"Armenia\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australia\";\n" "\"Austria\" = \"Austria\";\n" "\"Auto\" = \"Auto\";\n" "\"Auto-Detect Driver\" = \"Auto-Detect Driver\";\n" "\"Azerbaijan\" = \"Azerbaijan\";\n" "\"Bad administration group.\" = \"Bad administration group.\";\n" "\"Bad port number.\" = \"Bad port number.\";\n" "\"Bad print group.\" = \"Bad print group.\";\n" "\"Bad printer defaults.\" = \"Bad printer defaults.\";\n" "\"Bahamas\" = \"Bahamas\";\n" "\"Bahrain\" = \"Bahrain\";\n" "\"Bangladesh\" = \"Bangladesh\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Belarus\";\n" "\"Belgium\" = \"Belgium\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermuda\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivia (Plurinational State of)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius and Saba\";\n" "\"Borderless\" = \"Borderless\";\n" "\"Bosnia and Herzegovina\" = \"Bosnia and Herzegovina\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Bouvet Island\";\n" "\"Brazil\" = \"Brazil\";\n" "\"British Indian Ocean Territory\" = \"British Indian Ocean Territory\";\n" "\"Brunei Darussalam\" = \"Brunei Darussalam\";\n" "\"Bulgaria\" = \"Bulgaria\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Cabo Verde\";\n" "\"Cambodia\" = \"Cambodia\";\n" "\"Cameroon\" = \"Cameroon\";\n" "\"Canada\" = \"Canada\";\n" "\"Cancel All Jobs\" = \"Avbryt alle jobber\";\n" "\"Cancel Job\" = \"Avbryt jobb\";\n" "\"Canceled %s\" = \"Canceled %s\";\n" "\"Canceling\" = \"Canceling\";\n" "\"Cayman Islands\" = \"Cayman Islands\";\n" "\"Central African Republic\" = \"Central African Republic\";\n" "\"Certificate created.\" = \"Certificate created.\";\n" "\"Certificate installed.\" = \"Certificate installed.\";\n" "\"Certificate request created.\" = \"Certificate request created.\";\n" "\"Chad\" = \"Chad\";\n" "\"Change Access Password\" = \"Endre administratorpassord\";\n" "\"Change Log Level\" = \"Endre loggføringsnivå\";\n" "\"Change Network Settings\" = \"Change Network Settings\";\n" "\"Change Wi-Fi Network\" = \"Endre Wi-Fi-nettverk\";\n" "\"Changes Saved.\" = \"Endringer lagret.\";\n" "\"Changes saved.\" = \"Endringer lagret.\";\n" "\"Chile\" = \"Chile\";\n" "\"China\" = \"Kina\";\n" "\"Christmas Island\" = \"Christmas Island\";\n" "\"City/Locality\" = \"City/Locality\";\n" "\"Cocos (Keeling) Islands\" = \"Cocos (Keeling) Islands\";\n" "\"Colombia\" = \"Colombia\";\n" "\"Comoros\" = \"Comoros\";\n" "\"Completed %s\" = \"Completed %s\";\n" "\"Configuration\" = \"Oppsett\";\n" "\"Configure Media\" = \"Configure Media\";\n" "\"Confirm Cancel All\" = \"Confirm Cancel All\";\n" "\"Confirm Delete Printer\" = \"Confirm Delete Printer\";\n" "\"Congo\" = \"Congo\";\n" "\"Congo, Democratic Republic of the\" = \"Congo, Democratic Republic of the\";\n" "\"Contact\" = \"Kontakt\";\n" "\"Cook Islands\" = \"Cook Islands\";\n" "\"Costa Rica\" = \"Costa Rica\";\n" "\"Create Certificate Signing Request\" = \"Create Certificate Signing Request\";\n" "\"Create New Certificate\" = \"Opprett nytt sertifikat\";\n" "\"Create New TLS Certificate\" = \"Create New TLS Certificate\";\n" "\"Create TLS Certificate Request\" = \"Create TLS Certificate Request\";\n" "\"Croatia\" = \"Kroatia\";\n" "\"Cuba\" = \"Kuba\";\n" "\"Curaçao\" = \"Curaçao\";\n" "\"Current Password\" = \"Nåværende passord\";\n" "\"Custom Size\" = \"Egendefinert størrelse\";\n" "\"Cyprus\" = \"Kypros\";\n" "\"Czechia\" = \"Czechia\";\n" "\"Côte d'Ivoire\" = \"Côte d'Ivoire\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP w/Manual Address\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Service Name\";\n" "\"Debugging\" = \"Debugging\";\n" "\"Default printer set.\" = \"Default printer set.\";\n" "\"Delete\" = \"Slett\";\n" "\"Delete Printer\" = \"Slett skriver\";\n" "\"Denmark\" = \"Danmark\";\n" "\"Djibouti\" = \"Djibouti\";\n" "\"Domain Name\" = \"Domain Name\";\n" "\"Dominica\" = \"Dominica\";\n" "\"Dominican Republic\" = \"Dominican Republic\";\n" "\"Download Certificate Request File\" = \"Download Certificate Request File\";\n" "\"Ecuador\" = \"Ecuador\";\n" "\"Egypt\" = \"Egypt\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Equatorial Guinea\";\n" "\"Eritrea\" = \"Eritrea\";\n" "\"Errors\" = \"Errors\";\n" "\"Estonia\" = \"Estonia\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Ethiopia\";\n" "\"Falkland Islands (Malvinas)\" = \"Falkland Islands (Malvinas)\";\n" "\"Faroe Islands\" = \"Faroe Islands\";\n" "\"Fatal Errors/Conditions\" = \"Fatal Errors/Conditions\";\n" "\"Fiji\" = \"Fiji\";\n" "\"Finland\" = \"Finland\";\n" "\"France\" = \"France\";\n" "\"French Guiana\" = \"French Guiana\";\n" "\"French Polynesia\" = \"French Polynesia\";\n" "\"French Southern Territories\" = \"French Southern Territories\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Georgia\";\n" "\"Germany\" = \"Germany\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Greece\";\n" "\"Greenland\" = \"Greenland\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Group changes saved.\";\n" "\"Guadeloupe\" = \"Guadeloupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Guinea\";\n" "\"Guinea-Bissau\" = \"Guinea-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Island and McDonald Islands\";\n" "\"Hidden SSID\" = \"Hidden SSID\";\n" "\"Hold Job\" = \"Hold Job\";\n" "\"Hold New Jobs\" = \"Hold New Jobs\";\n" "\"Holding new jobs.\" = \"Holding new jobs.\";\n" "\"Holy See\" = \"Holy See\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Hostname\";\n" "\"Human-Readable Location\" = \"Human-Readable Location\";\n" "\"Hungary\" = \"Hungary\";\n" "\"IPv4 Address\" = \"IPv4 Address\";\n" "\"IPv4 Configuration\" = \"IPv4 Configuration\";\n" "\"IPv4 Gateway\" = \"IPv4 Gateway\";\n" "\"IPv4 Netmask\" = \"IPv4 Netmask\";\n" "\"IPv6 Address\" = \"IPv6 Address\";\n" "\"IPv6 Configuration\" = \"IPv6 Configuration\";\n" "\"IPv6 Link-Local\" = \"IPv6 Link-Local\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Prefix Length\";\n" "\"Iceland\" = \"Iceland\";\n" "\"Identify Printer\" = \"Identify Printer\";\n" "\"India\" = \"India\";\n" "\"Indonesia\" = \"Indonesia\";\n" "\"Informational\" = \"Informational\";\n" "\"Install TLS Certificate\" = \"Installer TLS-sertifikat\";\n" "\"Invalid IPv4 address.\" = \"Invalid IPv4 address.\";\n" "\"Invalid IPv4 netmask.\" = \"Invalid IPv4 netmask.\";\n" "\"Invalid IPv6 address.\" = \"Invalid IPv6 address.\";\n" "\"Invalid IPv6 prefix length.\" = \"Invalid IPv6 prefix length.\";\n" "\"Invalid Job ID.\" = \"Invalid Job ID.\";\n" "\"Invalid certificate or private key.\" = \"Ugyldig sertifikat eller privat nøkkel.\";\n" "\"Invalid form data.\" = \"Ugyldig skjemadata.\";\n" "\"Invalid form submission.\" = \"Ugyldig skjemainnsendelse.\";\n" "\"Invalid job ID.\" = \"Ugyldig jobb-ID.\";\n" "\"Invalid network configuration.\" = \"Invalid network configuration.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (Islamic Republic of)\";\n" "\"Iraq\" = \"Irak\";\n" "\"Ireland\" = \"Irland\";\n" "\"Isle of Man\" = \"Isle of Man\";\n" "\"Israel\" = \"Israel\";\n" "\"Italy\" = \"Italia\";\n" "\"Jamaica\" = \"Jamaica\";\n" "\"Japan\" = \"Japan\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Jobb #\";\n" "\"Job canceled.\" = \"Job canceled.\";\n" "\"Job held.\" = \"Job held.\";\n" "\"Job released.\" = \"Job released.\";\n" "\"Jobs\" = \"Jobber\";\n" "\"Joining Wi-Fi Network\" = \"Joining Wi-Fi Network\";\n" "\"Jordan\" = \"Jordan\";\n" "\"Kazakhstan\" = \"Kazakhstan\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Korea (Democratic People's Republic of)\";\n" "\"Korea, Republic of\" = \"Korea, Republic of\";\n" "\"Kuwait\" = \"Kuwait\";\n" "\"Kyrgyzstan\" = \"Kyrgyzstan\";\n" "\"Landscape\" = \"Liggende\";\n" "\"Lao People's Democratic Republic\" = \"Lao People's Democratic Republic\";\n" "\"Latvia\" = \"Latvia\";\n" "\"Lebanon\" = \"Lebanon\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Nivå\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libya\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Lithuania\";\n" "\"Location\" = \"Location\";\n" "\"Log Level\" = \"Loggføringsnivå\";\n" "\"Logging\" = \"Logging\";\n" "\"Logs\" = \"Logger\";\n" "\"Luxembourg\" = \"Luxembourg\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagascar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malaysia\";\n" "\"Maldives\" = \"Maldives\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Manual Configuration\";\n" "\"Marshall Islands\" = \"Marshall Islands\";\n" "\"Martinique\" = \"Martinique\";\n" "\"Mauritania\" = \"Mauritania\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Media\";\n" "\"Mexico\" = \"Mexico\";\n" "\"Micronesia (Federated States of)\" = \"Micronesia (Federated States of)\";\n" "\"Missing action.\" = \"Missing action.\";\n" "\"Missing job ID.\" = \"Missing job ID.\";\n" "\"Missing network name.\" = \"Missing network name.\";\n" "\"Missing private key.\" = \"Mangler privat nøkkel.\";\n" "\"Moldova, Republic of\" = \"Moldova, Republic of\";\n" "\"Monaco\" = \"Monaco\";\n" "\"Mongolia\" = \"Mongolia\";\n" "\"Montenegro\" = \"Montenegro\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Marokko\";\n" "\"Mozambique\" = \"Mozambique\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Navn\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Nederland\";\n" "\"Network\" = \"Nettverk\";\n" "\"Network Printer\" = \"Nettverksskriver\";\n" "\"Networking\" = \"Networking\";\n" "\"New Caledonia\" = \"New Caledonia\";\n" "\"New Zealand\" = \"New Zealand\";\n" "\"Nicaragua\" = \"Nicaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"No default printer set.\";\n" "\"No jobs in history.\" = \"Ingen jobber i historikk.\";\n" "\"Norfolk Island\" = \"Norfolk Island\";\n" "\"North Macedonia\" = \"North Macedonia\";\n" "\"Northern Mariana Islands\" = \"Northern Mariana Islands\";\n" "\"Norway\" = \"Norway\";\n" "\"Not set\" = \"Not set\";\n" "\"Off\" = \"Off\";\n" "\"Offset\" = \"Offset\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Options:\";\n" "\"Organization\" = \"Organisasjon\";\n" "\"Organization Name\" = \"Organisasjonsnavn\";\n" "\"Other Settings\" = \"Andre innstillinger\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palestine, State of\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua New Guinea\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Passord\";\n" "\"Password changed.\" = \"Passord endret.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\";\n" "\"Passwords do not match.\" = \"Passordene samsvarer ikke.\";\n" "\"Pause Printing\" = \"Pause Printing\";\n" "\"Peru\" = \"Peru\";\n" "\"Philippines\" = \"Philippines\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Skriv inn vertsnavnet eller IP-adressen til skriveren.\";\n" "\"Please enter a printer name.\" = \"Skriv inn et skrivernavn.\";\n" "\"Please select a device.\" = \"Velg en enhet.\";\n" "\"Please select a driver.\" = \"Please select a driver.\";\n" "\"Please select a valid log level.\" = \"Velg et gyldig loggføringsnivå.\";\n" "\"Poland\" = \"Polen\";\n" "\"Portrait\" = \"Stående\";\n" "\"Portugal\" = \"Portugal\";\n" "\"Primary DNS\" = \"Primary DNS\";\n" "\"Print Group\" = \"Skrivergruppe\";\n" "\"Print Test Page\" = \"Skriv ut testside\";\n" "\"Print job options:\" = \"Print job options:\";\n" "\"Printer identified.\" = \"Skriver identifisert.\";\n" "\"Printer is currently active.\" = \"Skriveren er i bruk.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Printer names must start with a letter or underscore and cannot contain special characters.\";\n" "\"Printer options:\" = \"Skriverinnstillinger:\";\n" "\"Printer paused.\" = \"Skriver satt på pause.\";\n" "\"Printer pausing.\" = \"Skriver tar pause.\";\n" "\"Printer resuming.\" = \"Skriver gjenopptar utskrift.\";\n" "\"Printers\" = \"Skrivere\";\n" "\"Printing Defaults\" = \"Utskriftsforvalg\";\n" "\"Puerto Rico\" = \"Puerto Rico\";\n" "\"Qatar\" = \"Qatar\";\n" "\"Queued %s\" = \"Queued %s\";\n" "\"Release Held New Jobs\" = \"Release Held New Jobs\";\n" "\"Release Job\" = \"Release Job\";\n" "\"Released held new jobs.\" = \"Released held new jobs.\";\n" "\"Reprint Job\" = \"Skriv ut jobb igjen\";\n" "\"Reprinted job.\" = \"Reprinted job.\";\n" "\"Resume Printing\" = \"Fortsett utskrift\";\n" "\"Reverse Landscape\" = \"Omvendt liggende\";\n" "\"Reverse Portrait\" = \"Omvendt stående\";\n" "\"Romania\" = \"Romania\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Running, %s since %s%s.\";\n" "\"Russian Federation\" = \"Russian Federation\";\n" "\"Rwanda\" = \"Rwanda\";\n" "\"Réunion\" = \"Réunion\";\n" "\"Saint Barthélemy\" = \"Saint Barthélemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Saint Helena, Ascension and Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts and Nevis\";\n" "\"Saint Lucia\" = \"Saint Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (French part)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre and Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint Vincent and the Grenadines\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Sao Tome and Principe\";\n" "\"Saudi Arabia\" = \"Saudi Arabia\";\n" "\"Save Changes\" = \"Save Changes\";\n" "\"Secondary DNS\" = \"Secondary DNS\";\n" "\"Security\" = \"Security\";\n" "\"Select Driver\" = \"Select Driver\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbia\";\n" "\"Server is not running.\" = \"Tjeneren kjører ikke.\";\n" "\"Set Access Password\" = \"Sett tilgangspassord\";\n" "\"Set as Default\" = \"Sett som forvalg\";\n" "\"Seychelles\" = \"Seychelles\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapore\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (Dutch part)\";\n" "\"Slovakia\" = \"Slovakia\";\n" "\"Slovenia\" = \"Slovenia\";\n" "\"Solomon Islands\" = \"Solomon Islands\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"South Africa\";\n" "\"South Georgia and the South Sandwich Islands\" = \"South Georgia and the South Sandwich Islands\";\n" "\"South Sudan\" = \"South Sudan\";\n" "\"Spain\" = \"Spain\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Started %s\";\n" "\"Status\" = \"Status\";\n" "\"Sub-commands:\" = \"Sub-commands:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Supplies\";\n" "\"Suriname\" = \"Suriname\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard and Jan Mayen\";\n" "\"Sweden\" = \"Sweden\";\n" "\"Switzerland\" = \"Switzerland\";\n" "\"Syrian Arab Republic\" = \"Syrian Arab Republic\";\n" "\"Taiwan, Province of China\" = \"Taiwan, Province of China\";\n" "\"Tajikistan\" = \"Tajikistan\";\n" "\"Tanzania, United Republic of\" = \"Tanzania, United Republic of\";\n" "\"Test page printed.\" = \"Test page printed.\";\n" "\"Thailand\" = \"Thailand\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad and Tobago\";\n" "\"Tunisia\" = \"Tunisia\";\n" "\"Turkey\" = \"Turkey\";\n" "\"Turkmenistan\" = \"Turkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Turks and Caicos Islands\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ukraine\";\n" "\"Unable to access test print file.\" = \"Unable to access test print file.\";\n" "\"Unable to copy print job.\" = \"Unable to copy print job.\";\n" "\"Unable to create certificate request.\" = \"Unable to create certificate request.\";\n" "\"Unable to create certificate.\" = \"Kunne ikke opprette sertifikat.\";\n" "\"Unable to create test print job.\" = \"Unable to create test print job.\";\n" "\"Unable to identify printer.\" = \"Unable to identify printer.\";\n" "\"Unable to lookup address.\" = \"Unable to lookup address.\";\n" "\"Unable to use that driver.\" = \"Unable to use that driver.\";\n" "\"United Arab Emirates\" = \"United Arab Emirates\";\n" "\"United Kingdom\" = \"United Kingdom\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"United Kingdom of Great Britain and Northern Ireland\";\n" "\"United States Minor Outlying Islands\" = \"United States Minor Outlying Islands\";\n" "\"United States of America\" = \"United States of America\";\n" "\"Unknown\" = \"Ukjent\";\n" "\"Unknown action.\" = \"Ukjent handling.\";\n" "\"Unknown form action.\" = \"Ukjent skjemahandling.\";\n" "\"Unknown form request.\" = \"Ukjent skjemaforespørsel.\";\n" "\"Updating Network Configuration\" = \"Updating Network Configuration\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\";\n" "\"Use My Position\" = \"Use My Position\";\n" "\"Users\" = \"Brukere\";\n" "\"Uzbekistan\" = \"Uzbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela (Bolivarian Republic of)\";\n" "\"Version %s\" = \"Version %s\";\n" "\"Viet Nam\" = \"Viet Nam\";\n" "\"View Logs\" = \"Vis loggføring\";\n" "\"Virgin Islands (British)\" = \"Virgin Islands (British)\";\n" "\"Virgin Islands (U.S.)\" = \"Virgin Islands (U.S.)\";\n" "\"Wallis and Futuna\" = \"Wallis and Futuna\";\n" "\"Warning\" = \"Advarsel\";\n" "\"Western Sahara\" = \"Western Sahara\";\n" "\"Wi-Fi Configuration\" = \"Wi-Fi-oppsett\";\n" "\"Wi-Fi Network\" = \"Wi-Fi-nettverk\";\n" "\"Width\" = \"Bredde\";\n" "\"Wrong old password.\" = \"Feil gammelt passord.\";\n" "\"Yemen\" = \"Yemen\";\n" "\"Zambia\" = \"Zambia\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"at %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Antall kopier\";\n" "\"default printer\" = \"forvalgt skriver\";\n" "\"finishings\" = \"Finisher\";\n" "\"finishings.10\" = \"Fold\";\n" "\"finishings.100\" = \"Z fold\";\n" "\"finishings.101\" = \"Engineering Z fold\";\n" "\"finishings.11\" = \"Cut\";\n" "\"finishings.12\" = \"Bale\";\n" "\"finishings.13\" = \"Booklet maker\";\n" "\"finishings.15\" = \"Coat\";\n" "\"finishings.16\" = \"Laminate\";\n" "\"finishings.20\" = \"Staple top left\";\n" "\"finishings.21\" = \"Staple bottom left\";\n" "\"finishings.22\" = \"Staple top right\";\n" "\"finishings.23\" = \"Staple bottom right\";\n" "\"finishings.24\" = \"Edge stitch left\";\n" "\"finishings.25\" = \"Edge stitch top\";\n" "\"finishings.26\" = \"Edge stitch right\";\n" "\"finishings.27\" = \"Edge stitch bottom\";\n" "\"finishings.28\" = \"2 staples on left\";\n" "\"finishings.29\" = \"2 staples on top\";\n" "\"finishings.3\" = \"None\";\n" "\"finishings.30\" = \"2 staples on right\";\n" "\"finishings.31\" = \"2 staples on bottom\";\n" "\"finishings.32\" = \"3 staples on left\";\n" "\"finishings.33\" = \"3 staples on top\";\n" "\"finishings.34\" = \"3 staples on right\";\n" "\"finishings.35\" = \"3 staples on bottom\";\n" "\"finishings.4\" = \"Staple\";\n" "\"finishings.5\" = \"Punch\";\n" "\"finishings.50\" = \"Bind left\";\n" "\"finishings.51\" = \"Bind top\";\n" "\"finishings.52\" = \"Bind right\";\n" "\"finishings.53\" = \"Bind bottom\";\n" "\"finishings.6\" = \"Cover\";\n" "\"finishings.60\" = \"Cut after every page\";\n" "\"finishings.61\" = \"Cut after every document\";\n" "\"finishings.62\" = \"Cut after every set\";\n" "\"finishings.63\" = \"Cut after job\";\n" "\"finishings.7\" = \"Bind\";\n" "\"finishings.70\" = \"Punch top left\";\n" "\"finishings.71\" = \"Punch bottom left\";\n" "\"finishings.72\" = \"Punch top right\";\n" "\"finishings.73\" = \"Punch bottom right\";\n" "\"finishings.74\" = \"2-hole punch left\";\n" "\"finishings.75\" = \"2-hole punch top\";\n" "\"finishings.76\" = \"2-hole punch right\";\n" "\"finishings.77\" = \"2-hole punch bottom\";\n" "\"finishings.78\" = \"3-hole punch left\";\n" "\"finishings.79\" = \"3-hole punch top\";\n" "\"finishings.8\" = \"Saddle stitch\";\n" "\"finishings.80\" = \"3-hole punch right\";\n" "\"finishings.81\" = \"3-hole punch bottom\";\n" "\"finishings.82\" = \"4-hole punch left\";\n" "\"finishings.83\" = \"4-hole punch top\";\n" "\"finishings.84\" = \"4-hole punch right\";\n" "\"finishings.85\" = \"4-hole punch bottom\";\n" "\"finishings.86\" = \"Multi-hole punch left\";\n" "\"finishings.87\" = \"Multi-hole punch top\";\n" "\"finishings.88\" = \"Multi-hole punch right\";\n" "\"finishings.89\" = \"Multi-hole punch bottom\";\n" "\"finishings.9\" = \"Edge stitch\";\n" "\"finishings.90\" = \"Accordion fold\";\n" "\"finishings.91\" = \"Double gate fold\";\n" "\"finishings.92\" = \"Gate fold\";\n" "\"finishings.93\" = \"Half fold\";\n" "\"finishings.94\" = \"Half Z fold\";\n" "\"finishings.95\" = \"Left gate fold\";\n" "\"finishings.96\" = \"Letter fold\";\n" "\"finishings.97\" = \"Parallel fold\";\n" "\"finishings.98\" = \"Poster fold\";\n" "\"finishings.99\" = \"Right gate fold\";\n" "\"holding new jobs\" = \"holding new jobs\";\n" "\"job-state-reasons.aborted-by-system\" = \"Stopping.\";\n" "\"job-state-reasons.compression-error\" = \"Decompression error.\";\n" "\"job-state-reasons.document-format-error\" = \"Document format error.\";\n" "\"job-state-reasons.document-password-error\" = \"Document password error.\";\n" "\"job-state-reasons.document-permission-error\" = \"Document permission error.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Document unprintable error.\";\n" "\"job-state-reasons.errors-detected\" = \"Errors detected.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Canceled at printer.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Canceled by user.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Printed.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Printed with errors.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Printed with warnings.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Insufficient data.\";\n" "\"job-state-reasons.job-fetchable\" = \"Fetchable.\";\n" "\"job-state-reasons.job-incoming\" = \"Incoming.\";\n" "\"job-state-reasons.job-printing\" = \"Printing.\";\n" "\"job-state-reasons.job-queued\" = \"Preparing to print.\";\n" "\"job-state-reasons.job-spooling\" = \"Spooling.\";\n" "\"job-state-reasons.none\" = \"Pending.\";\n" "\"job-state-reasons.printer-stopped\" = \"Printer offline.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Printer partially stopped.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Stopping.\";\n" "\"job-state-reasons.queued-in-device\" = \"Ready.\";\n" "\"job-state-reasons.warnings-detected\" = \"Warnings detected.\";\n" "\"job-state.3\" = \"Pending\";\n" "\"job-state.4\" = \"Held\";\n" "\"job-state.5\" = \"Processing\";\n" "\"job-state.6\" = \"Stopped\";\n" "\"job-state.7\" = \"Canceled\";\n" "\"job-state.8\" = \"Aborted\";\n" "\"job-state.9\" = \"Completed\";\n" "\"joining\" = \"joining\";\n" "\"media\" = \"Media\";\n" "\"media-col\" = \"Media\";\n" "\"media-size\" = \"Media Size\";\n" "\"media-size-name\" = \"Media Size\";\n" "\"media-source\" = \"Input Tray\";\n" "\"media-source.alternate\" = \"Alternate\";\n" "\"media-source.alternate-roll\" = \"Alternate roll\";\n" "\"media-source.auto\" = \"Automatic\";\n" "\"media-source.bottom\" = \"Bottom\";\n" "\"media-source.by-pass-tray\" = \"Multipurpose tray\";\n" "\"media-source.center\" = \"Center\";\n" "\"media-source.disc\" = \"Disc\";\n" "\"media-source.envelope\" = \"Envelope\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Large capacity\";\n" "\"media-source.left\" = \"Left\";\n" "\"media-source.main\" = \"Main\";\n" "\"media-source.main-roll\" = \"Main roll\";\n" "\"media-source.manual\" = \"Manual\";\n" "\"media-source.middle\" = \"Middle\";\n" "\"media-source.photo\" = \"Photo\";\n" "\"media-source.rear\" = \"Rear\";\n" "\"media-source.right\" = \"Right\";\n" "\"media-source.roll-1\" = \"Roll 1\";\n" "\"media-source.roll-10\" = \"Roll 10\";\n" "\"media-source.roll-2\" = \"Roll 2\";\n" "\"media-source.roll-3\" = \"Roll 3\";\n" "\"media-source.roll-4\" = \"Roll 4\";\n" "\"media-source.roll-5\" = \"Roll 5\";\n" "\"media-source.roll-6\" = \"Roll 6\";\n" "\"media-source.roll-7\" = \"Roll 7\";\n" "\"media-source.roll-8\" = \"Roll 8\";\n" "\"media-source.roll-9\" = \"Roll 9\";\n" "\"media-source.side\" = \"Side\";\n" "\"media-source.top\" = \"Top\";\n" "\"media-source.tray-1\" = \"Tray 1\";\n" "\"media-source.tray-10\" = \"Tray 10\";\n" "\"media-source.tray-11\" = \"Tray 11\";\n" "\"media-source.tray-12\" = \"Tray 12\";\n" "\"media-source.tray-13\" = \"Tray 13\";\n" "\"media-source.tray-14\" = \"Tray 14\";\n" "\"media-source.tray-15\" = \"Tray 15\";\n" "\"media-source.tray-16\" = \"Tray 16\";\n" "\"media-source.tray-17\" = \"Tray 17\";\n" "\"media-source.tray-18\" = \"Tray 18\";\n" "\"media-source.tray-19\" = \"Tray 19\";\n" "\"media-source.tray-2\" = \"Tray 2\";\n" "\"media-source.tray-20\" = \"Tray 20\";\n" "\"media-source.tray-3\" = \"Tray 3\";\n" "\"media-source.tray-4\" = \"Tray 4\";\n" "\"media-source.tray-5\" = \"Tray 5\";\n" "\"media-source.tray-6\" = \"Tray 6\";\n" "\"media-source.tray-7\" = \"Tray 7\";\n" "\"media-source.tray-8\" = \"Tray 8\";\n" "\"media-source.tray-9\" = \"Tray 9\";\n" "\"media-tracking\" = \"Media Tracking\";\n" "\"media-tracking.continuous\" = \"Continuous\";\n" "\"media-tracking.gap\" = \"Gap\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Media Type\";\n" "\"media-type.aluminum\" = \"Aluminum\";\n" "\"media-type.auto\" = \"Automatic\";\n" "\"media-type.back-print-film\" = \"Back print film\";\n" "\"media-type.cardboard\" = \"Cardboard\";\n" "\"media-type.cardstock\" = \"Cardstock\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Continuous\";\n" "\"media-type.continuous-long\" = \"Continuous long\";\n" "\"media-type.continuous-short\" = \"Continuous short\";\n" "\"media-type.corrugated-board\" = \"Corrugated board\";\n" "\"media-type.disc\" = \"Optical disc\";\n" "\"media-type.disc-glossy\" = \"Glossy optical disc\";\n" "\"media-type.disc-high-gloss\" = \"High gloss optical disc\";\n" "\"media-type.disc-matte\" = \"Matte optical disc\";\n" "\"media-type.disc-satin\" = \"Satin optical disc\";\n" "\"media-type.disc-semi-gloss\" = \"Semi-gloss optical disc\";\n" "\"media-type.double-wall\" = \"Double wall\";\n" "\"media-type.dry-film\" = \"Dry film\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Embossing foil\";\n" "\"media-type.end-board\" = \"End board\";\n" "\"media-type.envelope\" = \"Envelope\";\n" "\"media-type.envelope-archival\" = \"Archival envelope\";\n" "\"media-type.envelope-bond\" = \"Bond envelope\";\n" "\"media-type.envelope-coated\" = \"Coated envelope\";\n" "\"media-type.envelope-cotton\" = \"Cotton envelope\";\n" "\"media-type.envelope-fine\" = \"Fine envelope\";\n" "\"media-type.envelope-heavyweight\" = \"Heavyweight envelope\";\n" "\"media-type.envelope-inkjet\" = \"Inkjet envelope\";\n" "\"media-type.envelope-lightweight\" = \"Lightweight envelope\";\n" "\"media-type.envelope-plain\" = \"Plain envelope\";\n" "\"media-type.envelope-preprinted\" = \"Preprinted envelope\";\n" "\"media-type.envelope-window\" = \"Windowed envelope\";\n" "\"media-type.fabric\" = \"Fabric\";\n" "\"media-type.fabric-archival\" = \"Archival fabric\";\n" "\"media-type.fabric-glossy\" = \"Glossy fabric\";\n" "\"media-type.fabric-high-gloss\" = \"High gloss fabric\";\n" "\"media-type.fabric-matte\" = \"Matte fabric\";\n" "\"media-type.fabric-semi-gloss\" = \"Semi-gloss fabric\";\n" "\"media-type.fabric-waterproof\" = \"Waterproof fabric\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Flexo base\";\n" "\"media-type.flexo-photo-polymer\" = \"Flexo photo polymer\";\n" "\"media-type.flute\" = \"Flute\";\n" "\"media-type.foil\" = \"Foil\";\n" "\"media-type.full-cut-tabs\" = \"Full cut tabs\";\n" "\"media-type.glass\" = \"Glass\";\n" "\"media-type.glass-colored\" = \"Glass colored\";\n" "\"media-type.glass-opaque\" = \"Glass opaque\";\n" "\"media-type.glass-surfaced\" = \"Glass surfaced\";\n" "\"media-type.glass-textured\" = \"Glass textured\";\n" "\"media-type.gravure-cylinder\" = \"Gravure cylinder\";\n" "\"media-type.image-setter-paper\" = \"Image setter paper\";\n" "\"media-type.imaging-cylinder\" = \"Imaging cylinder\";\n" "\"media-type.labels\" = \"Labels\";\n" "\"media-type.labels-colored\" = \"Colored labels\";\n" "\"media-type.labels-glossy\" = \"Glossy labels\";\n" "\"media-type.labels-high-gloss\" = \"High gloss labels\";\n" "\"media-type.labels-inkjet\" = \"Inkjet labels\";\n" "\"media-type.labels-matte\" = \"Matte labels\";\n" "\"media-type.labels-permanent\" = \"Permanent labels\";\n" "\"media-type.labels-satin\" = \"Satin labels\";\n" "\"media-type.labels-security\" = \"Security labels\";\n" "\"media-type.labels-semi-gloss\" = \"Semi-gloss labels\";\n" "\"media-type.laminating-foil\" = \"Laminating foil\";\n" "\"media-type.letterhead\" = \"Letterhead\";\n" "\"media-type.metal\" = \"Metal\";\n" "\"media-type.metal-glossy\" = \"Metal glossy\";\n" "\"media-type.metal-high-gloss\" = \"Metal high gloss\";\n" "\"media-type.metal-matte\" = \"Metal matte\";\n" "\"media-type.metal-satin\" = \"Metal satin\";\n" "\"media-type.metal-semi-gloss\" = \"Metal semi gloss\";\n" "\"media-type.mounting-tape\" = \"Mounting tape\";\n" "\"media-type.multi-layer\" = \"Multi layer\";\n" "\"media-type.multi-part-form\" = \"Multi part form\";\n" "\"media-type.other\" = \"Other\";\n" "\"media-type.paper\" = \"Paper\";\n" "\"media-type.photographic\" = \"Photo paper\";\n" "\"media-type.photographic-archival\" = \"Photographic archival\";\n" "\"media-type.photographic-film\" = \"Photo film\";\n" "\"media-type.photographic-glossy\" = \"Glossy photo paper\";\n" "\"media-type.photographic-high-gloss\" = \"High gloss photo paper\";\n" "\"media-type.photographic-matte\" = \"Matte photo paper\";\n" "\"media-type.photographic-satin\" = \"Satin photo paper\";\n" "\"media-type.photographic-semi-gloss\" = \"Semi-gloss photo paper\";\n" "\"media-type.plastic\" = \"Plastic\";\n" "\"media-type.plastic-archival\" = \"Plastic archival\";\n" "\"media-type.plastic-colored\" = \"Plastic colored\";\n" "\"media-type.plastic-glossy\" = \"Plastic glossy\";\n" "\"media-type.plastic-high-gloss\" = \"Plastic high gloss\";\n" "\"media-type.plastic-matte\" = \"Plastic matte\";\n" "\"media-type.plastic-satin\" = \"Plastic satin\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastic semi gloss\";\n" "\"media-type.plate\" = \"Plate\";\n" "\"media-type.polyester\" = \"Polyester\";\n" "\"media-type.pre-cut-tabs\" = \"Pre cut tabs\";\n" "\"media-type.roll\" = \"Roll\";\n" "\"media-type.screen\" = \"Screen\";\n" "\"media-type.screen-paged\" = \"Screen paged\";\n" "\"media-type.self-adhesive\" = \"Self adhesive\";\n" "\"media-type.self-adhesive-film\" = \"Self adhesive film\";\n" "\"media-type.shrink-foil\" = \"Shrink foil\";\n" "\"media-type.single-face\" = \"Single face\";\n" "\"media-type.single-wall\" = \"Single wall\";\n" "\"media-type.sleeve\" = \"Sleeve\";\n" "\"media-type.stationery\" = \"Stationery\";\n" "\"media-type.stationery-archival\" = \"Stationery archival\";\n" "\"media-type.stationery-coated\" = \"Coated paper\";\n" "\"media-type.stationery-cotton\" = \"Stationery cotton\";\n" "\"media-type.stationery-fine\" = \"Vellum paper\";\n" "\"media-type.stationery-heavyweight\" = \"Heavyweight paper\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Stationery heavyweight coated\";\n" "\"media-type.stationery-inkjet\" = \"Stationery inkjet paper\";\n" "\"media-type.stationery-letterhead\" = \"Letterhead\";\n" "\"media-type.stationery-lightweight\" = \"Lightweight paper\";\n" "\"media-type.stationery-preprinted\" = \"Preprinted paper\";\n" "\"media-type.stationery-prepunched\" = \"Punched paper\";\n" "\"media-type.tab-stock\" = \"Tab stock\";\n" "\"media-type.tractor\" = \"Tractor\";\n" "\"media-type.transfer\" = \"Transfer\";\n" "\"media-type.transparency\" = \"Transparency\";\n" "\"media-type.triple-wall\" = \"Triple wall\";\n" "\"media-type.wet-film\" = \"Wet film\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 or US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Envelope\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Envelope\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Envelope\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Envelope\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Envelope\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Envelope\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Envelope\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Envelope\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Envelope\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Envelope\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Envelope\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Envelope\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Envelope\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Envelope\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Envelope\";\n" "\"media.iso_dl_110x220mm\" = \"DL Envelope\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Executive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Envelope Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Envelope Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Envelope Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Envelope Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Envelope Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Envelope Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Reply Postcard\";\n" "\"media.jpn_you4_105x235mm\" = \"Envelope You 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Envelope A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Envelope C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Executive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"European Fanfold\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"US Fanfold\";\n" "\"media.na_foolscap_8.5x13in\" = \"Foolscap\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Statement\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"US Letter (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"US Letter (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"US Letter\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Envelope Monarch\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Envelope #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Envelope #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Envelope #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Envelope #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Envelope #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Envelope Personal\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (Special)\";\n" "\"media.om_invite_220x220mm\" = \"Envelope Invitation\";\n" "\"media.om_italian_110x230mm\" = \"Envelope Italian\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389mm\";\n" "\"media.om_postfix_114x229mm\" = \"Envelope Postfix\";\n" "\"media.prc_10_324x458mm\" = \"Envelope chinese #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chinese 16k\";\n" "\"media.prc_1_102x165mm\" = \"Envelope chinese #1\";\n" "\"media.prc_2_102x176mm\" = \"Envelope chinese #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chinese 32k\";\n" "\"media.prc_3_125x176mm\" = \"Envelope chinese #3\";\n" "\"media.prc_4_110x208mm\" = \"Envelope chinese #4\";\n" "\"media.prc_5_110x220mm\" = \"Envelope chinese #5\";\n" "\"media.prc_6_120x320mm\" = \"Envelope chinese #6\";\n" "\"media.prc_7_160x230mm\" = \"Envelope chinese #7\";\n" "\"media.prc_8_120x309mm\" = \"Envelope chinese #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"not configured\";\n" "\"not visible\" = \"not visible\";\n" "\"off\" = \"off\";\n" "\"on\" = \"on\";\n" "\"orientation-requested\" = \"Orientation\";\n" "\"orientation-requested.3\" = \"Portrait\";\n" "\"orientation-requested.4\" = \"Landscape\";\n" "\"orientation-requested.5\" = \"Reverse landscape\";\n" "\"orientation-requested.6\" = \"Reverse portrait\";\n" "\"orientation-requested.7\" = \"None\";\n" "\"output-bin\" = \"Output Tray\";\n" "\"output-bin.auto\" = \"Automatic\";\n" "\"output-bin.bottom\" = \"Bottom\";\n" "\"output-bin.center\" = \"Center\";\n" "\"output-bin.face-down\" = \"Face down\";\n" "\"output-bin.face-up\" = \"Face up\";\n" "\"output-bin.large-capacity\" = \"Large capacity\";\n" "\"output-bin.left\" = \"Left\";\n" "\"output-bin.mailbox-1\" = \"Mailbox 1\";\n" "\"output-bin.mailbox-10\" = \"Mailbox 10\";\n" "\"output-bin.mailbox-2\" = \"Mailbox 2\";\n" "\"output-bin.mailbox-3\" = \"Mailbox 3\";\n" "\"output-bin.mailbox-4\" = \"Mailbox 4\";\n" "\"output-bin.mailbox-5\" = \"Mailbox 5\";\n" "\"output-bin.mailbox-6\" = \"Mailbox 6\";\n" "\"output-bin.mailbox-7\" = \"Mailbox 7\";\n" "\"output-bin.mailbox-8\" = \"Mailbox 8\";\n" "\"output-bin.mailbox-9\" = \"Mailbox 9\";\n" "\"output-bin.middle\" = \"Middle\";\n" "\"output-bin.my-mailbox\" = \"My mailbox\";\n" "\"output-bin.rear\" = \"Rear\";\n" "\"output-bin.right\" = \"Right\";\n" "\"output-bin.side\" = \"Side\";\n" "\"output-bin.stacker-1\" = \"Stacker 1\";\n" "\"output-bin.stacker-10\" = \"Stacker 10\";\n" "\"output-bin.stacker-2\" = \"Stacker 2\";\n" "\"output-bin.stacker-3\" = \"Stacker 3\";\n" "\"output-bin.stacker-4\" = \"Stacker 4\";\n" "\"output-bin.stacker-5\" = \"Stacker 5\";\n" "\"output-bin.stacker-6\" = \"Stacker 6\";\n" "\"output-bin.stacker-7\" = \"Stacker 7\";\n" "\"output-bin.stacker-8\" = \"Stacker 8\";\n" "\"output-bin.stacker-9\" = \"Stacker 9\";\n" "\"output-bin.top\" = \"Top\";\n" "\"output-bin.tray-1\" = \"Tray 1\";\n" "\"output-bin.tray-10\" = \"Tray 10\";\n" "\"output-bin.tray-2\" = \"Tray 2\";\n" "\"output-bin.tray-3\" = \"Tray 3\";\n" "\"output-bin.tray-4\" = \"Tray 4\";\n" "\"output-bin.tray-5\" = \"Tray 5\";\n" "\"output-bin.tray-6\" = \"Tray 6\";\n" "\"output-bin.tray-7\" = \"Tray 7\";\n" "\"output-bin.tray-8\" = \"Tray 8\";\n" "\"output-bin.tray-9\" = \"Tray 9\";\n" "\"print-color-mode\" = \"Print Mode\";\n" "\"print-color-mode.auto\" = \"Automatic\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto monochrome\";\n" "\"print-color-mode.bi-level\" = \"Text\";\n" "\"print-color-mode.color\" = \"Color\";\n" "\"print-color-mode.highlight\" = \"Highlight\";\n" "\"print-color-mode.monochrome\" = \"Monochrome\";\n" "\"print-color-mode.process-bi-level\" = \"Process Text\";\n" "\"print-color-mode.process-monochrome\" = \"Process monochrome\";\n" "\"print-content-optimize\" = \"Optimize For\";\n" "\"print-content-optimize.auto\" = \"Automatic\";\n" "\"print-content-optimize.graphic\" = \"Graphics\";\n" "\"print-content-optimize.photo\" = \"Photo\";\n" "\"print-content-optimize.text\" = \"Text\";\n" "\"print-content-optimize.text-and-graphic\" = \"Text and graphics\";\n" "\"print-darkness\" = \"Print Darkness\";\n" "\"print-quality\" = \"Print Quality\";\n" "\"print-quality.3\" = \"Draft\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Best\";\n" "\"print-scaling\" = \"Scaling\";\n" "\"print-scaling.auto\" = \"Automatic\";\n" "\"print-scaling.auto-fit\" = \"Auto-fit\";\n" "\"print-scaling.fill\" = \"Fill\";\n" "\"print-scaling.fit\" = \"Fit\";\n" "\"print-scaling.none\" = \"None\";\n" "\"print-speed\" = \"Print Speed\";\n" "\"printer-resolution\" = \"Resolution\";\n" "\"printer-state-reasons.cover-open\" = \"Cover open.\";\n" "\"printer-state-reasons.door-open\" = \"Door open.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Identify printer.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Paper tray missing.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Out of ink.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Low ink.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Waste bin almost full.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Waste bin full.\";\n" "\"printer-state-reasons.media-empty\" = \"Out of paper.\";\n" "\"printer-state-reasons.media-jam\" = \"Paper jam.\";\n" "\"printer-state-reasons.media-low\" = \"Replace paper soon.\";\n" "\"printer-state-reasons.media-needed\" = \"Load paper.\";\n" "\"printer-state-reasons.none\" = \"Ready.\";\n" "\"printer-state-reasons.offline\" = \"Offline.\";\n" "\"printer-state-reasons.other\" = \"See printer.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Printer busy.\";\n" "\"printer-state-reasons.toner-empty\" = \"Out of toner.\";\n" "\"printer-state-reasons.toner-low\" = \"Toner low.\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Processing\";\n" "\"printer-state.5\" = \"Stopped\";\n" "\"sides\" = \"2-Sided Printing\";\n" "\"sides.one-sided\" = \"Off\";\n" "\"sides.two-sided-long-edge\" = \"On (portrait)\";\n" "\"sides.two-sided-short-edge\" = \"On (landscape)\";\n" "\"unable to join\" = \"unable to join\";\n" "\"yesterday at %02d:%02d:%02d\" = \"yesterday at %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Åland Islands\";\n"; pappl-1.4.9/pappl/strings/nl.strings000066400000000000000000000000001476704353100174720ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/nn.strings000066400000000000000000000000001476704353100174740ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/pl.strings000066400000000000000000001411561476704353100175160ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Anuluj wszystkie zadania (cancel)."; " -c COPIES" = " -c KOPIE"; " -d PRINTER Specify printer." = " -d DRUKARKA Określ drukarkę."; " -j JOB-ID Specify job ID (cancel)." = " -j ID-ZADANIA Określ identyfikator zadania (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m NAZWA-STEROWNIKA Określ sterownik (add/modify)."; " -n COPIES Specify number of copies (submit)." = " -n KOPIE Określ liczbę kopii (submit)."; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o NAZWA=WARTOŚĆ Określ opcję (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 do 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 do 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:SZEROKOŚĆ,DŁUGOŚĆ'"; " -o printer-location='LOCATION'" = " -o printer-location='LOKALIZACJA'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANIZACJA'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='JEDNOSTKA/SEKCJA'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI Określ ipp: lub ipps: drukarka/serwer."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v URI-URZĄDZENIA Podaj gniazdo: lub usb: urządzenie (add/modify)."; " add PRINTER Add a printer." = " add DRUKARKA Dodaj drukarkę."; " autoadd Automatically add supported printers." = " autoadd Automatyczne dodawanie obsługiwanych drukarek."; " cancel Cancel one or more jobs." = " cancel Anuluj jedno lub więcej zadań."; " default Set the default printer." = " default Ustaw domyślną drukarkę."; " delete Delete a printer." = " delete Usuń drukarkę."; " devices List devices." = " devices Wyświetl listę urządzeń."; " drivers List drivers." = " drivers Wyświetl listę sterowników."; " jobs List jobs." = " jobs Wyświetl listę zadań."; " modify Modify a printer." = " modify Zmodyfikuj drukarkę."; " options List printer options." = " options Wyświetl listę opcji drukarki."; " pause Pause printing for a printer." = " pause Wstrzymaj drukowanie drukarki."; " printers List printers." = " printers Wyświetl listę drukarek."; " resume Resume printing for a printer." = " resume Wznów drukowanie drukarki."; " server Run a server." = " server Uruchom serwer."; " shutdown Shutdown a running server." = " shutdown Wyłącz uruchomiony serwer."; " status Show server/printer/job status." = " status Pokaż stan serwera/drukarki/zadania."; " submit Submit a file for printing." = " submit Prześlij plik do druku."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d.%02d.%02d o %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d dni temu o %02d:%02d:%02d"; "%d inches/sec" = "%d in/s"; "%d job" = "%d zadanie"; /* Media size in millimeters */ "%d x %dmm" = "%d x %d mm"; "%ddpi" = "%d dpi"; "%dx%ddpi" = "%d x %d dpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) z %s"; /* Source/Tray Media */ "%s Media" = "%s Nośnik"; "%s: Bad 'server-port' value." = "%s: Nieprawidłowa wartość 'server-port'."; "%s: Bad job ID." = "%s: Nieprawidłowy identyfikator zadania."; "%s: Bad printer URI '%s'." = "%s: Nieprawidłowy URI drukarki '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Nie można określić więcej niż jednego polecenia podrzędnego."; "%s: Empty print file received on the standard input." = "%s: Odebrano pusty plik do wydruku na standardowym wejściu."; "%s: Failed to create a system." = "%s: Nie udało się utworzyć systemu."; "%s: Missing '-d PRINTER'." = "%s: Brak '-d DRUKARKA'."; "%s: Missing '-m DRIVER-NAME'." = "%s: Brak '-m NAZWA-STEROWNIKA'."; "%s: Missing '-v DEVICE-URI'." = "%s: Brak '-v URI-URZĄDZENIA'."; "%s: Missing copy count after '-n'." = "%s: Brak liczby kopii po '-n'."; "%s: Missing device URI after '-v'." = "%s: Brak URI urządzenia po '-v'."; "%s: Missing driver name after '-m'." = "%s: Brak nazwy sterownika po '-m'."; "%s: Missing filename after '--'." = "%s: Brak nazwy pliku po '--'."; "%s: Missing hostname after '-h'." = "%s: Brak nazwy hosta po '-h'."; "%s: Missing job ID after '-j'." = "%s: Brak identyfikatora zadania po '-j'."; "%s: Missing option(s) after '-o'." = "%s: Brak opcji po '-o'."; "%s: Missing printer URI after '-u'." = "%s: Brak URI drukarki po '-u'."; "%s: Missing printer name after '-d'." = "%s: Brak nazwy drukarki po '-d'."; "%s: Missing space after '-o'." = "%s: Brak spacji po '-o'."; "%s: Missing title after '-t'." = "%s: Brak tytułu po '-t'."; "%s: No default printer available." = "%s: Brak dostępnej drukarki domyślnej."; "%s: No files to print." = "%s: Brak plików do wydrukowania."; "%s: Server is not running." = "%s: Serwer nie jest uruchomiony."; "%s: Sub-command '%s' does not accept files." = "%s: Podpolecenie '%s' nie akceptuje plików."; "%s: Sub-command 'autoadd' is not supported." = "%s: Podpolecenie 'autoadd' nie jest obsługiwane."; "%s: Too many files." = "%s: Zbyt wiele plików."; "%s: Unable to access '%s': %s" = "%s: Nie można uzyskać dostępu do '%s': %s"; "%s: Unable to add printer: %s" = "%s: Nie można dodać drukarki: %s"; "%s: Unable to cancel job: %s" = "%s: Nie można anulować zadania: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: Nie można połączyć się z drukarką w '%s:%d': %s"; "%s: Unable to connect to server: %s" = "%s: Nie można połączyć się z serwerem: %s"; "%s: Unable to create temporary file: %s" = "%s: Nie można utworzyć pliku tymczasowego: %s"; "%s: Unable to delete printer: %s" = "%s: Nie można usunąć drukarki: %s"; "%s: Unable to get available devices: %s" = "%s: Nie można uzyskać dostępnych urządzeń: %s"; "%s: Unable to get information for '%s': %s" = "%s: Nie można uzyskać informacji o '%s': %s"; "%s: Unable to get information for printer: %s" = "%s: Nie można uzyskać informacji o drukarce: %s"; "%s: Unable to get printer options: %s" = "%s: Nie można uzyskać opcji drukarki: %s"; "%s: Unable to modify printer: %s" = "%s: Nie można zmodyfikować drukarki: %s"; "%s: Unable to pause printer: %s" = "%s: Nie można wstrzymać drukarki: %s"; "%s: Unable to print '%s': %s" = "%s: Nie można wydrukować '%s': %s"; "%s: Unable to resume printer: %s" = "%s: Nie można wznowić drukarki: %s"; "%s: Unable to set default printer: %s" = "%s: Nie można ustawić domyślnej drukarki: %s"; "%s: Unable to shutdown server: %s" = "%s: Nie można wyłączyć serwera: %s"; "%s: Unable to start server: %s" = "%s: Nie można uruchomić serwera: %s"; "%s: Unable to write to temporary file: %s" = "%s: Nie można zapisać do pliku tymczasowego: %s"; "%s: Unknown option '%s'." = "%s: Nieznana opcja '%s'."; "%s: Unknown option '-%c'." = "%s: Nieznana opcja '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Nieznane podpolecenie '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Nieobsługiwany schemat URI '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Ostrzeżenie — poświadczenia użytkownika nie są obsługiwane w URI."; ", Borderless" = ", Bez obramowania"; "A printer with that name already exists." = "Drukarka o tej nazwie już istnieje."; "Aborted %s" = "Przerwano %s"; "Add Printer" = "Dodaj drukarkę"; "Admin Group" = "Grupa administratorów"; "Afghanistan" = "Afganistan"; "Albania" = "Albania"; "Algeria" = "Algieria"; "American Samoa" = "Samoa Amerykańskie"; "Andorra" = "Andora"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarktyda"; "Antigua and Barbuda" = "Antigua i Barbuda"; "Argentina" = "Argentyna"; "Armenia" = "Armenia"; "Aruba" = "Aruba"; "Australia" = "Australia"; "Austria" = "Austria"; "Auto" = "Automatycznie"; "Auto-Detect Driver" = "Automatyczne wykrywanie sterownika"; "Azerbaijan" = "Azerbejdżan"; "Bad administration group." = "Zła grupa administracyjna."; "Bad port number." = "Zły numer portu."; "Bad print group." = "Zła grupa drukowania."; "Bad printer defaults." = "Złe ustawienia domyślne drukarki."; "Bahamas" = "Bahamy"; "Bahrain" = "Bahrajn"; "Bangladesh" = "Bangladesz"; "Barbados" = "Barbados"; "Belarus" = "Białoruś"; "Belgium" = "Belgia"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermudy"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Boliwia (Wielonarodowe Państwo Boliwia)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius i Saba"; "Borderless" = "Bez obramowania"; "Bosnia and Herzegovina" = "Bośnia i Hercegowina"; "Botswana" = "Botswana"; "Bouvet Island" = "Wyspa Bouveta"; "Brazil" = "Brazylia"; "British Indian Ocean Territory" = "Brytyjskie Terytorium Oceanu Indyjskiego"; "Brunei Darussalam" = "Brunei Darussalam"; "Bulgaria" = "Bułgaria"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Republika Zielonego Przylądka"; "Cambodia" = "Kambodża"; "Cameroon" = "Kamerun"; "Canada" = "Kanada"; "Cancel All Jobs" = "Anuluj wszystkie zadania"; "Cancel Job" = "Anuluj zadanie"; "Canceled %s" = "Anulowano %s"; "Canceling" = "Anulowanie"; "Cayman Islands" = "Kajmany"; "Central African Republic" = "Republika Środkowoafrykańska"; "Certificate created." = "Certyfikat utworzony."; "Certificate installed." = "Certyfikat zainstalowany."; "Certificate request created." = "Żądanie certyfikatu utworzone."; "Chad" = "Czad"; "Change Access Password" = "Zmień hasło dostępu"; "Change Log Level" = "Zmień poziom dziennika"; "Change Network Settings" = "Zmień ustawienia sieciowe"; "Change Wi-Fi Network" = "Zmień sieć Wi-Fi"; "Changes Saved." = "Zmiany zapisane."; "Changes saved." = "Zmiany zapisane."; "Chile" = "Chile"; "China" = "Chiny"; "Christmas Island" = "Wyspa Bożego Narodzenia"; "City/Locality" = "Miasto/Miejscowość"; "Cocos (Keeling) Islands" = "Wyspy Kokosowe (Keelinga)"; "Colombia" = "Kolumbia"; "Comoros" = "Komory"; "Completed %s" = "Ukończono %s"; "Configuration" = "Konfiguracja"; "Configure Media" = "Konfigurowanie nośników"; "Confirm Cancel All" = "Potwierdź anulowanie wszystkiego"; "Confirm Delete Printer" = "Potwierdź usunięcie drukarki"; "Congo" = "Kongo"; "Congo, Democratic Republic of the" = "Kongo, Republika Demokratyczna"; "Contact" = "Kontakt"; "Cook Islands" = "Wyspy Cooka"; "Costa Rica" = "Kostaryka"; "Create Certificate Signing Request" = "Utwórz żądanie podpisania certyfikatu"; "Create New Certificate" = "Utwórz nowy certyfikat"; "Create New TLS Certificate" = "Utwórz nowy certyfikat TLS"; "Create TLS Certificate Request" = "Utwórz żądanie certyfikatu TLS"; "Croatia" = "Chorwacja"; "Cuba" = "Kuba"; "Curaçao" = "Curaçao"; "Current Password" = "Aktualne hasło"; "Custom Size" = "Rozmiar niestandardowy"; "Cyprus" = "Cypr"; "Czechia" = "Czechy"; "Côte d'Ivoire" = "Wybrzeże Kości Słoniowej"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP z adresem ręcznym"; "DNS-SD Service Name" = "Nazwa usługi DNS-SD"; "Debugging" = "Debugowanie"; "Default printer set." = "Domyślny zestaw drukarki."; "Delete" = "Usuń"; "Delete Printer" = "Usuń drukarkę"; "Denmark" = "Dania"; "Djibouti" = "Dżibuti"; "Domain Name" = "Nazwa domeny"; "Dominica" = "Dominika"; "Dominican Republic" = "Republika Dominikany"; "Download Certificate Request File" = "Pobierz plik żądania certyfikatu"; "Ecuador" = "Ekwador"; "Egypt" = "Egipt"; "El Salvador" = "Salwador"; "Equatorial Guinea" = "Gwinea Równikowa"; "Eritrea" = "Erytrea"; "Errors" = "Błędy"; "Estonia" = "Estonia"; "Eswatini" = "Eswatini"; "Ethiopia" = "Etiopia"; "Falkland Islands (Malvinas)" = "Falklandy (Malwiny)"; "Faroe Islands" = "Wyspy Owcze"; "Fatal Errors/Conditions" = "Krytyczne błędy/warunki"; "Fiji" = "Fidżi"; "Finland" = "Finlandia"; "France" = "Francja"; "French Guiana" = "Gujana Francuska"; "French Polynesia" = "Polinezja Francuska"; "French Southern Territories" = "Francuskie Terytoria Południowe"; "Gabon" = "Gabon"; "Gambia" = "Gambia"; "Georgia" = "Gruzja"; "Germany" = "Niemcy"; "Ghana" = "Ghana"; "Gibraltar" = "Gibraltar"; "Greece" = "Grecja"; "Greenland" = "Grenlandia"; "Grenada" = "Grenada"; "Group changes saved." = "Zmiany w grupie zapisane."; "Guadeloupe" = "Gwadelupa"; "Guam" = "Guam"; "Guatemala" = "Gwatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Gwinea"; "Guinea-Bissau" = "Gwinea Bissau"; "Guyana" = "Gujana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Wyspy Heard i McDonalda"; "Hidden SSID" = "Ukryty SSID"; "Hold Job" = "Wstrzymaj zadanie"; "Hold New Jobs" = "Wstrzymuj nowe zadania"; "Holding new jobs." = "Wstrzymywanie nowych zadań."; "Holy See" = "Stolica Apostolska"; "Honduras" = "Honduras"; "Hong Kong" = "Hongkong"; "Hostname" = "Nazwa hosta"; "Human-Readable Location" = "Lokalizacja czytelna dla człowieka"; "Hungary" = "Węgry"; "IPv4 Address" = "Adres IPv4"; "IPv4 Configuration" = "Konfiguracja IPv4"; "IPv4 Gateway" = "Brama IPv4"; "IPv4 Netmask" = "Maska sieci IPv4"; "IPv6 Address" = "Adres IPv6"; "IPv6 Configuration" = "Konfiguracja IPv6"; "IPv6 Link-Local" = "Łącze lokalne IPv6"; "IPv6 Prefix Length" = "Długość prefiksu IPv6"; "Iceland" = "Islandia"; "Identify Printer" = "Zidentyfikuj drukarkę"; "India" = "Indie"; "Indonesia" = "Indonezja"; "Informational" = "Informacyjny"; "Install TLS Certificate" = "Zainstaluj certyfikat TLS"; "Invalid IPv4 address." = "Nieprawidłowy adres IPv4."; "Invalid IPv4 netmask." = "Nieprawidłowa maska sieci IPv4."; "Invalid IPv6 address." = "Nieprawidłowy adres IPv6."; "Invalid IPv6 prefix length." = "Nieprawidłowa długość prefiksu IPv6."; "Invalid Job ID." = "Nieprawidłowy identyfikator zadania."; "Invalid certificate or private key." = "Nieprawidłowy certyfikat lub klucz prywatny."; "Invalid form data." = "Nieprawidłowe dane formularza."; "Invalid form submission." = "Nieprawidłowe wysłanie formularza."; "Invalid job ID." = "Nieprawidłowy identyfikator zadania."; "Invalid network configuration." = "Nieprawidłowa konfiguracja sieci."; "Iran (Islamic Republic of)" = "Iran (Islamska Republika Iranu)"; "Iraq" = "Irak"; "Ireland" = "Irlandia"; "Isle of Man" = "Wyspa Man"; "Israel" = "Izrael"; "Italy" = "Włochy"; "Jamaica" = "Jamajka"; "Japan" = "Japonia"; "Jersey" = "Jersey"; "Job #" = "Zadanie #"; "Job canceled." = "Zadanie anulowane."; "Job held." = "Zadanie wstrzymane."; "Job released." = "Zadanie wznowione."; "Jobs" = "Zadania"; "Joining Wi-Fi Network" = "Dołączanie do sieci Wi-Fi"; "Jordan" = "Jordania"; "Kazakhstan" = "Kazachstan"; "Kenya" = "Kenia"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Korea (Koreańska Republika Ludowo-Demokratyczna)"; "Korea, Republic of" = "Korea (Republika Korei)"; "Kuwait" = "Kuwejt"; "Kyrgyzstan" = "Kirgistan"; "Landscape" = "Poziomo"; "Lao People's Democratic Republic" = "Laotańska Republika Ludowo-Demokratyczna"; "Latvia" = "Łotwa"; "Lebanon" = "Liban"; "Lesotho" = "Lesotho"; "Level" = "Poziom"; "Liberia" = "Liberia"; "Libya" = "Libia"; "Liechtenstein" = "Liechtenstein"; "Lithuania" = "Litwa"; "Location" = "Lokalizacja"; "Log Level" = "Poziom dziennika"; "Logging" = "Rejestrowanie"; "Logs" = "Dzienniki"; "Luxembourg" = "Luksemburg"; "Macao" = "Makao"; "Madagascar" = "Madagaskar"; "Malawi" = "Malawi"; "Malaysia" = "Malezja"; "Maldives" = "Malediwy"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Konfiguracja ręczna"; "Marshall Islands" = "Wyspy Marshalla"; "Martinique" = "Martynika"; "Mauritania" = "Mauretania"; "Mauritius" = "Mauritius"; "Mayotte" = "Majotta"; "Media" = "Nośniki"; "Mexico" = "Meksyk"; "Micronesia (Federated States of)" = "Mikronezja (Sfederowane Stany Mikronezji)"; "Missing action." = "Brak działania."; "Missing job ID." = "Brak identyfikatora zadania."; "Missing network name." = "Brak nazwy sieci."; "Missing private key." = "Brak klucza prywatnego."; "Moldova, Republic of" = "Mołdawia, Republika Mołdawii"; "Monaco" = "Monako"; "Mongolia" = "Mongolia"; "Montenegro" = "Czarnogóra"; "Montserrat" = "Montserrat"; "Morocco" = "Maroko"; "Mozambique" = "Mozambik"; "Myanmar" = "Myanmar"; "Name" = "Nazwa"; "Namibia" = "Namibia"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Holandia"; "Network" = "Sieć"; "Network Printer" = "Drukarka sieciowa"; "Networking" = "Sieciowość"; "New Caledonia" = "Nowa Kaledonia"; "New Zealand" = "Nowa Zelandia"; "Nicaragua" = "Nikaragua"; "Niger" = "Niger"; "Nigeria" = "Nigeria"; "Niue" = "Niue"; "No default printer set." = "Nie ustawiono drukarki domyślnej."; "No jobs in history." = "Nie ma zadań w historii."; "Norfolk Island" = "Wyspa Norfolk"; "North Macedonia" = "Macedonia Północna"; "Northern Mariana Islands" = "Mariany Północne"; "Norway" = "Norwegia"; "Not set" = "Nie ustawiono"; "Off" = "Wyłączony"; "Offset" = "Przesunięcie"; "Oman" = "Oman"; "Options:" = "Opcje:"; "Organization" = "Organizacja"; "Organization Name" = "Nazwa organizacji"; "Other Settings" = "Inne ustawienia"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Palestyna, Państwo Palestyna"; "Panama" = "Panama"; "Papua New Guinea" = "Papua Nowa Gwinea"; "Paraguay" = "Paragwaj"; "Password" = "Hasło"; "Password changed." = "Hasło zostało zmienione."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Hasło musi mieć co najmniej osiem znaków i zawierać co najmniej jedną wielką literę, jedną małą literę i jedną cyfrę."; "Passwords do not match." = "Hasła nie pasują do siebie."; "Pause Printing" = "Wstrzymaj drukowanie"; "Peru" = "Peru"; "Philippines" = "Filipiny"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Wprowadź nazwę hosta lub adres IP drukarki."; "Please enter a printer name." = "Wprowadź nazwę drukarki."; "Please select a device." = "Wybierz urządzenie."; "Please select a driver." = "Wybierz sterownik."; "Please select a valid log level." = "Wybierz odpowiedni poziom rejestrowania."; "Poland" = "Polska"; "Portrait" = "Pionowo"; "Portugal" = "Portugalia"; "Primary DNS" = "Podstawowy DNS"; "Print Group" = "Grupa drukowania"; "Print Test Page" = "Wydrukuj stronę testową"; "Print job options:" = "Opcje zadania drukowania:"; "Printer identified." = "Drukarka zidentyfikowana."; "Printer is currently active." = "Drukarka jest obecnie aktywna."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Nazwy drukarek muszą zaczynać się od litery lub podkreślenia i nie mogą zawierać znaków specjalnych."; "Printer options:" = "Opcje drukarki:"; "Printer paused." = "Drukarka wstrzymana."; "Printer pausing." = "Wstrzymanie drukarki."; "Printer resuming." = "Wznawianie drukarki."; "Printers" = "Drukarki"; "Printing Defaults" = "Ustawienia domyślne drukowania"; "Puerto Rico" = "Portoryko"; "Qatar" = "Katar"; "Queued %s" = "W kolejce %s"; "Release Held New Jobs" = "Wznów wstrzymane nowe zadania"; "Release Job" = "Wznów zadanie"; "Released held new jobs." = "Wznowiono wstrzymane nowe zadania."; "Reprint Job" = "Zadanie przedruku"; "Reprinted job." = "Przedrukowane zadanie."; "Resume Printing" = "Wznów drukowanie"; "Reverse Landscape" = "Poziomy (obrócony)"; "Reverse Portrait" = "Pionowy (obrócony)"; "Romania" = "Rumunia"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Uruchomiony, %s od %s%s."; "Russian Federation" = "Federacja Rosyjska"; "Rwanda" = "Rwanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint-Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Święta Helena, Wniebowstąpienie i Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts i Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (część francuska)"; "Saint Pierre and Miquelon" = "Saint-Pierre i Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent i Grenadyny"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Wyspy Świętego Tomasza i Książęca"; "Saudi Arabia" = "Arabia Saudyjska"; "Save Changes" = "Zapisz zmiany"; "Secondary DNS" = "Pomocniczy DNS"; "Security" = "Bezpieczeństwo"; "Select Driver" = "Wybierz sterownik"; "Senegal" = "Senegal"; "Serbia" = "Serbia"; "Server is not running." = "Serwer nie jest uruchomiony."; "Set Access Password" = "Ustaw hasło dostępu"; "Set as Default" = "Ustaw jako domyślne"; "Seychelles" = "Seszele"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapur"; "Sint Maarten (Dutch part)" = "Sint Maarten (część holenderska)"; "Slovakia" = "Słowacja"; "Slovenia" = "Słowenia"; "Solomon Islands" = "Wyspy Salomona"; "Somalia" = "Somalia"; "South Africa" = "Republika Południowej Afryki"; "South Georgia and the South Sandwich Islands" = "Georgia Południowa i Sandwich Południowy"; "South Sudan" = "Sudan Południowy"; "Spain" = "Hiszpania"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "Rozpoczęto %s"; "Status" = "Status"; "Sub-commands:" = "Podkomendy:"; "Sudan" = "Sudan"; "Supplies" = "Materiały eksploatacyjne"; "Suriname" = "Surinam"; "Svalbard and Jan Mayen" = "Svalbard i Jan Mayen"; "Sweden" = "Szwecja"; "Switzerland" = "Szwajcaria"; "Syrian Arab Republic" = "Syryjska Republika Arabska"; "Taiwan, Province of China" = "Tajwan (prowincja Republiki Chińskiej)"; "Tajikistan" = "Tadżykistan"; "Tanzania, United Republic of" = "Tanzania, Zjednoczona Republika Tanzanii"; "Test page printed." = "Strona testowa wydrukowana."; "Thailand" = "Tajlandia"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Ten formularz tworzy żądanie podpisania certyfikatu („CSR”), które można wysłać do urzędu certyfikacji („CA”) w celu uzyskania zaufanego certyfikatu TLS. Klucz prywatny jest zapisywany oddzielnie do użytku z certyfikatem otrzymanym od urzędu certyfikacji."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Ten formularz tworzy nowy „samopodpisany” certyfikat TLS do bezpiecznego drukowania. Certyfikaty z podpisem własnym nie są automatycznie uznawane za zaufane przez przeglądarki internetowe."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Ten formularz zainstaluje zaufany certyfikat TLS uzyskany od urzędu certyfikacji („CA”). Po zainstalowaniu będzie natychmiast używany."; "Timor-Leste" = "Timor Wschodni"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trynidad i Tobago"; "Tunisia" = "Tunezja"; "Turkey" = "Turcja"; "Turkmenistan" = "Turkmenistan"; "Turks and Caicos Islands" = "Wyspy Turks i Caicos"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukraina"; "Unable to access test print file." = "Nie można uzyskać dostępu do pliku wydruku testowego."; "Unable to copy print job." = "Nie można skopiować zadania drukowania."; "Unable to create certificate request." = "Nie można utworzyć żądania certyfikatu."; "Unable to create certificate." = "Nie można utworzyć certyfikatu."; "Unable to create test print job." = "Nie można utworzyć testowego zadania drukowania."; "Unable to identify printer." = "Nie można zidentyfikować drukarki."; "Unable to lookup address." = "Nie można wyszukać adresu."; "Unable to use that driver." = "Nie można użyć tego sterownika."; "United Arab Emirates" = "Zjednoczone Emiraty Arabskie"; "United Kingdom" = "Zjednoczone Królestwo"; "United Kingdom of Great Britain and Northern Ireland" = "Zjednoczone Królestwo Wielkiej Brytanii i Irlandii Północnej"; "United States Minor Outlying Islands" = "Dalekie Wyspy Mniejsze Stanów Zjednoczonych"; "United States of America" = "Stany Zjednoczone Ameryki"; "Unknown" = "Nieznany"; "Unknown action." = "Nieznana czynność."; "Unknown form action." = "Nieznana czynność formularza."; "Unknown form request." = "Nieznane żądanie formularza."; "Updating Network Configuration" = "Aktualizowanie konfiguracji sieci"; "Uruguay" = "Urugwaj"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Użycie: %s SUB-COMMAND [OPCJE] [NAZWA PLIKU]\n"; "Use My Position" = "Użyj mojej pozycji"; "Users" = "Użytkownicy"; "Uzbekistan" = "Uzbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Wenezuela (Boliwariańska Republika Wenezueli)"; "Version %s" = "Wersja %"; "Viet Nam" = "Wietnam"; "View Logs" = "Wyświetl dzienniki"; "Virgin Islands (British)" = "Wyspy Dziewicze (brytyjskie)"; "Virgin Islands (U.S.)" = "Wyspy Dziewicze (amerykańskie)"; "Wallis and Futuna" = "Wallis i Futuna"; "Warning" = "Ostrzeżenie"; "Western Sahara" = "Sahara Zachodnia"; "Wi-Fi Configuration" = "Konfiguracja Wi-Fi"; "Wi-Fi Network" = "Sieć Wi-Fi"; "Width" = "Szerokość"; "Wrong old password." = "Nieprawidłowe stare hasło."; "Yemen" = "Jemen"; "Zambia" = "Zambia"; "Zimbabwe" = "Zimbabwe"; "at %02d:%02d:%02d" = "o %02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Liczba kopii"; "default printer" = "drukarka domyślna"; "finishings" = "Wykończenie"; "finishings.10" = "Składanie"; "finishings.100" = "Składanie Z"; "finishings.101" = "Inżynierskie składanie Z"; "finishings.11" = "Cięcie"; "finishings.12" = "Bela"; "finishings.13" = "Kreator broszur"; "finishings.15" = "Płaszcz"; "finishings.16" = "Laminat"; "finishings.20" = "Zszywka na górze po lewej"; "finishings.21" = "Zszywka na dole po lewej"; "finishings.22" = "Zszywka na górze po prawej"; "finishings.23" = "Zszywka na dole po prawej"; "finishings.24" = "Lewy ścieg brzegowy"; "finishings.25" = "Górny ścieg brzegowy"; "finishings.26" = "Prawy ścieg brzegowy"; "finishings.27" = "Dolny ścieg brzegowy"; "finishings.28" = "2 zszywki po lewej"; "finishings.29" = "2 zszywki na górze"; "finishings.3" = "Brak"; "finishings.30" = "2 zszywki po prawej"; "finishings.31" = "2 zszywki na dole"; "finishings.32" = "3 zszywki po lewej"; "finishings.33" = "3 zszywki na górze"; "finishings.34" = "3 zszywki po prawej"; "finishings.35" = "3 zszywki na dole"; "finishings.4" = "Zszywka"; "finishings.5" = "Dziurkacz"; "finishings.50" = "Wiązanie po lewej"; "finishings.51" = "Wiązanie na górze"; "finishings.52" = "Wiązanie po prawej"; "finishings.53" = "Wiązanie na dole"; "finishings.6" = "Okładka"; "finishings.60" = "Cięcie po każdej stronie"; "finishings.61" = "Cięcie po każdym dokumencie"; "finishings.62" = "Cięcie po każdym zestawie"; "finishings.63" = "Cięcie po zadaniu"; "finishings.7" = "Wiązanie"; "finishings.70" = "Dziurkacz na górze po lewej"; "finishings.71" = "Dziurkacz na dole po lewej"; "finishings.72" = "Dziurkacz na górze po prawej"; "finishings.73" = "Dziurkacz na dole po prawej"; "finishings.74" = "2-otworowy dziurkacz po lewej"; "finishings.75" = "2-otworowy dziurkacz na górze"; "finishings.76" = "2-otworowy dziurkacz po prawej"; "finishings.77" = "2-otworowy dziurkacz na dole"; "finishings.78" = "3-otworowy dziurkacz po lewej"; "finishings.79" = "3-otworowy dziurkacz na górze"; "finishings.8" = "Ścieg siodłowy"; "finishings.80" = "3-otworowy dziurkacz po prawej"; "finishings.81" = "3-otworowy dziurkacz na dole"; "finishings.82" = "4-otworowy dziurkacz po lewej"; "finishings.83" = "4-otworowy dziurkacz na górze"; "finishings.84" = "4-otworowy dziurkacz po prawej"; "finishings.85" = "4-otworowy dziurkacz na dole"; "finishings.86" = "Wielootworowy dziurkacz po lewej"; "finishings.87" = "Wielootworowy dziurkacz na górze"; "finishings.88" = "Wielootworowy dziurkacz po prawej"; "finishings.89" = "Wielootworowy dziurkacz na dole"; "finishings.9" = "Ścieg brzegowy"; "finishings.90" = "Składanie akordeonowe"; "finishings.91" = "Składanie podwójnej bramy"; "finishings.92" = "Składanie bramy"; "finishings.93" = "Składanie połowiczne"; "finishings.94" = "Składanie połowiczne Z"; "finishings.95" = "Składanie bramy lewej"; "finishings.96" = "Składanie listu"; "finishings.97" = "Składanie równoległe"; "finishings.98" = "Składanie plakatu"; "finishings.99" = "Składanie bramy prawej"; "holding new jobs" = "wstrzymywanie nowych zadań"; "job-state-reasons.aborted-by-system" = "Zatrzymanie."; "job-state-reasons.compression-error" = "Błąd dekompresji."; "job-state-reasons.document-format-error" = "Błąd formatu dokumentu."; "job-state-reasons.document-password-error" = "Błąd hasła dokumentu."; "job-state-reasons.document-permission-error" = "Błąd uprawnień do dokumentu."; "job-state-reasons.document-unprintable-error" = "Błąd uniemożliwiający drukowanie dokumentu."; "job-state-reasons.errors-detected" = "Wykryto błędy."; "job-state-reasons.job-canceled-at-device" = "Anulowano w drukarce."; "job-state-reasons.job-canceled-by-user" = "Anulowano przez użytkownika."; "job-state-reasons.job-completed-successfully" = "Wydrukowano."; "job-state-reasons.job-completed-with-errors" = "Wydrukowano z błędami."; "job-state-reasons.job-completed-with-warnings" = "Wydrukowano z ostrzeżeniami."; "job-state-reasons.job-data-insufficient" = "Niewystarczające dane."; "job-state-reasons.job-fetchable" = "Do pobrania."; "job-state-reasons.job-incoming" = "Przychodzące."; "job-state-reasons.job-printing" = "Drukowanie."; "job-state-reasons.job-queued" = "Przygotowanie do drukowania."; "job-state-reasons.job-spooling" = "Buforowanie."; "job-state-reasons.none" = "W toku."; "job-state-reasons.printer-stopped" = "Drukarka offline."; "job-state-reasons.printer-stopped-partly" = "Drukarka częściowo zatrzymana."; "job-state-reasons.processing-to-stop-point" = "Zatrzymanie."; "job-state-reasons.queued-in-device" = "Gotowe."; "job-state-reasons.warnings-detected" = "Wykryto ostrzeżenia."; "job-state.3" = "W toku"; "job-state.4" = "Wstrzymane"; "job-state.5" = "Przetwarzanie"; "job-state.6" = "Zatrzymane"; "job-state.7" = "Anulowane"; "job-state.8" = "Przerwane"; "job-state.9" = "Zakończone"; "joining" = "dołączenie"; "media" = "Nośniki"; "media-col" = "Nośniki"; "media-size" = "Rozmiar nośnika"; "media-size-name" = "Rozmiar nośnika"; "media-source" = "Podajnik"; "media-source.alternate" = "Alternatywne"; "media-source.alternate-roll" = "Rolka zastępcza"; "media-source.auto" = "Automatyczne"; "media-source.bottom" = "Dół"; "media-source.by-pass-tray" = "Taca wielozadaniowa"; "media-source.center" = "Centrum"; "media-source.disc" = "Płyta"; "media-source.envelope" = "Koperta"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Duża pojemność"; "media-source.left" = "Lewo"; "media-source.main" = "Główne"; "media-source.main-roll" = "Główna rolka"; "media-source.manual" = "Ręczne"; "media-source.middle" = "Środek"; "media-source.photo" = "Zdjęcie"; "media-source.rear" = "Tył"; "media-source.right" = "Prawo"; "media-source.roll-1" = "Rolka 1"; "media-source.roll-10" = "Rolka 10"; "media-source.roll-2" = "Rolka 2"; "media-source.roll-3" = "Rolka 3"; "media-source.roll-4" = "Rolka 4"; "media-source.roll-5" = "Rolka 5"; "media-source.roll-6" = "Rolka 6"; "media-source.roll-7" = "Rolka 7"; "media-source.roll-8" = "Rolka 8"; "media-source.roll-9" = "Rolka 9"; "media-source.side" = "Bok"; "media-source.top" = "Góra"; "media-source.tray-1" = "Taca 1"; "media-source.tray-10" = "Taca 10"; "media-source.tray-11" = "Taca 11"; "media-source.tray-12" = "Taca 12"; "media-source.tray-13" = "Taca 13"; "media-source.tray-14" = "Taca 14"; "media-source.tray-15" = "Taca 15"; "media-source.tray-16" = "Taca 16"; "media-source.tray-17" = "Taca 17"; "media-source.tray-18" = "Taca 18"; "media-source.tray-19" = "Taca 19"; "media-source.tray-2" = "Taca 2"; "media-source.tray-20" = "Taca 20"; "media-source.tray-3" = "Taca 3"; "media-source.tray-4" = "Taca 4"; "media-source.tray-5" = "Taca 5"; "media-source.tray-6" = "Taca 6"; "media-source.tray-7" = "Taca 7"; "media-source.tray-8" = "Taca 8"; "media-source.tray-9" = "Taca 9"; "media-tracking" = "Śledzenie nośników"; "media-tracking.continuous" = "Ciągłe"; "media-tracking.gap" = "Dystans"; "media-tracking.mark" = "Znacznik"; "media-tracking.web" = "Internet"; "media-type" = "Typ nośników"; "media-type.aluminum" = "Aluminium"; "media-type.auto" = "Automatyczny"; "media-type.back-print-film" = "Folia nadrukowana z tyłu"; "media-type.cardboard" = "Karton"; "media-type.cardstock" = "Karta"; "media-type.cd" = "CD"; "media-type.continuous" = "Ciągły"; "media-type.continuous-long" = "Ciągły (długi)"; "media-type.continuous-short" = "Ciągły (krótki)"; "media-type.corrugated-board" = "Tektura falista"; "media-type.disc" = "Dysk optyczny"; "media-type.disc-glossy" = "Dysk optyczny błyszczący"; "media-type.disc-high-gloss" = "Dysk optyczny o wysokim połysku"; "media-type.disc-matte" = "Dysk optyczny matowy"; "media-type.disc-satin" = "Dysk optyczny satynowy"; "media-type.disc-semi-gloss" = "Dysk optyczny półbłyszczący"; "media-type.double-wall" = "Dwuścienny"; "media-type.dry-film" = "Folia sucha"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Folia tłoczona"; "media-type.end-board" = "Burta tylna"; "media-type.envelope" = "Koperta"; "media-type.envelope-archival" = "Koperta do archiwizacji"; "media-type.envelope-bond" = "Koperta bond"; "media-type.envelope-coated" = "Koperta powlekana"; "media-type.envelope-cotton" = "Koperta bawełniana"; "media-type.envelope-fine" = "Koperta drobna"; "media-type.envelope-heavyweight" = "Koperta o dużej gramaturze"; "media-type.envelope-inkjet" = "Koperta do druku atramentowego"; "media-type.envelope-lightweight" = "Koperta o lekkiej gramaturze"; "media-type.envelope-plain" = "Koperta zwykła"; "media-type.envelope-preprinted" = "Koperta z nadrukiem"; "media-type.envelope-window" = "Koperta z okienkiem"; "media-type.fabric" = "Tkanina"; "media-type.fabric-archival" = "Tkanina do archiwizacji"; "media-type.fabric-glossy" = "Tkanina błyszcząca"; "media-type.fabric-high-gloss" = "Tkanina o wysokim połysku"; "media-type.fabric-matte" = "Tkanina matowa"; "media-type.fabric-semi-gloss" = "Tkanina półbłyszcząca"; "media-type.fabric-waterproof" = "Tkanina wodoodporna"; "media-type.film" = "Film"; "media-type.flexo-base" = "Baza fleksograficzna"; "media-type.flexo-photo-polymer" = "Fotopolimer fleksograficzny"; "media-type.flute" = "Flet"; "media-type.foil" = "Folia"; "media-type.full-cut-tabs" = "Zakładki pełne"; "media-type.glass" = "Szkło"; "media-type.glass-colored" = "Szkło barwione"; "media-type.glass-opaque" = "Szkło nieprzezroczyste"; "media-type.glass-surfaced" = "Szkło wypolerowane"; "media-type.glass-textured" = "Szkło teksturowane"; "media-type.gravure-cylinder" = "Cylinder wklęsły"; "media-type.image-setter-paper" = "Papier do naświetlania"; "media-type.imaging-cylinder" = "Cylinder obrazujący"; "media-type.labels" = "Etykiety"; "media-type.labels-colored" = "Etykiety barwione"; "media-type.labels-glossy" = "Etykiety błyszczące"; "media-type.labels-high-gloss" = "Etykiety o wysokim połysku"; "media-type.labels-inkjet" = "Etykiety do druku atramentowego"; "media-type.labels-matte" = "Etykiety matowe"; "media-type.labels-permanent" = "Etykiety trwałe"; "media-type.labels-satin" = "Etykiety satynowe"; "media-type.labels-security" = "Etykiety zabezpieczające"; "media-type.labels-semi-gloss" = "Etykiety półbłyszczące"; "media-type.laminating-foil" = "Folia do laminowania"; "media-type.letterhead" = "Blankiet firmowy"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal błyszczący"; "media-type.metal-high-gloss" = "Metal o wysokim połysku"; "media-type.metal-matte" = "Metal matowy"; "media-type.metal-satin" = "Metal satynowy"; "media-type.metal-semi-gloss" = "Metal półbłyszczący"; "media-type.mounting-tape" = "Taśma montażowa"; "media-type.multi-layer" = "Wielowarstwowy"; "media-type.multi-part-form" = "Formularz wieloczęściowy"; "media-type.other" = "Inny"; "media-type.paper" = "Papier"; "media-type.photographic" = "Papier fotograficzny"; "media-type.photographic-archival" = "Fotograficzna do archiwizacji"; "media-type.photographic-film" = "Film fotograficzny"; "media-type.photographic-glossy" = "Papier fotograficzny błyszczący"; "media-type.photographic-high-gloss" = "Papier fotograficzny o wysokim połysku"; "media-type.photographic-matte" = "Papier fotograficzny matowy"; "media-type.photographic-satin" = "Papier fotograficzny satynowy"; "media-type.photographic-semi-gloss" = "Papier fotograficzny półbłyszczący"; "media-type.plastic" = "Plastik"; "media-type.plastic-archival" = "Plastik do archiwizacji"; "media-type.plastic-colored" = "Plastik barwiony"; "media-type.plastic-glossy" = "Plastik błyszczący"; "media-type.plastic-high-gloss" = "Plastik o wysokim połysku"; "media-type.plastic-matte" = "Plastik matowy"; "media-type.plastic-satin" = "Plastik satynowy"; "media-type.plastic-semi-gloss" = "Plastik półbłyszczący"; "media-type.plate" = "Płyta offsetowa"; "media-type.polyester" = "Poliester"; "media-type.pre-cut-tabs" = "Zakładki wstępnie przycięte"; "media-type.roll" = "Rolka"; "media-type.screen" = "Ekran"; "media-type.screen-paged" = "Ekran stronicowany"; "media-type.self-adhesive" = "Samoprzylepny"; "media-type.self-adhesive-film" = "Folia samoprzylepna"; "media-type.shrink-foil" = "Folia termokurczliwa"; "media-type.single-face" = "Powierzchnia pojedyncza"; "media-type.single-wall" = "Jednościenny"; "media-type.sleeve" = "Koszulka"; "media-type.stationery" = "Materiały piśmienne"; "media-type.stationery-archival" = "Materiały piśmienne do archiwizacji"; "media-type.stationery-coated" = "Papier powlekany"; "media-type.stationery-cotton" = "Materiały piśmienne bawełniane"; "media-type.stationery-fine" = "Papier welinowy"; "media-type.stationery-heavyweight" = "Papier o dużej gramaturze"; "media-type.stationery-heavyweight-coated" = "Materiały piśmienne o dużej gramaturze, powlekane"; "media-type.stationery-inkjet" = "Papier biurowy do druku atramentowego"; "media-type.stationery-letterhead" = "Blankiet firmowy"; "media-type.stationery-lightweight" = "Papier o lekkiej gramaturze"; "media-type.stationery-preprinted" = "Papier wstępnie zadrukowany"; "media-type.stationery-prepunched" = "Papier dziurkowany"; "media-type.tab-stock" = "Papier z zakładkami"; "media-type.tractor" = "Traktor"; "media-type.transfer" = "Transferowy"; "media-type.transparency" = "Przezroczysty"; "media-type.triple-wall" = "Trójścienny"; "media-type.wet-film" = "Film wilgotny"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 lub US Letter"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (extra)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (extra)"; "media.iso_a4-tab_225x297mm" = "A4 (tab)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (extra)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (extra)"; "media.iso_b5_176x250mm" = "B5 Koperta"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4 Koperta"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Koperta"; "media.iso_c10_28x40mm" = "C10 Koperta"; "media.iso_c1_648x917mm" = "C1 Koperta"; "media.iso_c2_458x648mm" = "C2 Koperta"; "media.iso_c3_324x458mm" = "C3 Koperta"; "media.iso_c4_229x324mm" = "C4 Koperta"; "media.iso_c5_162x229mm" = "C5 Koperta"; "media.iso_c6_114x162mm" = "C6 Koperta"; "media.iso_c6c5_114x229mm" = "C6/C5 Koperta"; "media.iso_c7_81x114mm" = "C7 Koperta"; "media.iso_c7c6_81x162mm" = "C7/C6 Koperta"; "media.iso_c8_57x81mm" = "C8 Koperta"; "media.iso_c9_40x57mm" = "C9 Koperta"; "media.iso_dl_110x220mm" = "DL Koperta"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Executive"; "media.jpn_chou2_111.1x146mm" = "Koperta Chou 2"; "media.jpn_chou3_120x235mm" = "Koperta Chou 3"; "media.jpn_chou40_90x225mm" = "Koperta Chou 40"; "media.jpn_chou4_90x205mm" = "Koperta Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Koperta Kahu"; "media.jpn_kaku2_240x332mm" = "Koperta Kahu 2"; "media.jpn_oufuku_148x200mm" = "Pocztówka z odpowiedzią (Oufuku Reply Postcard)"; "media.jpn_you4_105x235mm" = "Koperta You 4"; "media.na_a2_4.375x5.75in" = "Koperta A2"; "media.na_c5_6.5x9.5in" = "Koperta C5"; "media.na_executive_7.25x10.5in" = "Executive"; "media.na_fanfold-eur_8.5x12in" = "Składanka europejska"; "media.na_fanfold-us_11x14.875in" = "Składanka amerykańska"; "media.na_foolscap_8.5x13in" = "Papier kancelaryjny"; "media.na_invoice_5.5x8.5in" = "Oświadczenie"; "media.na_legal-extra_9.5x15in" = "US Legal (Extra)"; "media.na_legal_8.5x14in" = "US Legal"; "media.na_letter-extra_9.5x12in" = "US Letter (Extra)"; "media.na_letter-plus_8.5x12.69in" = "US Letter (Plus)"; "media.na_letter_8.5x11in" = "US Letter"; "media.na_monarch_3.875x7.5in" = "Koperta Monarch"; "media.na_number-10_4.125x9.5in" = "Koperta #10"; "media.na_number-11_4.5x10.375in" = "Koperta #11"; "media.na_number-12_4.75x11in" = "Koperta #12"; "media.na_number-14_5x11.5in" = "Koperta #14"; "media.na_number-9_3.875x8.875in" = "Koperta #9"; "media.na_personal_3.625x6.5in" = "Koperta Personal"; "media.na_quarto_8.5x10.83in" = "Quarto"; "media.om_folio-sp_215x315mm" = "Folio"; "media.om_folio_210x330mm" = "Folio (Special)"; "media.om_invite_220x220mm" = "Koperta zaproszeniowa"; "media.om_italian_110x230mm" = "Koperta włoska"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275 mm"; "media.om_large-photo_200x300" = "200 x 300 mm"; "media.om_medium-photo_130x180mm" = "130 x 180 mm"; "media.om_pa-kai_267x389mm" = "267 x 389 mm"; "media.om_postfix_114x229mm" = "Koperta Postfix"; "media.prc_10_324x458mm" = "Koperta chińska #10"; "media.prc_16k_146x215mm" = "Chińska 16k"; "media.prc_1_102x165mm" = "Koperta chińska #1"; "media.prc_2_102x176mm" = "Koperta chińska #2"; "media.prc_32k_97x151mm" = "Chińska 32k"; "media.prc_3_125x176mm" = "Koperta chińska #3"; "media.prc_4_110x208mm" = "Koperta chińska #4"; "media.prc_5_110x220mm" = "Koperta chińska #5"; "media.prc_6_120x320mm" = "Koperta chińska #6"; "media.prc_7_160x230mm" = "Koperta chińska #7"; "media.prc_8_120x309mm" = "Koperta chińska #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "nie skonfigurowano"; "not visible" = "niewidoczne"; "off" = "wyłączone"; "on" = "włączone"; "orientation-requested" = "Orientacja"; "orientation-requested.3" = "Pionowa"; "orientation-requested.4" = "Pozioma"; "orientation-requested.5" = "Pozioma (obrócona)"; "orientation-requested.6" = "Pionowa (obrócona)"; "orientation-requested.7" = "Brak"; "output-bin" = "Odbiornik"; "output-bin.auto" = "Automatyczny"; "output-bin.bottom" = "Dół"; "output-bin.center" = "Centrum"; "output-bin.face-down" = "Do dołu"; "output-bin.face-up" = "Do góry"; "output-bin.large-capacity" = "Duża pojemność"; "output-bin.left" = "Lewo"; "output-bin.mailbox-1" = "Skrzynka pocztowa 1"; "output-bin.mailbox-10" = "Skrzynka pocztowa 10"; "output-bin.mailbox-2" = "Skrzynka pocztowa 2"; "output-bin.mailbox-3" = "Skrzynka pocztowa 3"; "output-bin.mailbox-4" = "Skrzynka pocztowa 4"; "output-bin.mailbox-5" = "Skrzynka pocztowa 5"; "output-bin.mailbox-6" = "Skrzynka pocztowa 6"; "output-bin.mailbox-7" = "Skrzynka pocztowa 7"; "output-bin.mailbox-8" = "Skrzynka pocztowa 8"; "output-bin.mailbox-9" = "Skrzynka pocztowa 9"; "output-bin.middle" = "Środek"; "output-bin.my-mailbox" = "Moja skrzynka pocztowa"; "output-bin.rear" = "Tył"; "output-bin.right" = "Prawo"; "output-bin.side" = "Bok"; "output-bin.stacker-1" = "Zszywacz 1"; "output-bin.stacker-10" = "Zszywacz 10"; "output-bin.stacker-2" = "Zszywacz 2"; "output-bin.stacker-3" = "Zszywacz 3"; "output-bin.stacker-4" = "Zszywacz 4"; "output-bin.stacker-5" = "Zszywacz 5"; "output-bin.stacker-6" = "Zszywacz 6"; "output-bin.stacker-7" = "Zszywacz 7"; "output-bin.stacker-8" = "Zszywacz 8"; "output-bin.stacker-9" = "Zszywacz 9"; "output-bin.top" = "Góra"; "output-bin.tray-1" = "Taca 1"; "output-bin.tray-10" = "Taca 10"; "output-bin.tray-2" = "Taca 2"; "output-bin.tray-3" = "Taca 3"; "output-bin.tray-4" = "Taca 4"; "output-bin.tray-5" = "Taca 5"; "output-bin.tray-6" = "Taca 6"; "output-bin.tray-7" = "Taca 7"; "output-bin.tray-8" = "Taca 8"; "output-bin.tray-9" = "Taca 9"; "print-color-mode" = "Tryb drukowania"; "print-color-mode.auto" = "Automatyczny"; "print-color-mode.auto-monochrome" = "Auto. monochromia"; "print-color-mode.bi-level" = "Tekst"; "print-color-mode.color" = "Kolor"; "print-color-mode.highlight" = "Wyróżnienie"; "print-color-mode.monochrome" = "Monochromia"; "print-color-mode.process-bi-level" = "Przetwarzanie tekstu"; "print-color-mode.process-monochrome" = "Przetwarzanie monochromi"; "print-content-optimize" = "Optymalizuj pod kątem"; "print-content-optimize.auto" = "Automatycznie"; "print-content-optimize.graphic" = "Grafiki"; "print-content-optimize.photo" = "Zdjęć"; "print-content-optimize.text" = "Tekstu"; "print-content-optimize.text-and-graphic" = "Tekstu i grafiki"; "print-darkness" = "Ciemność wydruku"; "print-quality" = "Jakość wydruku"; "print-quality.3" = "Szkic"; "print-quality.4" = "Normalna"; "print-quality.5" = "Najlepsza"; "print-scaling" = "Skalowanie"; "print-scaling.auto" = "Automatyczne"; "print-scaling.auto-fit" = "Automatyczne dopasowanie"; "print-scaling.fill" = "Wypełnianie"; "print-scaling.fit" = "Dopasowanie"; "print-scaling.none" = "Brak"; "print-speed" = "Szybkość drukowania"; "printer-resolution" = "Rozdzielczość"; "printer-state-reasons.cover-open" = "Pokrywa otwarta."; "printer-state-reasons.door-open" = "Drzwi otwarte."; "printer-state-reasons.identify-printer-requested" = "Zidentyfikuj drukarkę."; "printer-state-reasons.input-tray-missing" = "Brak zasobnika papieru."; "printer-state-reasons.marker-supply-empty" = "Brak atramentu."; "printer-state-reasons.marker-supply-low" = "Niski poziom atramentu."; "printer-state-reasons.marker-waste-almost-full" = "Kosz na śmieci prawie pełny."; "printer-state-reasons.marker-waste-full" = "Kosz na śmieci pełny."; "printer-state-reasons.media-empty" = "Brak papieru."; "printer-state-reasons.media-jam" = "Zacięcie papieru."; "printer-state-reasons.media-low" = "Wkrótce wymień papier."; "printer-state-reasons.media-needed" = "Włóż papier."; "printer-state-reasons.none" = "Gotowa."; "printer-state-reasons.offline" = "Offline."; "printer-state-reasons.other" = "Zobacz drukarkę."; "printer-state-reasons.spool-area-full" = "Drukarka zajęta."; "printer-state-reasons.toner-empty" = "Brak tonera."; "printer-state-reasons.toner-low" = "Niski poziom tonera."; "printer-state.3" = "Bezczynna"; "printer-state.4" = "Przetwarzanie"; "printer-state.5" = "Zatrzymana"; "sides" = "Drukowanie dwustronne"; "sides.one-sided" = "Wyłączone"; "sides.two-sided-long-edge" = "Wyłączone (pionowo)"; "sides.two-sided-short-edge" = "Wyłączone (poziomo)"; "unable to join" = "nie można dołączyć"; "yesterday at %02d:%02d:%02d" = "wczoraj o %02d:%02d:%02d"; "Åland Islands" = "Wyspy Alandzkie"; pappl-1.4.9/pappl/strings/pl_strings.h000066400000000000000000001616451476704353100200320ustar00rootroot00000000000000static const char *pl_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Anuluj wszystkie zadania (cancel).\";\n" "\" -c COPIES\" = \" -c KOPIE\";\n" "\" -d PRINTER Specify printer.\" = \" -d DRUKARKA Określ drukarkę.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j ID-ZADANIA Określ identyfikator zadania (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m NAZWA-STEROWNIKA Określ sterownik (add/modify).\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n KOPIE Określ liczbę kopii (submit).\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (default)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o NAZWA=WARTOŚĆ Określ opcję (add,modify,server,submit).\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 do 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 do 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:SZEROKOŚĆ,DŁUGOŚĆ'\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='LOKALIZACJA'\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANIZACJA'\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='JEDNOSTKA/SEKCJA'\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI Określ ipp: lub ipps: drukarka/serwer.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v URI-URZĄDZENIA Podaj gniazdo: lub usb: urządzenie (add/modify).\";\n" "\" add PRINTER Add a printer.\" = \" add DRUKARKA Dodaj drukarkę.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Automatyczne dodawanie obsługiwanych drukarek.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Anuluj jedno lub więcej zadań.\";\n" "\" default Set the default printer.\" = \" default Ustaw domyślną drukarkę.\";\n" "\" delete Delete a printer.\" = \" delete Usuń drukarkę.\";\n" "\" devices List devices.\" = \" devices Wyświetl listę urządzeń.\";\n" "\" drivers List drivers.\" = \" drivers Wyświetl listę sterowników.\";\n" "\" jobs List jobs.\" = \" jobs Wyświetl listę zadań.\";\n" "\" modify Modify a printer.\" = \" modify Zmodyfikuj drukarkę.\";\n" "\" options List printer options.\" = \" options Wyświetl listę opcji drukarki.\";\n" "\" pause Pause printing for a printer.\" = \" pause Wstrzymaj drukowanie drukarki.\";\n" "\" printers List printers.\" = \" printers Wyświetl listę drukarek.\";\n" "\" resume Resume printing for a printer.\" = \" resume Wznów drukowanie drukarki.\";\n" "\" server Run a server.\" = \" server Uruchom serwer.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Wyłącz uruchomiony serwer.\";\n" "\" status Show server/printer/job status.\" = \" status Pokaż stan serwera/drukarki/zadania.\";\n" "\" submit Submit a file for printing.\" = \" submit Prześlij plik do druku.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d.%02d.%02d o %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d dni temu o %02d:%02d:%02d\";\n" "\"%d inches/sec\" = \"%d in/s\";\n" "\"%d job\" = \"%d zadanie\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %d mm\";\n" "\"%ddpi\" = \"%d dpi\";\n" "\"%dx%ddpi\" = \"%d x %d dpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g\\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s (%s%s)\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) z %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Nośnik\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Nieprawidłowa wartość 'server-port'.\";\n" "\"%s: Bad job ID.\" = \"%s: Nieprawidłowy identyfikator zadania.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Nieprawidłowy URI drukarki '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Nie można określić więcej niż jednego polecenia podrzędnego.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Odebrano pusty plik do wydruku na standardowym wejściu.\";\n" "\"%s: Failed to create a system.\" = \"%s: Nie udało się utworzyć systemu.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: Brak '-d DRUKARKA'.\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: Brak '-m NAZWA-STEROWNIKA'.\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: Brak '-v URI-URZĄDZENIA'.\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: Brak liczby kopii po '-n'.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: Brak URI urządzenia po '-v'.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: Brak nazwy sterownika po '-m'.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: Brak nazwy pliku po '--'.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: Brak nazwy hosta po '-h'.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: Brak identyfikatora zadania po '-j'.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: Brak opcji po '-o'.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: Brak URI drukarki po '-u'.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: Brak nazwy drukarki po '-d'.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: Brak spacji po '-o'.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: Brak tytułu po '-t'.\";\n" "\"%s: No default printer available.\" = \"%s: Brak dostępnej drukarki domyślnej.\";\n" "\"%s: No files to print.\" = \"%s: Brak plików do wydrukowania.\";\n" "\"%s: Server is not running.\" = \"%s: Serwer nie jest uruchomiony.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: Podpolecenie '%s' nie akceptuje plików.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: Podpolecenie 'autoadd' nie jest obsługiwane.\";\n" "\"%s: Too many files.\" = \"%s: Zbyt wiele plików.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: Nie można uzyskać dostępu do '%s': %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Nie można dodać drukarki: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: Nie można anulować zadania: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: Nie można połączyć się z drukarką w '%s:%d': %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Nie można połączyć się z serwerem: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Nie można utworzyć pliku tymczasowego: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Nie można usunąć drukarki: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Nie można uzyskać dostępnych urządzeń: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: Nie można uzyskać informacji o '%s': %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Nie można uzyskać informacji o drukarce: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Nie można uzyskać opcji drukarki: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Nie można zmodyfikować drukarki: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Nie można wstrzymać drukarki: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: Nie można wydrukować '%s': %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Nie można wznowić drukarki: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Nie można ustawić domyślnej drukarki: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Nie można wyłączyć serwera: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Nie można uruchomić serwera: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Nie można zapisać do pliku tymczasowego: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Nieznana opcja '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Nieznana opcja '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Nieznane podpolecenie '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Nieobsługiwany schemat URI '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Ostrzeżenie — poświadczenia użytkownika nie są obsługiwane w URI.\";\n" "\", Borderless\" = \", Bez obramowania\";\n" "\"A printer with that name already exists.\" = \"Drukarka o tej nazwie już istnieje.\";\n" "\"Aborted %s\" = \"Przerwano %s\";\n" "\"Add Printer\" = \"Dodaj drukarkę\";\n" "\"Admin Group\" = \"Grupa administratorów\";\n" "\"Afghanistan\" = \"Afganistan\";\n" "\"Albania\" = \"Albania\";\n" "\"Algeria\" = \"Algieria\";\n" "\"American Samoa\" = \"Samoa Amerykańskie\";\n" "\"Andorra\" = \"Andora\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarktyda\";\n" "\"Antigua and Barbuda\" = \"Antigua i Barbuda\";\n" "\"Argentina\" = \"Argentyna\";\n" "\"Armenia\" = \"Armenia\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Australia\";\n" "\"Austria\" = \"Austria\";\n" "\"Auto\" = \"Automatycznie\";\n" "\"Auto-Detect Driver\" = \"Automatyczne wykrywanie sterownika\";\n" "\"Azerbaijan\" = \"Azerbejdżan\";\n" "\"Bad administration group.\" = \"Zła grupa administracyjna.\";\n" "\"Bad port number.\" = \"Zły numer portu.\";\n" "\"Bad print group.\" = \"Zła grupa drukowania.\";\n" "\"Bad printer defaults.\" = \"Złe ustawienia domyślne drukarki.\";\n" "\"Bahamas\" = \"Bahamy\";\n" "\"Bahrain\" = \"Bahrajn\";\n" "\"Bangladesh\" = \"Bangladesz\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Białoruś\";\n" "\"Belgium\" = \"Belgia\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermudy\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Boliwia (Wielonarodowe Państwo Boliwia)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius i Saba\";\n" "\"Borderless\" = \"Bez obramowania\";\n" "\"Bosnia and Herzegovina\" = \"Bośnia i Hercegowina\";\n" "\"Botswana\" = \"Botswana\";\n" "\"Bouvet Island\" = \"Wyspa Bouveta\";\n" "\"Brazil\" = \"Brazylia\";\n" "\"British Indian Ocean Territory\" = \"Brytyjskie Terytorium Oceanu Indyjskiego\";\n" "\"Brunei Darussalam\" = \"Brunei Darussalam\";\n" "\"Bulgaria\" = \"Bułgaria\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Republika Zielonego Przylądka\";\n" "\"Cambodia\" = \"Kambodża\";\n" "\"Cameroon\" = \"Kamerun\";\n" "\"Canada\" = \"Kanada\";\n" "\"Cancel All Jobs\" = \"Anuluj wszystkie zadania\";\n" "\"Cancel Job\" = \"Anuluj zadanie\";\n" "\"Canceled %s\" = \"Anulowano %s\";\n" "\"Canceling\" = \"Anulowanie\";\n" "\"Cayman Islands\" = \"Kajmany\";\n" "\"Central African Republic\" = \"Republika Środkowoafrykańska\";\n" "\"Certificate created.\" = \"Certyfikat utworzony.\";\n" "\"Certificate installed.\" = \"Certyfikat zainstalowany.\";\n" "\"Certificate request created.\" = \"Żądanie certyfikatu utworzone.\";\n" "\"Chad\" = \"Czad\";\n" "\"Change Access Password\" = \"Zmień hasło dostępu\";\n" "\"Change Log Level\" = \"Zmień poziom dziennika\";\n" "\"Change Network Settings\" = \"Zmień ustawienia sieciowe\";\n" "\"Change Wi-Fi Network\" = \"Zmień sieć Wi-Fi\";\n" "\"Changes Saved.\" = \"Zmiany zapisane.\";\n" "\"Changes saved.\" = \"Zmiany zapisane.\";\n" "\"Chile\" = \"Chile\";\n" "\"China\" = \"Chiny\";\n" "\"Christmas Island\" = \"Wyspa Bożego Narodzenia\";\n" "\"City/Locality\" = \"Miasto/Miejscowość\";\n" "\"Cocos (Keeling) Islands\" = \"Wyspy Kokosowe (Keelinga)\";\n" "\"Colombia\" = \"Kolumbia\";\n" "\"Comoros\" = \"Komory\";\n" "\"Completed %s\" = \"Ukończono %s\";\n" "\"Configuration\" = \"Konfiguracja\";\n" "\"Configure Media\" = \"Konfigurowanie nośników\";\n" "\"Confirm Cancel All\" = \"Potwierdź anulowanie wszystkiego\";\n" "\"Confirm Delete Printer\" = \"Potwierdź usunięcie drukarki\";\n" "\"Congo\" = \"Kongo\";\n" "\"Congo, Democratic Republic of the\" = \"Kongo, Republika Demokratyczna\";\n" "\"Contact\" = \"Kontakt\";\n" "\"Cook Islands\" = \"Wyspy Cooka\";\n" "\"Costa Rica\" = \"Kostaryka\";\n" "\"Create Certificate Signing Request\" = \"Utwórz żądanie podpisania certyfikatu\";\n" "\"Create New Certificate\" = \"Utwórz nowy certyfikat\";\n" "\"Create New TLS Certificate\" = \"Utwórz nowy certyfikat TLS\";\n" "\"Create TLS Certificate Request\" = \"Utwórz żądanie certyfikatu TLS\";\n" "\"Croatia\" = \"Chorwacja\";\n" "\"Cuba\" = \"Kuba\";\n" "\"Curaçao\" = \"Curaçao\";\n" "\"Current Password\" = \"Aktualne hasło\";\n" "\"Custom Size\" = \"Rozmiar niestandardowy\";\n" "\"Cyprus\" = \"Cypr\";\n" "\"Czechia\" = \"Czechy\";\n" "\"Côte d'Ivoire\" = \"Wybrzeże Kości Słoniowej\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP z adresem ręcznym\";\n" "\"DNS-SD Service Name\" = \"Nazwa usługi DNS-SD\";\n" "\"Debugging\" = \"Debugowanie\";\n" "\"Default printer set.\" = \"Domyślny zestaw drukarki.\";\n" "\"Delete\" = \"Usuń\";\n" "\"Delete Printer\" = \"Usuń drukarkę\";\n" "\"Denmark\" = \"Dania\";\n" "\"Djibouti\" = \"Dżibuti\";\n" "\"Domain Name\" = \"Nazwa domeny\";\n" "\"Dominica\" = \"Dominika\";\n" "\"Dominican Republic\" = \"Republika Dominikany\";\n" "\"Download Certificate Request File\" = \"Pobierz plik żądania certyfikatu\";\n" "\"Ecuador\" = \"Ekwador\";\n" "\"Egypt\" = \"Egipt\";\n" "\"El Salvador\" = \"Salwador\";\n" "\"Equatorial Guinea\" = \"Gwinea Równikowa\";\n" "\"Eritrea\" = \"Erytrea\";\n" "\"Errors\" = \"Błędy\";\n" "\"Estonia\" = \"Estonia\";\n" "\"Eswatini\" = \"Eswatini\";\n" "\"Ethiopia\" = \"Etiopia\";\n" "\"Falkland Islands (Malvinas)\" = \"Falklandy (Malwiny)\";\n" "\"Faroe Islands\" = \"Wyspy Owcze\";\n" "\"Fatal Errors/Conditions\" = \"Krytyczne błędy/warunki\";\n" "\"Fiji\" = \"Fidżi\";\n" "\"Finland\" = \"Finlandia\";\n" "\"France\" = \"Francja\";\n" "\"French Guiana\" = \"Gujana Francuska\";\n" "\"French Polynesia\" = \"Polinezja Francuska\";\n" "\"French Southern Territories\" = \"Francuskie Terytoria Południowe\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambia\";\n" "\"Georgia\" = \"Gruzja\";\n" "\"Germany\" = \"Niemcy\";\n" "\"Ghana\" = \"Ghana\";\n" "\"Gibraltar\" = \"Gibraltar\";\n" "\"Greece\" = \"Grecja\";\n" "\"Greenland\" = \"Grenlandia\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Zmiany w grupie zapisane.\";\n" "\"Guadeloupe\" = \"Gwadelupa\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Gwatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Gwinea\";\n" "\"Guinea-Bissau\" = \"Gwinea Bissau\";\n" "\"Guyana\" = \"Gujana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Wyspy Heard i McDonalda\";\n" "\"Hidden SSID\" = \"Ukryty SSID\";\n" "\"Hold Job\" = \"Wstrzymaj zadanie\";\n" "\"Hold New Jobs\" = \"Wstrzymuj nowe zadania\";\n" "\"Holding new jobs.\" = \"Wstrzymywanie nowych zadań.\";\n" "\"Holy See\" = \"Stolica Apostolska\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hongkong\";\n" "\"Hostname\" = \"Nazwa hosta\";\n" "\"Human-Readable Location\" = \"Lokalizacja czytelna dla człowieka\";\n" "\"Hungary\" = \"Węgry\";\n" "\"IPv4 Address\" = \"Adres IPv4\";\n" "\"IPv4 Configuration\" = \"Konfiguracja IPv4\";\n" "\"IPv4 Gateway\" = \"Brama IPv4\";\n" "\"IPv4 Netmask\" = \"Maska sieci IPv4\";\n" "\"IPv6 Address\" = \"Adres IPv6\";\n" "\"IPv6 Configuration\" = \"Konfiguracja IPv6\";\n" "\"IPv6 Link-Local\" = \"Łącze lokalne IPv6\";\n" "\"IPv6 Prefix Length\" = \"Długość prefiksu IPv6\";\n" "\"Iceland\" = \"Islandia\";\n" "\"Identify Printer\" = \"Zidentyfikuj drukarkę\";\n" "\"India\" = \"Indie\";\n" "\"Indonesia\" = \"Indonezja\";\n" "\"Informational\" = \"Informacyjny\";\n" "\"Install TLS Certificate\" = \"Zainstaluj certyfikat TLS\";\n" "\"Invalid IPv4 address.\" = \"Nieprawidłowy adres IPv4.\";\n" "\"Invalid IPv4 netmask.\" = \"Nieprawidłowa maska sieci IPv4.\";\n" "\"Invalid IPv6 address.\" = \"Nieprawidłowy adres IPv6.\";\n" "\"Invalid IPv6 prefix length.\" = \"Nieprawidłowa długość prefiksu IPv6.\";\n" "\"Invalid Job ID.\" = \"Nieprawidłowy identyfikator zadania.\";\n" "\"Invalid certificate or private key.\" = \"Nieprawidłowy certyfikat lub klucz prywatny.\";\n" "\"Invalid form data.\" = \"Nieprawidłowe dane formularza.\";\n" "\"Invalid form submission.\" = \"Nieprawidłowe wysłanie formularza.\";\n" "\"Invalid job ID.\" = \"Nieprawidłowy identyfikator zadania.\";\n" "\"Invalid network configuration.\" = \"Nieprawidłowa konfiguracja sieci.\";\n" "\"Iran (Islamic Republic of)\" = \"Iran (Islamska Republika Iranu)\";\n" "\"Iraq\" = \"Irak\";\n" "\"Ireland\" = \"Irlandia\";\n" "\"Isle of Man\" = \"Wyspa Man\";\n" "\"Israel\" = \"Izrael\";\n" "\"Italy\" = \"Włochy\";\n" "\"Jamaica\" = \"Jamajka\";\n" "\"Japan\" = \"Japonia\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"Zadanie #\";\n" "\"Job canceled.\" = \"Zadanie anulowane.\";\n" "\"Job held.\" = \"Zadanie wstrzymane.\";\n" "\"Job released.\" = \"Zadanie wznowione.\";\n" "\"Jobs\" = \"Zadania\";\n" "\"Joining Wi-Fi Network\" = \"Dołączanie do sieci Wi-Fi\";\n" "\"Jordan\" = \"Jordania\";\n" "\"Kazakhstan\" = \"Kazachstan\";\n" "\"Kenya\" = \"Kenia\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Korea (Koreańska Republika Ludowo-Demokratyczna)\";\n" "\"Korea, Republic of\" = \"Korea (Republika Korei)\";\n" "\"Kuwait\" = \"Kuwejt\";\n" "\"Kyrgyzstan\" = \"Kirgistan\";\n" "\"Landscape\" = \"Poziomo\";\n" "\"Lao People's Democratic Republic\" = \"Laotańska Republika Ludowo-Demokratyczna\";\n" "\"Latvia\" = \"Łotwa\";\n" "\"Lebanon\" = \"Liban\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Poziom\";\n" "\"Liberia\" = \"Liberia\";\n" "\"Libya\" = \"Libia\";\n" "\"Liechtenstein\" = \"Liechtenstein\";\n" "\"Lithuania\" = \"Litwa\";\n" "\"Location\" = \"Lokalizacja\";\n" "\"Log Level\" = \"Poziom dziennika\";\n" "\"Logging\" = \"Rejestrowanie\";\n" "\"Logs\" = \"Dzienniki\";\n" "\"Luxembourg\" = \"Luksemburg\";\n" "\"Macao\" = \"Makao\";\n" "\"Madagascar\" = \"Madagaskar\";\n" "\"Malawi\" = \"Malawi\";\n" "\"Malaysia\" = \"Malezja\";\n" "\"Maldives\" = \"Malediwy\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Konfiguracja ręczna\";\n" "\"Marshall Islands\" = \"Wyspy Marshalla\";\n" "\"Martinique\" = \"Martynika\";\n" "\"Mauritania\" = \"Mauretania\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Majotta\";\n" "\"Media\" = \"Nośniki\";\n" "\"Mexico\" = \"Meksyk\";\n" "\"Micronesia (Federated States of)\" = \"Mikronezja (Sfederowane Stany Mikronezji)\";\n" "\"Missing action.\" = \"Brak działania.\";\n" "\"Missing job ID.\" = \"Brak identyfikatora zadania.\";\n" "\"Missing network name.\" = \"Brak nazwy sieci.\";\n" "\"Missing private key.\" = \"Brak klucza prywatnego.\";\n" "\"Moldova, Republic of\" = \"Mołdawia, Republika Mołdawii\";\n" "\"Monaco\" = \"Monako\";\n" "\"Mongolia\" = \"Mongolia\";\n" "\"Montenegro\" = \"Czarnogóra\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Maroko\";\n" "\"Mozambique\" = \"Mozambik\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Nazwa\";\n" "\"Namibia\" = \"Namibia\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Holandia\";\n" "\"Network\" = \"Sieć\";\n" "\"Network Printer\" = \"Drukarka sieciowa\";\n" "\"Networking\" = \"Sieciowość\";\n" "\"New Caledonia\" = \"Nowa Kaledonia\";\n" "\"New Zealand\" = \"Nowa Zelandia\";\n" "\"Nicaragua\" = \"Nikaragua\";\n" "\"Niger\" = \"Niger\";\n" "\"Nigeria\" = \"Nigeria\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"Nie ustawiono drukarki domyślnej.\";\n" "\"No jobs in history.\" = \"Nie ma zadań w historii.\";\n" "\"Norfolk Island\" = \"Wyspa Norfolk\";\n" "\"North Macedonia\" = \"Macedonia Północna\";\n" "\"Northern Mariana Islands\" = \"Mariany Północne\";\n" "\"Norway\" = \"Norwegia\";\n" "\"Not set\" = \"Nie ustawiono\";\n" "\"Off\" = \"Wyłączony\";\n" "\"Offset\" = \"Przesunięcie\";\n" "\"Oman\" = \"Oman\";\n" "\"Options:\" = \"Opcje:\";\n" "\"Organization\" = \"Organizacja\";\n" "\"Organization Name\" = \"Nazwa organizacji\";\n" "\"Other Settings\" = \"Inne ustawienia\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Palestyna, Państwo Palestyna\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua Nowa Gwinea\";\n" "\"Paraguay\" = \"Paragwaj\";\n" "\"Password\" = \"Hasło\";\n" "\"Password changed.\" = \"Hasło zostało zmienione.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Hasło musi mieć co najmniej osiem znaków i zawierać co najmniej jedną wielką literę, jedną małą literę i jedną cyfrę.\";\n" "\"Passwords do not match.\" = \"Hasła nie pasują do siebie.\";\n" "\"Pause Printing\" = \"Wstrzymaj drukowanie\";\n" "\"Peru\" = \"Peru\";\n" "\"Philippines\" = \"Filipiny\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Wprowadź nazwę hosta lub adres IP drukarki.\";\n" "\"Please enter a printer name.\" = \"Wprowadź nazwę drukarki.\";\n" "\"Please select a device.\" = \"Wybierz urządzenie.\";\n" "\"Please select a driver.\" = \"Wybierz sterownik.\";\n" "\"Please select a valid log level.\" = \"Wybierz odpowiedni poziom rejestrowania.\";\n" "\"Poland\" = \"Polska\";\n" "\"Portrait\" = \"Pionowo\";\n" "\"Portugal\" = \"Portugalia\";\n" "\"Primary DNS\" = \"Podstawowy DNS\";\n" "\"Print Group\" = \"Grupa drukowania\";\n" "\"Print Test Page\" = \"Wydrukuj stronę testową\";\n" "\"Print job options:\" = \"Opcje zadania drukowania:\";\n" "\"Printer identified.\" = \"Drukarka zidentyfikowana.\";\n" "\"Printer is currently active.\" = \"Drukarka jest obecnie aktywna.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Nazwy drukarek muszą zaczynać się od litery lub podkreślenia i nie mogą zawierać znaków specjalnych.\";\n" "\"Printer options:\" = \"Opcje drukarki:\";\n" "\"Printer paused.\" = \"Drukarka wstrzymana.\";\n" "\"Printer pausing.\" = \"Wstrzymanie drukarki.\";\n" "\"Printer resuming.\" = \"Wznawianie drukarki.\";\n" "\"Printers\" = \"Drukarki\";\n" "\"Printing Defaults\" = \"Ustawienia domyślne drukowania\";\n" "\"Puerto Rico\" = \"Portoryko\";\n" "\"Qatar\" = \"Katar\";\n" "\"Queued %s\" = \"W kolejce %s\";\n" "\"Release Held New Jobs\" = \"Wznów wstrzymane nowe zadania\";\n" "\"Release Job\" = \"Wznów zadanie\";\n" "\"Released held new jobs.\" = \"Wznowiono wstrzymane nowe zadania.\";\n" "\"Reprint Job\" = \"Zadanie przedruku\";\n" "\"Reprinted job.\" = \"Przedrukowane zadanie.\";\n" "\"Resume Printing\" = \"Wznów drukowanie\";\n" "\"Reverse Landscape\" = \"Poziomy (obrócony)\";\n" "\"Reverse Portrait\" = \"Pionowy (obrócony)\";\n" "\"Romania\" = \"Rumunia\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Uruchomiony, %s od %s%s.\";\n" "\"Russian Federation\" = \"Federacja Rosyjska\";\n" "\"Rwanda\" = \"Rwanda\";\n" "\"Réunion\" = \"Réunion\";\n" "\"Saint Barthélemy\" = \"Saint-Barthélemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Święta Helena, Wniebowstąpienie i Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts i Nevis\";\n" "\"Saint Lucia\" = \"Saint Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (część francuska)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint-Pierre i Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint Vincent i Grenadyny\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Wyspy Świętego Tomasza i Książęca\";\n" "\"Saudi Arabia\" = \"Arabia Saudyjska\";\n" "\"Save Changes\" = \"Zapisz zmiany\";\n" "\"Secondary DNS\" = \"Pomocniczy DNS\";\n" "\"Security\" = \"Bezpieczeństwo\";\n" "\"Select Driver\" = \"Wybierz sterownik\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Serbia\";\n" "\"Server is not running.\" = \"Serwer nie jest uruchomiony.\";\n" "\"Set Access Password\" = \"Ustaw hasło dostępu\";\n" "\"Set as Default\" = \"Ustaw jako domyślne\";\n" "\"Seychelles\" = \"Seszele\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapur\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (część holenderska)\";\n" "\"Slovakia\" = \"Słowacja\";\n" "\"Slovenia\" = \"Słowenia\";\n" "\"Solomon Islands\" = \"Wyspy Salomona\";\n" "\"Somalia\" = \"Somalia\";\n" "\"South Africa\" = \"Republika Południowej Afryki\";\n" "\"South Georgia and the South Sandwich Islands\" = \"Georgia Południowa i Sandwich Południowy\";\n" "\"South Sudan\" = \"Sudan Południowy\";\n" "\"Spain\" = \"Hiszpania\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"Rozpoczęto %s\";\n" "\"Status\" = \"Status\";\n" "\"Sub-commands:\" = \"Podkomendy:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Materiały eksploatacyjne\";\n" "\"Suriname\" = \"Surinam\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard i Jan Mayen\";\n" "\"Sweden\" = \"Szwecja\";\n" "\"Switzerland\" = \"Szwajcaria\";\n" "\"Syrian Arab Republic\" = \"Syryjska Republika Arabska\";\n" "\"Taiwan, Province of China\" = \"Tajwan (prowincja Republiki Chińskiej)\";\n" "\"Tajikistan\" = \"Tadżykistan\";\n" "\"Tanzania, United Republic of\" = \"Tanzania, Zjednoczona Republika Tanzanii\";\n" "\"Test page printed.\" = \"Strona testowa wydrukowana.\";\n" "\"Thailand\" = \"Tajlandia\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Ten formularz tworzy żądanie podpisania certyfikatu („CSR”), które można wysłać do urzędu certyfikacji („CA”) w celu uzyskania zaufanego certyfikatu TLS. Klucz prywatny jest zapisywany oddzielnie do użytku z certyfikatem otrzymanym od urzędu certyfikacji.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Ten formularz tworzy nowy „samopodpisany” certyfikat TLS do bezpiecznego drukowania. Certyfikaty z podpisem własnym nie są automatycznie uznawane za zaufane przez przeglądarki internetowe.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Ten formularz zainstaluje zaufany certyfikat TLS uzyskany od urzędu certyfikacji („CA”). Po zainstalowaniu będzie natychmiast używany.\";\n" "\"Timor-Leste\" = \"Timor Wschodni\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trynidad i Tobago\";\n" "\"Tunisia\" = \"Tunezja\";\n" "\"Turkey\" = \"Turcja\";\n" "\"Turkmenistan\" = \"Turkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Wyspy Turks i Caicos\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ukraina\";\n" "\"Unable to access test print file.\" = \"Nie można uzyskać dostępu do pliku wydruku testowego.\";\n" "\"Unable to copy print job.\" = \"Nie można skopiować zadania drukowania.\";\n" "\"Unable to create certificate request.\" = \"Nie można utworzyć żądania certyfikatu.\";\n" "\"Unable to create certificate.\" = \"Nie można utworzyć certyfikatu.\";\n" "\"Unable to create test print job.\" = \"Nie można utworzyć testowego zadania drukowania.\";\n" "\"Unable to identify printer.\" = \"Nie można zidentyfikować drukarki.\";\n" "\"Unable to lookup address.\" = \"Nie można wyszukać adresu.\";\n" "\"Unable to use that driver.\" = \"Nie można użyć tego sterownika.\";\n" "\"United Arab Emirates\" = \"Zjednoczone Emiraty Arabskie\";\n" "\"United Kingdom\" = \"Zjednoczone Królestwo\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Zjednoczone Królestwo Wielkiej Brytanii i Irlandii Północnej\";\n" "\"United States Minor Outlying Islands\" = \"Dalekie Wyspy Mniejsze Stanów Zjednoczonych\";\n" "\"United States of America\" = \"Stany Zjednoczone Ameryki\";\n" "\"Unknown\" = \"Nieznany\";\n" "\"Unknown action.\" = \"Nieznana czynność.\";\n" "\"Unknown form action.\" = \"Nieznana czynność formularza.\";\n" "\"Unknown form request.\" = \"Nieznane żądanie formularza.\";\n" "\"Updating Network Configuration\" = \"Aktualizowanie konfiguracji sieci\";\n" "\"Uruguay\" = \"Urugwaj\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Użycie: %s SUB-COMMAND [OPCJE] [NAZWA PLIKU]\\n\";\n" "\"Use My Position\" = \"Użyj mojej pozycji\";\n" "\"Users\" = \"Użytkownicy\";\n" "\"Uzbekistan\" = \"Uzbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Wenezuela (Boliwariańska Republika Wenezueli)\";\n" "\"Version %s\" = \"Wersja %\";\n" "\"Viet Nam\" = \"Wietnam\";\n" "\"View Logs\" = \"Wyświetl dzienniki\";\n" "\"Virgin Islands (British)\" = \"Wyspy Dziewicze (brytyjskie)\";\n" "\"Virgin Islands (U.S.)\" = \"Wyspy Dziewicze (amerykańskie)\";\n" "\"Wallis and Futuna\" = \"Wallis i Futuna\";\n" "\"Warning\" = \"Ostrzeżenie\";\n" "\"Western Sahara\" = \"Sahara Zachodnia\";\n" "\"Wi-Fi Configuration\" = \"Konfiguracja Wi-Fi\";\n" "\"Wi-Fi Network\" = \"Sieć Wi-Fi\";\n" "\"Width\" = \"Szerokość\";\n" "\"Wrong old password.\" = \"Nieprawidłowe stare hasło.\";\n" "\"Yemen\" = \"Jemen\";\n" "\"Zambia\" = \"Zambia\";\n" "\"Zimbabwe\" = \"Zimbabwe\";\n" "\"at %02d:%02d:%02d\" = \"o %02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Liczba kopii\";\n" "\"default printer\" = \"drukarka domyślna\";\n" "\"finishings\" = \"Wykończenie\";\n" "\"finishings.10\" = \"Składanie\";\n" "\"finishings.100\" = \"Składanie Z\";\n" "\"finishings.101\" = \"Inżynierskie składanie Z\";\n" "\"finishings.11\" = \"Cięcie\";\n" "\"finishings.12\" = \"Bela\";\n" "\"finishings.13\" = \"Kreator broszur\";\n" "\"finishings.15\" = \"Płaszcz\";\n" "\"finishings.16\" = \"Laminat\";\n" "\"finishings.20\" = \"Zszywka na górze po lewej\";\n" "\"finishings.21\" = \"Zszywka na dole po lewej\";\n" "\"finishings.22\" = \"Zszywka na górze po prawej\";\n" "\"finishings.23\" = \"Zszywka na dole po prawej\";\n" "\"finishings.24\" = \"Lewy ścieg brzegowy\";\n" "\"finishings.25\" = \"Górny ścieg brzegowy\";\n" "\"finishings.26\" = \"Prawy ścieg brzegowy\";\n" "\"finishings.27\" = \"Dolny ścieg brzegowy\";\n" "\"finishings.28\" = \"2 zszywki po lewej\";\n" "\"finishings.29\" = \"2 zszywki na górze\";\n" "\"finishings.3\" = \"Brak\";\n" "\"finishings.30\" = \"2 zszywki po prawej\";\n" "\"finishings.31\" = \"2 zszywki na dole\";\n" "\"finishings.32\" = \"3 zszywki po lewej\";\n" "\"finishings.33\" = \"3 zszywki na górze\";\n" "\"finishings.34\" = \"3 zszywki po prawej\";\n" "\"finishings.35\" = \"3 zszywki na dole\";\n" "\"finishings.4\" = \"Zszywka\";\n" "\"finishings.5\" = \"Dziurkacz\";\n" "\"finishings.50\" = \"Wiązanie po lewej\";\n" "\"finishings.51\" = \"Wiązanie na górze\";\n" "\"finishings.52\" = \"Wiązanie po prawej\";\n" "\"finishings.53\" = \"Wiązanie na dole\";\n" "\"finishings.6\" = \"Okładka\";\n" "\"finishings.60\" = \"Cięcie po każdej stronie\";\n" "\"finishings.61\" = \"Cięcie po każdym dokumencie\";\n" "\"finishings.62\" = \"Cięcie po każdym zestawie\";\n" "\"finishings.63\" = \"Cięcie po zadaniu\";\n" "\"finishings.7\" = \"Wiązanie\";\n" "\"finishings.70\" = \"Dziurkacz na górze po lewej\";\n" "\"finishings.71\" = \"Dziurkacz na dole po lewej\";\n" "\"finishings.72\" = \"Dziurkacz na górze po prawej\";\n" "\"finishings.73\" = \"Dziurkacz na dole po prawej\";\n" "\"finishings.74\" = \"2-otworowy dziurkacz po lewej\";\n" "\"finishings.75\" = \"2-otworowy dziurkacz na górze\";\n" "\"finishings.76\" = \"2-otworowy dziurkacz po prawej\";\n" "\"finishings.77\" = \"2-otworowy dziurkacz na dole\";\n" "\"finishings.78\" = \"3-otworowy dziurkacz po lewej\";\n" "\"finishings.79\" = \"3-otworowy dziurkacz na górze\";\n" "\"finishings.8\" = \"Ścieg siodłowy\";\n" "\"finishings.80\" = \"3-otworowy dziurkacz po prawej\";\n" "\"finishings.81\" = \"3-otworowy dziurkacz na dole\";\n" "\"finishings.82\" = \"4-otworowy dziurkacz po lewej\";\n" "\"finishings.83\" = \"4-otworowy dziurkacz na górze\";\n" "\"finishings.84\" = \"4-otworowy dziurkacz po prawej\";\n" "\"finishings.85\" = \"4-otworowy dziurkacz na dole\";\n" "\"finishings.86\" = \"Wielootworowy dziurkacz po lewej\";\n" "\"finishings.87\" = \"Wielootworowy dziurkacz na górze\";\n" "\"finishings.88\" = \"Wielootworowy dziurkacz po prawej\";\n" "\"finishings.89\" = \"Wielootworowy dziurkacz na dole\";\n" "\"finishings.9\" = \"Ścieg brzegowy\";\n" "\"finishings.90\" = \"Składanie akordeonowe\";\n" "\"finishings.91\" = \"Składanie podwójnej bramy\";\n" "\"finishings.92\" = \"Składanie bramy\";\n" "\"finishings.93\" = \"Składanie połowiczne\";\n" "\"finishings.94\" = \"Składanie połowiczne Z\";\n" "\"finishings.95\" = \"Składanie bramy lewej\";\n" "\"finishings.96\" = \"Składanie listu\";\n" "\"finishings.97\" = \"Składanie równoległe\";\n" "\"finishings.98\" = \"Składanie plakatu\";\n" "\"finishings.99\" = \"Składanie bramy prawej\";\n" "\"holding new jobs\" = \"wstrzymywanie nowych zadań\";\n" "\"job-state-reasons.aborted-by-system\" = \"Zatrzymanie.\";\n" "\"job-state-reasons.compression-error\" = \"Błąd dekompresji.\";\n" "\"job-state-reasons.document-format-error\" = \"Błąd formatu dokumentu.\";\n" "\"job-state-reasons.document-password-error\" = \"Błąd hasła dokumentu.\";\n" "\"job-state-reasons.document-permission-error\" = \"Błąd uprawnień do dokumentu.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Błąd uniemożliwiający drukowanie dokumentu.\";\n" "\"job-state-reasons.errors-detected\" = \"Wykryto błędy.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Anulowano w drukarce.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Anulowano przez użytkownika.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Wydrukowano.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Wydrukowano z błędami.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Wydrukowano z ostrzeżeniami.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Niewystarczające dane.\";\n" "\"job-state-reasons.job-fetchable\" = \"Do pobrania.\";\n" "\"job-state-reasons.job-incoming\" = \"Przychodzące.\";\n" "\"job-state-reasons.job-printing\" = \"Drukowanie.\";\n" "\"job-state-reasons.job-queued\" = \"Przygotowanie do drukowania.\";\n" "\"job-state-reasons.job-spooling\" = \"Buforowanie.\";\n" "\"job-state-reasons.none\" = \"W toku.\";\n" "\"job-state-reasons.printer-stopped\" = \"Drukarka offline.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Drukarka częściowo zatrzymana.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Zatrzymanie.\";\n" "\"job-state-reasons.queued-in-device\" = \"Gotowe.\";\n" "\"job-state-reasons.warnings-detected\" = \"Wykryto ostrzeżenia.\";\n" "\"job-state.3\" = \"W toku\";\n" "\"job-state.4\" = \"Wstrzymane\";\n" "\"job-state.5\" = \"Przetwarzanie\";\n" "\"job-state.6\" = \"Zatrzymane\";\n" "\"job-state.7\" = \"Anulowane\";\n" "\"job-state.8\" = \"Przerwane\";\n" "\"job-state.9\" = \"Zakończone\";\n" "\"joining\" = \"dołączenie\";\n" "\"media\" = \"Nośniki\";\n" "\"media-col\" = \"Nośniki\";\n" "\"media-size\" = \"Rozmiar nośnika\";\n" "\"media-size-name\" = \"Rozmiar nośnika\";\n" "\"media-source\" = \"Podajnik\";\n" "\"media-source.alternate\" = \"Alternatywne\";\n" "\"media-source.alternate-roll\" = \"Rolka zastępcza\";\n" "\"media-source.auto\" = \"Automatyczne\";\n" "\"media-source.bottom\" = \"Dół\";\n" "\"media-source.by-pass-tray\" = \"Taca wielozadaniowa\";\n" "\"media-source.center\" = \"Centrum\";\n" "\"media-source.disc\" = \"Płyta\";\n" "\"media-source.envelope\" = \"Koperta\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Duża pojemność\";\n" "\"media-source.left\" = \"Lewo\";\n" "\"media-source.main\" = \"Główne\";\n" "\"media-source.main-roll\" = \"Główna rolka\";\n" "\"media-source.manual\" = \"Ręczne\";\n" "\"media-source.middle\" = \"Środek\";\n" "\"media-source.photo\" = \"Zdjęcie\";\n" "\"media-source.rear\" = \"Tył\";\n" "\"media-source.right\" = \"Prawo\";\n" "\"media-source.roll-1\" = \"Rolka 1\";\n" "\"media-source.roll-10\" = \"Rolka 10\";\n" "\"media-source.roll-2\" = \"Rolka 2\";\n" "\"media-source.roll-3\" = \"Rolka 3\";\n" "\"media-source.roll-4\" = \"Rolka 4\";\n" "\"media-source.roll-5\" = \"Rolka 5\";\n" "\"media-source.roll-6\" = \"Rolka 6\";\n" "\"media-source.roll-7\" = \"Rolka 7\";\n" "\"media-source.roll-8\" = \"Rolka 8\";\n" "\"media-source.roll-9\" = \"Rolka 9\";\n" "\"media-source.side\" = \"Bok\";\n" "\"media-source.top\" = \"Góra\";\n" "\"media-source.tray-1\" = \"Taca 1\";\n" "\"media-source.tray-10\" = \"Taca 10\";\n" "\"media-source.tray-11\" = \"Taca 11\";\n" "\"media-source.tray-12\" = \"Taca 12\";\n" "\"media-source.tray-13\" = \"Taca 13\";\n" "\"media-source.tray-14\" = \"Taca 14\";\n" "\"media-source.tray-15\" = \"Taca 15\";\n" "\"media-source.tray-16\" = \"Taca 16\";\n" "\"media-source.tray-17\" = \"Taca 17\";\n" "\"media-source.tray-18\" = \"Taca 18\";\n" "\"media-source.tray-19\" = \"Taca 19\";\n" "\"media-source.tray-2\" = \"Taca 2\";\n" "\"media-source.tray-20\" = \"Taca 20\";\n" "\"media-source.tray-3\" = \"Taca 3\";\n" "\"media-source.tray-4\" = \"Taca 4\";\n" "\"media-source.tray-5\" = \"Taca 5\";\n" "\"media-source.tray-6\" = \"Taca 6\";\n" "\"media-source.tray-7\" = \"Taca 7\";\n" "\"media-source.tray-8\" = \"Taca 8\";\n" "\"media-source.tray-9\" = \"Taca 9\";\n" "\"media-tracking\" = \"Śledzenie nośników\";\n" "\"media-tracking.continuous\" = \"Ciągłe\";\n" "\"media-tracking.gap\" = \"Dystans\";\n" "\"media-tracking.mark\" = \"Znacznik\";\n" "\"media-tracking.web\" = \"Internet\";\n" "\"media-type\" = \"Typ nośników\";\n" "\"media-type.aluminum\" = \"Aluminium\";\n" "\"media-type.auto\" = \"Automatyczny\";\n" "\"media-type.back-print-film\" = \"Folia nadrukowana z tyłu\";\n" "\"media-type.cardboard\" = \"Karton\";\n" "\"media-type.cardstock\" = \"Karta\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Ciągły\";\n" "\"media-type.continuous-long\" = \"Ciągły (długi)\";\n" "\"media-type.continuous-short\" = \"Ciągły (krótki)\";\n" "\"media-type.corrugated-board\" = \"Tektura falista\";\n" "\"media-type.disc\" = \"Dysk optyczny\";\n" "\"media-type.disc-glossy\" = \"Dysk optyczny błyszczący\";\n" "\"media-type.disc-high-gloss\" = \"Dysk optyczny o wysokim połysku\";\n" "\"media-type.disc-matte\" = \"Dysk optyczny matowy\";\n" "\"media-type.disc-satin\" = \"Dysk optyczny satynowy\";\n" "\"media-type.disc-semi-gloss\" = \"Dysk optyczny półbłyszczący\";\n" "\"media-type.double-wall\" = \"Dwuścienny\";\n" "\"media-type.dry-film\" = \"Folia sucha\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Folia tłoczona\";\n" "\"media-type.end-board\" = \"Burta tylna\";\n" "\"media-type.envelope\" = \"Koperta\";\n" "\"media-type.envelope-archival\" = \"Koperta do archiwizacji\";\n" "\"media-type.envelope-bond\" = \"Koperta bond\";\n" "\"media-type.envelope-coated\" = \"Koperta powlekana\";\n" "\"media-type.envelope-cotton\" = \"Koperta bawełniana\";\n" "\"media-type.envelope-fine\" = \"Koperta drobna\";\n" "\"media-type.envelope-heavyweight\" = \"Koperta o dużej gramaturze\";\n" "\"media-type.envelope-inkjet\" = \"Koperta do druku atramentowego\";\n" "\"media-type.envelope-lightweight\" = \"Koperta o lekkiej gramaturze\";\n" "\"media-type.envelope-plain\" = \"Koperta zwykła\";\n" "\"media-type.envelope-preprinted\" = \"Koperta z nadrukiem\";\n" "\"media-type.envelope-window\" = \"Koperta z okienkiem\";\n" "\"media-type.fabric\" = \"Tkanina\";\n" "\"media-type.fabric-archival\" = \"Tkanina do archiwizacji\";\n" "\"media-type.fabric-glossy\" = \"Tkanina błyszcząca\";\n" "\"media-type.fabric-high-gloss\" = \"Tkanina o wysokim połysku\";\n" "\"media-type.fabric-matte\" = \"Tkanina matowa\";\n" "\"media-type.fabric-semi-gloss\" = \"Tkanina półbłyszcząca\";\n" "\"media-type.fabric-waterproof\" = \"Tkanina wodoodporna\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Baza fleksograficzna\";\n" "\"media-type.flexo-photo-polymer\" = \"Fotopolimer fleksograficzny\";\n" "\"media-type.flute\" = \"Flet\";\n" "\"media-type.foil\" = \"Folia\";\n" "\"media-type.full-cut-tabs\" = \"Zakładki pełne\";\n" "\"media-type.glass\" = \"Szkło\";\n" "\"media-type.glass-colored\" = \"Szkło barwione\";\n" "\"media-type.glass-opaque\" = \"Szkło nieprzezroczyste\";\n" "\"media-type.glass-surfaced\" = \"Szkło wypolerowane\";\n" "\"media-type.glass-textured\" = \"Szkło teksturowane\";\n" "\"media-type.gravure-cylinder\" = \"Cylinder wklęsły\";\n" "\"media-type.image-setter-paper\" = \"Papier do naświetlania\";\n" "\"media-type.imaging-cylinder\" = \"Cylinder obrazujący\";\n" "\"media-type.labels\" = \"Etykiety\";\n" "\"media-type.labels-colored\" = \"Etykiety barwione\";\n" "\"media-type.labels-glossy\" = \"Etykiety błyszczące\";\n" "\"media-type.labels-high-gloss\" = \"Etykiety o wysokim połysku\";\n" "\"media-type.labels-inkjet\" = \"Etykiety do druku atramentowego\";\n" "\"media-type.labels-matte\" = \"Etykiety matowe\";\n" "\"media-type.labels-permanent\" = \"Etykiety trwałe\";\n" "\"media-type.labels-satin\" = \"Etykiety satynowe\";\n" "\"media-type.labels-security\" = \"Etykiety zabezpieczające\";\n" "\"media-type.labels-semi-gloss\" = \"Etykiety półbłyszczące\";\n" "\"media-type.laminating-foil\" = \"Folia do laminowania\";\n" "\"media-type.letterhead\" = \"Blankiet firmowy\";\n" "\"media-type.metal\" = \"Metal\";\n" "\"media-type.metal-glossy\" = \"Metal błyszczący\";\n" "\"media-type.metal-high-gloss\" = \"Metal o wysokim połysku\";\n" "\"media-type.metal-matte\" = \"Metal matowy\";\n" "\"media-type.metal-satin\" = \"Metal satynowy\";\n" "\"media-type.metal-semi-gloss\" = \"Metal półbłyszczący\";\n" "\"media-type.mounting-tape\" = \"Taśma montażowa\";\n" "\"media-type.multi-layer\" = \"Wielowarstwowy\";\n" "\"media-type.multi-part-form\" = \"Formularz wieloczęściowy\";\n" "\"media-type.other\" = \"Inny\";\n" "\"media-type.paper\" = \"Papier\";\n" "\"media-type.photographic\" = \"Papier fotograficzny\";\n" "\"media-type.photographic-archival\" = \"Fotograficzna do archiwizacji\";\n" "\"media-type.photographic-film\" = \"Film fotograficzny\";\n" "\"media-type.photographic-glossy\" = \"Papier fotograficzny błyszczący\";\n" "\"media-type.photographic-high-gloss\" = \"Papier fotograficzny o wysokim połysku\";\n" "\"media-type.photographic-matte\" = \"Papier fotograficzny matowy\";\n" "\"media-type.photographic-satin\" = \"Papier fotograficzny satynowy\";\n" "\"media-type.photographic-semi-gloss\" = \"Papier fotograficzny półbłyszczący\";\n" "\"media-type.plastic\" = \"Plastik\";\n" "\"media-type.plastic-archival\" = \"Plastik do archiwizacji\";\n" "\"media-type.plastic-colored\" = \"Plastik barwiony\";\n" "\"media-type.plastic-glossy\" = \"Plastik błyszczący\";\n" "\"media-type.plastic-high-gloss\" = \"Plastik o wysokim połysku\";\n" "\"media-type.plastic-matte\" = \"Plastik matowy\";\n" "\"media-type.plastic-satin\" = \"Plastik satynowy\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastik półbłyszczący\";\n" "\"media-type.plate\" = \"Płyta offsetowa\";\n" "\"media-type.polyester\" = \"Poliester\";\n" "\"media-type.pre-cut-tabs\" = \"Zakładki wstępnie przycięte\";\n" "\"media-type.roll\" = \"Rolka\";\n" "\"media-type.screen\" = \"Ekran\";\n" "\"media-type.screen-paged\" = \"Ekran stronicowany\";\n" "\"media-type.self-adhesive\" = \"Samoprzylepny\";\n" "\"media-type.self-adhesive-film\" = \"Folia samoprzylepna\";\n" "\"media-type.shrink-foil\" = \"Folia termokurczliwa\";\n" "\"media-type.single-face\" = \"Powierzchnia pojedyncza\";\n" "\"media-type.single-wall\" = \"Jednościenny\";\n" "\"media-type.sleeve\" = \"Koszulka\";\n" "\"media-type.stationery\" = \"Materiały piśmienne\";\n" "\"media-type.stationery-archival\" = \"Materiały piśmienne do archiwizacji\";\n" "\"media-type.stationery-coated\" = \"Papier powlekany\";\n" "\"media-type.stationery-cotton\" = \"Materiały piśmienne bawełniane\";\n" "\"media-type.stationery-fine\" = \"Papier welinowy\";\n" "\"media-type.stationery-heavyweight\" = \"Papier o dużej gramaturze\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Materiały piśmienne o dużej gramaturze, powlekane\";\n" "\"media-type.stationery-inkjet\" = \"Papier biurowy do druku atramentowego\";\n" "\"media-type.stationery-letterhead\" = \"Blankiet firmowy\";\n" "\"media-type.stationery-lightweight\" = \"Papier o lekkiej gramaturze\";\n" "\"media-type.stationery-preprinted\" = \"Papier wstępnie zadrukowany\";\n" "\"media-type.stationery-prepunched\" = \"Papier dziurkowany\";\n" "\"media-type.tab-stock\" = \"Papier z zakładkami\";\n" "\"media-type.tractor\" = \"Traktor\";\n" "\"media-type.transfer\" = \"Transferowy\";\n" "\"media-type.transparency\" = \"Przezroczysty\";\n" "\"media-type.triple-wall\" = \"Trójścienny\";\n" "\"media-type.wet-film\" = \"Film wilgotny\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 lub US Letter\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (extra)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (extra)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (tab)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (extra)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (extra)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Koperta\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4 Koperta\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Koperta\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Koperta\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Koperta\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Koperta\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Koperta\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Koperta\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Koperta\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Koperta\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Koperta\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Koperta\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Koperta\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Koperta\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Koperta\";\n" "\"media.iso_dl_110x220mm\" = \"DL Koperta\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Executive\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Koperta Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Koperta Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Koperta Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Koperta Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Koperta Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Koperta Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Pocztówka z odpowiedzią (Oufuku Reply Postcard)\";\n" "\"media.jpn_you4_105x235mm\" = \"Koperta You 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Koperta A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Koperta C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Executive\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"Składanka europejska\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"Składanka amerykańska\";\n" "\"media.na_foolscap_8.5x13in\" = \"Papier kancelaryjny\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Oświadczenie\";\n" "\"media.na_legal-extra_9.5x15in\" = \"US Legal (Extra)\";\n" "\"media.na_legal_8.5x14in\" = \"US Legal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"US Letter (Extra)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"US Letter (Plus)\";\n" "\"media.na_letter_8.5x11in\" = \"US Letter\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Koperta Monarch\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Koperta #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Koperta #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Koperta #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Koperta #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Koperta #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Koperta Personal\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Quarto\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folio\";\n" "\"media.om_folio_210x330mm\" = \"Folio (Special)\";\n" "\"media.om_invite_220x220mm\" = \"Koperta zaproszeniowa\";\n" "\"media.om_italian_110x230mm\" = \"Koperta włoska\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275 mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300 mm\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180 mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389 mm\";\n" "\"media.om_postfix_114x229mm\" = \"Koperta Postfix\";\n" "\"media.prc_10_324x458mm\" = \"Koperta chińska #10\";\n" "\"media.prc_16k_146x215mm\" = \"Chińska 16k\";\n" "\"media.prc_1_102x165mm\" = \"Koperta chińska #1\";\n" "\"media.prc_2_102x176mm\" = \"Koperta chińska #2\";\n" "\"media.prc_32k_97x151mm\" = \"Chińska 32k\";\n" "\"media.prc_3_125x176mm\" = \"Koperta chińska #3\";\n" "\"media.prc_4_110x208mm\" = \"Koperta chińska #4\";\n" "\"media.prc_5_110x220mm\" = \"Koperta chińska #5\";\n" "\"media.prc_6_120x320mm\" = \"Koperta chińska #6\";\n" "\"media.prc_7_160x230mm\" = \"Koperta chińska #7\";\n" "\"media.prc_8_120x309mm\" = \"Koperta chińska #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"nie skonfigurowano\";\n" "\"not visible\" = \"niewidoczne\";\n" "\"off\" = \"wyłączone\";\n" "\"on\" = \"włączone\";\n" "\"orientation-requested\" = \"Orientacja\";\n" "\"orientation-requested.3\" = \"Pionowa\";\n" "\"orientation-requested.4\" = \"Pozioma\";\n" "\"orientation-requested.5\" = \"Pozioma (obrócona)\";\n" "\"orientation-requested.6\" = \"Pionowa (obrócona)\";\n" "\"orientation-requested.7\" = \"Brak\";\n" "\"output-bin\" = \"Odbiornik\";\n" "\"output-bin.auto\" = \"Automatyczny\";\n" "\"output-bin.bottom\" = \"Dół\";\n" "\"output-bin.center\" = \"Centrum\";\n" "\"output-bin.face-down\" = \"Do dołu\";\n" "\"output-bin.face-up\" = \"Do góry\";\n" "\"output-bin.large-capacity\" = \"Duża pojemność\";\n" "\"output-bin.left\" = \"Lewo\";\n" "\"output-bin.mailbox-1\" = \"Skrzynka pocztowa 1\";\n" "\"output-bin.mailbox-10\" = \"Skrzynka pocztowa 10\";\n" "\"output-bin.mailbox-2\" = \"Skrzynka pocztowa 2\";\n" "\"output-bin.mailbox-3\" = \"Skrzynka pocztowa 3\";\n" "\"output-bin.mailbox-4\" = \"Skrzynka pocztowa 4\";\n" "\"output-bin.mailbox-5\" = \"Skrzynka pocztowa 5\";\n" "\"output-bin.mailbox-6\" = \"Skrzynka pocztowa 6\";\n" "\"output-bin.mailbox-7\" = \"Skrzynka pocztowa 7\";\n" "\"output-bin.mailbox-8\" = \"Skrzynka pocztowa 8\";\n" "\"output-bin.mailbox-9\" = \"Skrzynka pocztowa 9\";\n" "\"output-bin.middle\" = \"Środek\";\n" "\"output-bin.my-mailbox\" = \"Moja skrzynka pocztowa\";\n" "\"output-bin.rear\" = \"Tył\";\n" "\"output-bin.right\" = \"Prawo\";\n" "\"output-bin.side\" = \"Bok\";\n" "\"output-bin.stacker-1\" = \"Zszywacz 1\";\n" "\"output-bin.stacker-10\" = \"Zszywacz 10\";\n" "\"output-bin.stacker-2\" = \"Zszywacz 2\";\n" "\"output-bin.stacker-3\" = \"Zszywacz 3\";\n" "\"output-bin.stacker-4\" = \"Zszywacz 4\";\n" "\"output-bin.stacker-5\" = \"Zszywacz 5\";\n" "\"output-bin.stacker-6\" = \"Zszywacz 6\";\n" "\"output-bin.stacker-7\" = \"Zszywacz 7\";\n" "\"output-bin.stacker-8\" = \"Zszywacz 8\";\n" "\"output-bin.stacker-9\" = \"Zszywacz 9\";\n" "\"output-bin.top\" = \"Góra\";\n" "\"output-bin.tray-1\" = \"Taca 1\";\n" "\"output-bin.tray-10\" = \"Taca 10\";\n" "\"output-bin.tray-2\" = \"Taca 2\";\n" "\"output-bin.tray-3\" = \"Taca 3\";\n" "\"output-bin.tray-4\" = \"Taca 4\";\n" "\"output-bin.tray-5\" = \"Taca 5\";\n" "\"output-bin.tray-6\" = \"Taca 6\";\n" "\"output-bin.tray-7\" = \"Taca 7\";\n" "\"output-bin.tray-8\" = \"Taca 8\";\n" "\"output-bin.tray-9\" = \"Taca 9\";\n" "\"print-color-mode\" = \"Tryb drukowania\";\n" "\"print-color-mode.auto\" = \"Automatyczny\";\n" "\"print-color-mode.auto-monochrome\" = \"Auto. monochromia\";\n" "\"print-color-mode.bi-level\" = \"Tekst\";\n" "\"print-color-mode.color\" = \"Kolor\";\n" "\"print-color-mode.highlight\" = \"Wyróżnienie\";\n" "\"print-color-mode.monochrome\" = \"Monochromia\";\n" "\"print-color-mode.process-bi-level\" = \"Przetwarzanie tekstu\";\n" "\"print-color-mode.process-monochrome\" = \"Przetwarzanie monochromi\";\n" "\"print-content-optimize\" = \"Optymalizuj pod kątem\";\n" "\"print-content-optimize.auto\" = \"Automatycznie\";\n" "\"print-content-optimize.graphic\" = \"Grafiki\";\n" "\"print-content-optimize.photo\" = \"Zdjęć\";\n" "\"print-content-optimize.text\" = \"Tekstu\";\n" "\"print-content-optimize.text-and-graphic\" = \"Tekstu i grafiki\";\n" "\"print-darkness\" = \"Ciemność wydruku\";\n" "\"print-quality\" = \"Jakość wydruku\";\n" "\"print-quality.3\" = \"Szkic\";\n" "\"print-quality.4\" = \"Normalna\";\n" "\"print-quality.5\" = \"Najlepsza\";\n" "\"print-scaling\" = \"Skalowanie\";\n" "\"print-scaling.auto\" = \"Automatyczne\";\n" "\"print-scaling.auto-fit\" = \"Automatyczne dopasowanie\";\n" "\"print-scaling.fill\" = \"Wypełnianie\";\n" "\"print-scaling.fit\" = \"Dopasowanie\";\n" "\"print-scaling.none\" = \"Brak\";\n" "\"print-speed\" = \"Szybkość drukowania\";\n" "\"printer-resolution\" = \"Rozdzielczość\";\n" "\"printer-state-reasons.cover-open\" = \"Pokrywa otwarta.\";\n" "\"printer-state-reasons.door-open\" = \"Drzwi otwarte.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Zidentyfikuj drukarkę.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Brak zasobnika papieru.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Brak atramentu.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Niski poziom atramentu.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Kosz na śmieci prawie pełny.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Kosz na śmieci pełny.\";\n" "\"printer-state-reasons.media-empty\" = \"Brak papieru.\";\n" "\"printer-state-reasons.media-jam\" = \"Zacięcie papieru.\";\n" "\"printer-state-reasons.media-low\" = \"Wkrótce wymień papier.\";\n" "\"printer-state-reasons.media-needed\" = \"Włóż papier.\";\n" "\"printer-state-reasons.none\" = \"Gotowa.\";\n" "\"printer-state-reasons.offline\" = \"Offline.\";\n" "\"printer-state-reasons.other\" = \"Zobacz drukarkę.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Drukarka zajęta.\";\n" "\"printer-state-reasons.toner-empty\" = \"Brak tonera.\";\n" "\"printer-state-reasons.toner-low\" = \"Niski poziom tonera.\";\n" "\"printer-state.3\" = \"Bezczynna\";\n" "\"printer-state.4\" = \"Przetwarzanie\";\n" "\"printer-state.5\" = \"Zatrzymana\";\n" "\"sides\" = \"Drukowanie dwustronne\";\n" "\"sides.one-sided\" = \"Wyłączone\";\n" "\"sides.two-sided-long-edge\" = \"Wyłączone (pionowo)\";\n" "\"sides.two-sided-short-edge\" = \"Wyłączone (poziomo)\";\n" "\"unable to join\" = \"nie można dołączyć\";\n" "\"yesterday at %02d:%02d:%02d\" = \"wczoraj o %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Wyspy Alandzkie\";\n"; pappl-1.4.9/pappl/strings/pt.strings000066400000000000000000000000001476704353100175040ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/tr.strings000066400000000000000000001363011476704353100175240ustar00rootroot00000000000000" -a Cancel all jobs (cancel)." = " -a Tüm işleri iptal et (cancel)."; " -c COPIES" = " -c KOPYA"; " -d PRINTER Specify printer." = " -d YAZICI Yazıcı belirt."; " -j JOB-ID Specify job ID (cancel)." = " -j İŞ-NO İş numarası belirt (cancel)."; " -m DRIVER-NAME Specify driver (add/modify)." = " -m SÜRÜCÜ-ADI Sürücü belirt (add/modify)."; " -n COPIES Specify number of copies (submit)." = " -n KOPYA Kopya sayısını belirt (submit)."; " -o %s=%s (default)" = " -o %s=%s (default)"; " -o NAME=VALUE Specify option (add,modify,server,submit)." = " -o AD=DEĞER Seçenek belirt (add,modify,server,submit)."; " -o print-darkness=-100 to 100" = " -o print-darkness=-100 ila 100"; " -o printer-darkness=0 to 100" = " -o printer-darkness=0 ila 100"; " -o printer-geo-location='geo:LATITUDE,LONGITUDE'" = " -o printer-geo-location='geo:ENLEM,BOYLAM'"; " -o printer-location='LOCATION'" = " -o printer-location='KONUM'"; " -o printer-organization='ORGANIZATION'" = " -o printer-organization='ORGANİZASYON'"; " -o printer-organizational-unit='UNIT/SECTION'" = " -o printer-organizational-unit='BİRİM/BÖLÜM'"; " -u URI Specify ipp: or ipps: printer/server." = " -u URI ipp: veya ipps: yazıcı/sunucu belirt."; " -v DEVICE-URI Specify socket: or usb: device (add/modify)." = " -v AYGIT-URI socket: veya usb: aygıt belirt (add/modify)."; " add PRINTER Add a printer." = " add YAZICI Yazıcı ekle."; " autoadd Automatically add supported printers." = " autoadd Desteklenen yazıcıları otomatik olarak ekle."; " cancel Cancel one or more jobs." = " cancel Bir veya daha fazla işi iptal et."; " default Set the default printer." = " default Öntanımlı yazıcıyı ayarla."; " delete Delete a printer." = " delete Yazıcı sil."; " devices List devices." = " devices Aygıtları listele."; " drivers List drivers." = " drivers Sürücüleri listele."; " jobs List jobs." = " jobs İşleri listele."; " modify Modify a printer." = " modify Yazıcı düzenle."; " options List printer options." = " options Yazıcı seçeneklerini listele."; " pause Pause printing for a printer." = " pause Bir yazıcı için yazdırmayı duraklat."; " printers List printers." = " printers Yazıcıları listele."; " resume Resume printing for a printer." = " resume Bir yazıcı için yazdırmayı devam ettir."; " server Run a server." = " server Sunucu çalıştır."; " shutdown Shutdown a running server." = " shutdown Çalışan bir sunucuyu kapat."; " status Show server/printer/job status." = " status Sunucu/yazıcı/iş durumunu göster."; " submit Submit a file for printing." = " submit Yazdırmak için bir dosya gönder."; "%04d-%02d-%02d at %02d:%02d:%02d" = "%04d-%02d-%02d, %02d:%02d:%02d"; "%d days ago at %02d:%02d:%02d" = "%d gün önce, %02d:%02d:%02d'de"; "%d inches/sec" = "%d inç/s"; "%d job" = "%d iş"; /* Media size in millimeters */ "%d x %dmm" = "%d x %dmm"; "%ddpi" = "%ddpi"; "%dx%ddpi" = "%dx%ddpi"; /* Media size in inches */ "%g x %g\"" = "%g x %g\""; /* size (type+borderless) */ "%s (%s%s)" = "%s (%s%s)"; /* size (type+borderless) from source/tray */ "%s (%s%s) from %s" = "%s (%s%s) kaynak: %s"; /* Source/Tray Media */ "%s Media" = "%s Ortamı"; "%s: Bad 'server-port' value." = "%s: Hatalı 'sunucu-bağlantı noktası' değeri."; "%s: Bad job ID." = "%s: Hatalı iş numarası."; "%s: Bad printer URI '%s'." = "%s: Hatalı yazıcı URI'si: '%s'."; "%s: Cannot specify more than one sub-command." = "%s: Birden fazla alt komut belirtilemez."; "%s: Empty print file received on the standard input." = "%s: Standart girişte boş yazdırma dosyası alındı."; "%s: Failed to create a system." = "%s: Sistem oluşturulamadı."; "%s: Missing '-d PRINTER'." = "%s: '-d YAZICI' eksik."; "%s: Missing '-m DRIVER-NAME'." = "%s: '-m SÜRÜCÜ-ADI' eksik."; "%s: Missing '-v DEVICE-URI'." = "%s: '-v AYGIT-URI' eksik."; "%s: Missing copy count after '-n'." = "%s: '-n' seçeneğinden sonra kopya sayısı eksik."; "%s: Missing device URI after '-v'." = "%s: '-v' seçeneğinden sonra aygıt URI'si eksik."; "%s: Missing driver name after '-m'." = "%s: '-m' seçeneğinden sonra sürücü adı eksik."; "%s: Missing filename after '--'." = "%s: '--' sonrasında dosya adı eksik."; "%s: Missing hostname after '-h'." = "%s: '-h' seçeneğinden sonra ana makine adı eksik."; "%s: Missing job ID after '-j'." = "%s: '-j' seçeneğinden sonra iş numarası eksik."; "%s: Missing option(s) after '-o'." = "%s: '-o' sonrasında seçenek(ler) eksik."; "%s: Missing printer URI after '-u'." = "%s: '-u' seçeneğinden sonra yazıcı URI'si eksik."; "%s: Missing printer name after '-d'." = "%s: '-d' seçeneğinden sonra yazıcı adı eksik."; "%s: Missing space after '-o'." = "%s: '-o' seçeneğinden sonra boşluk eksik."; "%s: Missing title after '-t'." = "%s: '-t' seçeneğinden sonra başlık eksik."; "%s: No default printer available." = "%s: Kullanılabilir öntanımlı yazıcı yok."; "%s: No files to print." = "%s: Yazdırılacak dosya yok."; "%s: Server is not running." = "%s: Sunucu çalışmıyor."; "%s: Sub-command '%s' does not accept files." = "%s: '%s' alt komutu dosya kabul etmiyor."; "%s: Sub-command 'autoadd' is not supported." = "%s: 'autoadd' alt komutu desteklenmiyor."; "%s: Too many files." = "%s: Çok fazla dosya."; "%s: Unable to access '%s': %s" = "%s: '%s' erişilebilir değil: %s"; "%s: Unable to add printer: %s" = "%s: Yazıcı eklenemiyor: %s"; "%s: Unable to cancel job: %s" = "%s: İş iptal edilemiyor: %s"; "%s: Unable to connect to printer at '%s:%d': %s" = "%s: '%s:%d' konumunda yazıcıya bağlanılamıyor: %s"; "%s: Unable to connect to server: %s" = "%s: Sunucuya bağlanılamıyor: %s"; "%s: Unable to create temporary file: %s" = "%s: Geçici dosya oluşturulamıyor: %s"; "%s: Unable to delete printer: %s" = "%s: Yazıcı silinemiyor: %s"; "%s: Unable to get available devices: %s" = "%s: Kullanılabilir aygıtlar alınamıyor: %s"; "%s: Unable to get information for '%s': %s" = "%s: '%s' için bilgi alınamıyor: %s"; "%s: Unable to get information for printer: %s" = "%s: Yazıcı için bilgi alınamıyor: %s"; "%s: Unable to get printer options: %s" = "%s: Yazıcı seçenekleri alınamıyor: %s"; "%s: Unable to modify printer: %s" = "%s: Yazıcı düzenlenemiyor: %s"; "%s: Unable to pause printer: %s" = "%s: Yazıcı duraklatılamıyor: %s"; "%s: Unable to print '%s': %s" = "%s: '%s' yazdırılamıyor: %s"; "%s: Unable to resume printer: %s" = "%s: Yazıcı devam ettirilemiyor: %s"; "%s: Unable to set default printer: %s" = "%s: Öntanımlı yazıcı ayarlanamıyor: %s"; "%s: Unable to shutdown server: %s" = "%s: Sunucu kapatılamıyor: %s"; "%s: Unable to start server: %s" = "%s: Sunucu başlatılamıyor: %s"; "%s: Unable to write to temporary file: %s" = "%s: Geçici dosyaya yazılamıyor: %s"; "%s: Unknown option '%s'." = "%s: Bilinmeyen seçenek '%s'."; "%s: Unknown option '-%c'." = "%s: Bilinmeyen seçenek '-%c'."; "%s: Unknown sub-command '%s'." = "%s: Bilinmeyen alt komut '%s'."; "%s: Unsupported URI scheme '%s'." = "%s: Desteklenmeyen URI şeması '%s'."; "%s: Warning - user credentials are not supported in URIs." = "%s: Uyarı - URI'lerde kullanıcı kimlik bilgileri desteklenmiyor."; ", Borderless" = ", Kenarlıksız"; "A printer with that name already exists." = "Bu ada sahip bir yazıcı zaten var."; "Aborted %s" = "%s sonlandırıldı"; "Add Printer" = "Yazıcı Ekle"; "Admin Group" = "Yönetici Grubu"; "Afghanistan" = "Afganistan"; "Albania" = "Arnavutluk"; "Algeria" = "Cezayir"; "American Samoa" = "Amerikan Samoası"; "Andorra" = "Andorra"; "Angola" = "Angola"; "Anguilla" = "Anguilla"; "Antarctica" = "Antarktika"; "Antigua and Barbuda" = "Antigua ve Barbuda"; "Argentina" = "Arjantin"; "Armenia" = "Ermenistan"; "Aruba" = "Aruba"; "Australia" = "Avustralya"; "Austria" = "Avusturya"; "Auto" = "Otomatik"; "Auto-Detect Driver" = "Sürücüyü Otomatik Algıla"; "Azerbaijan" = "Azerbaycan"; "Bad administration group." = "Hatalı yönetim grubu."; "Bad port number." = "Hatalı bağlantı noktası numarası."; "Bad print group." = "Hatalı yazdırma grubu."; "Bad printer defaults." = "Hatalı yazıcı öntanımlı değerleri."; "Bahamas" = "Bahamalar"; "Bahrain" = "Bahreyn"; "Bangladesh" = "Bangladeş"; "Barbados" = "Barbados"; "Belarus" = "Belarus"; "Belgium" = "Belçika"; "Belize" = "Belize"; "Benin" = "Benin"; "Bermuda" = "Bermuda"; "Bhutan" = "Bhutan"; "Bolivia (Plurinational State of)" = "Bolivya (Çokuluslu Devleti)"; "Bonaire, Sint Eustatius and Saba" = "Bonaire, Sint Eustatius ve Saba"; "Borderless" = "Kenarlıksız"; "Bosnia and Herzegovina" = "Bosna Hersek"; "Botswana" = "Botsvana"; "Bouvet Island" = "Bouvet Adası"; "Brazil" = "Brezilya"; "British Indian Ocean Territory" = "Britanya Hint Okyanusu Toprakları"; "Brunei Darussalam" = "Brunei Sultanlığı"; "Bulgaria" = "Bulgaristan"; "Burkina Faso" = "Burkina Faso"; "Burundi" = "Burundi"; "Cabo Verde" = "Yeşil Burun Adaları"; "Cambodia" = "Kamboçya"; "Cameroon" = "Kamerun"; "Canada" = "Kanada"; "Cancel All Jobs" = "Tüm İşleri İptal Et"; "Cancel Job" = "İşi İptal Et"; "Canceled %s" = "%s iptal edildi"; "Canceling" = "İptal ediliyor"; "Cayman Islands" = "Cayman Adaları"; "Central African Republic" = "Orta Afrika Cumhuriyeti"; "Certificate created." = "Sertifika oluşturuldu."; "Certificate installed." = "Sertifika kuruldu."; "Certificate request created." = "Sertifika isteği oluşturuldu."; "Chad" = "Çad"; "Change Access Password" = "Erişim Parolasını Değiştir"; "Change Log Level" = "Günlük Kaydı Seviyesini Değiştir"; "Change Network Settings" = "Ağ Ayarlarını Değiştir"; "Change Wi-Fi Network" = "Wi-Fi Ağını Değiştir"; "Changes Saved." = "Değişiklikler Kaydedildi."; "Changes saved." = "Değişiklikler kaydedildi."; "Chile" = "Şili"; "China" = "Çin"; "Christmas Island" = "Christmas Adası"; "City/Locality" = "Şehir/Yerellik"; "Cocos (Keeling) Islands" = "Cocos (Keeling) Adaları"; "Colombia" = "Kolombiya"; "Comoros" = "Komorlar"; "Completed %s" = "%s tamamlandı"; "Configuration" = "Yapılandırma"; "Configure Media" = "Ortamı Yapılandır"; "Confirm Cancel All" = "Tümünü İptal Etmeyi Onayla"; "Confirm Delete Printer" = "Yazıcıyı Silmeyi Onayla"; "Congo" = "Kongo"; "Congo, Democratic Republic of the" = "Kongo Demokratik Cumhuriyeti"; "Contact" = "İletişim"; "Cook Islands" = "Cook Adaları"; "Costa Rica" = "Kosta Rika"; "Create Certificate Signing Request" = "Sertifika İmzalama İsteği Oluştur"; "Create New Certificate" = "Yeni Sertifika Oluştur"; "Create New TLS Certificate" = "Yeni TLS Sertifikası Oluştur"; "Create TLS Certificate Request" = "TLS Sertifikası İsteği Oluştur"; "Croatia" = "Hırvatistan"; "Cuba" = "Küba"; "Curaçao" = "Curaçao"; "Current Password" = "Geçerli Parola"; "Custom Size" = "Özel Boyut"; "Cyprus" = "Kıbrıs"; "Czechia" = "Çekya"; "Côte d'Ivoire" = "Fildişi Sahili"; "DHCP" = "DHCP"; "DHCP w/Manual Address" = "DHCP ve Elle Adres"; "DNS-SD Service Name" = "DNS-SD Hizmet Adı"; "Debugging" = "Hata Ayıklama"; "Default printer set." = "Öntanımlı yazıcı ayarlandı."; "Delete" = "Sil"; "Delete Printer" = "Yazıcı Sil"; "Denmark" = "Danimarka"; "Djibouti" = "Cibuti"; "Domain Name" = "Etki Alanı Adı"; "Dominica" = "Dominika"; "Dominican Republic" = "Dominik Cumhuriyeti"; "Download Certificate Request File" = "Sertifika İstek Dosyasını İndir"; "Ecuador" = "Ekvador"; "Egypt" = "Mısır"; "El Salvador" = "El Salvador"; "Equatorial Guinea" = "Equatorial Guinea"; "Eritrea" = "Eritre"; "Errors" = "Hatalar"; "Estonia" = "Estonya"; "Eswatini" = "Esvatini"; "Ethiopia" = "Etiyopya"; "Falkland Islands (Malvinas)" = "Falkland Adaları (Malvinas)"; "Faroe Islands" = "Faroe Adaları"; "Fatal Errors/Conditions" = "Ölümcül Hatalar/Koşullar"; "Fiji" = "Fiji"; "Finland" = "Finlandiya"; "France" = "Fransa"; "French Guiana" = "Fransız Guyanası"; "French Polynesia" = "Fransız Polinezyası"; "French Southern Territories" = "Fransız Güney Toprakları"; "Gabon" = "Gabon"; "Gambia" = "Gambiya"; "Georgia" = "Gürcistan"; "Germany" = "Almanya"; "Ghana" = "Gana"; "Gibraltar" = "Cebelitarık"; "Greece" = "Yunanistan"; "Greenland" = "Grönland"; "Grenada" = "Grenada"; "Group changes saved." = "Grup değişiklikleri kaydedildi."; "Guadeloupe" = "Guadeloupe"; "Guam" = "Guam"; "Guatemala" = "Guatemala"; "Guernsey" = "Guernsey"; "Guinea" = "Gine"; "Guinea-Bissau" = "Gine-Bissau"; "Guyana" = "Guyana"; "Haiti" = "Haiti"; "Heard Island and McDonald Islands" = "Heard Adası ve McDonald Adaları"; "Hidden SSID" = "Gizli SSID"; "Hold Job" = "İşi Beklet"; "Hold New Jobs" = "Yeni İşleri Beklet"; "Holding new jobs." = "Yeni işler bekletiliyor."; "Holy See" = "Vatikan"; "Honduras" = "Honduras"; "Hong Kong" = "Hong Kong"; "Hostname" = "Ana Makine Adı"; "Human-Readable Location" = "İnsan Tarafından Okunabilir Konum"; "Hungary" = "Macaristan"; "IPv4 Address" = "IPv4 Adresi"; "IPv4 Configuration" = "IPv4 Yapılandırması"; "IPv4 Gateway" = "IPv4 Ağ Geçidi"; "IPv4 Netmask" = "IPv4 Ağ Maskesi"; "IPv6 Address" = "IPv6 Adresi"; "IPv6 Configuration" = "IPv6 Yapılandırması"; "IPv6 Link-Local" = "IPv6 Yerel Bağlantı"; "IPv6 Prefix Length" = "IPv6 Ön Ek Uzunluğu"; "Iceland" = "İzlanda"; "Identify Printer" = "Yazıcı Tanımla"; "India" = "Hindistan"; "Indonesia" = "Endonezya"; "Informational" = "Bilgi"; "Install TLS Certificate" = "TLS Sertifikası Kur"; "Invalid IPv4 address." = "Geçersiz IPv4 adresi."; "Invalid IPv4 netmask." = "Geçersiz IPv4 ağ maskesi."; "Invalid IPv6 address." = "Geçersiz IPv6 adresi."; "Invalid IPv6 prefix length." = "Geçersiz IPv6 ön ek uzunluğu."; "Invalid Job ID." = "Geçersiz İş Numarası."; "Invalid certificate or private key." = "Geçersiz sertifika veya özel anahtar."; "Invalid form data." = "Geçersiz form verisi."; "Invalid form submission." = "Geçersiz form gönderimi."; "Invalid job ID." = "Geçersiz iş numarası."; "Invalid network configuration." = "Geçersiz ağ yapılandırması."; "Iran (Islamic Republic of)" = "İran (İslam Cumhuriyeti)"; "Iraq" = "Irak"; "Ireland" = "İrlanda"; "Isle of Man" = "Man Adası"; "Israel" = "İsrail"; "Italy" = "İtalya"; "Jamaica" = "Jamaika"; "Japan" = "Japonya"; "Jersey" = "Jersey"; "Job #" = "İş #"; "Job canceled." = "İş iptal edildi."; "Job held." = "İş bekletildi."; "Job released." = "İş serbest bırakıldı."; "Jobs" = "İşler"; "Joining Wi-Fi Network" = "Wi-Fi Ağına Bağlanıyor"; "Jordan" = "Ürdün"; "Kazakhstan" = "Kazakistan"; "Kenya" = "Kenya"; "Kiribati" = "Kiribati"; "Korea (Democratic People's Republic of)" = "Kore (Demokratik Halk Cumhuriyeti)"; "Korea, Republic of" = "Kore Cumhuriyeti"; "Kuwait" = "Kuveyt"; "Kyrgyzstan" = "Kırgızistan"; "Landscape" = "Manzara"; "Lao People's Democratic Republic" = "Lao Demokratik Halk Cumhuriyeti"; "Latvia" = "Letonya"; "Lebanon" = "Lübnan"; "Lesotho" = "Lesotho"; "Level" = "Seviye"; "Liberia" = "Liberya"; "Libya" = "Libya"; "Liechtenstein" = "Lihtenştayn"; "Lithuania" = "Litvanya"; "Location" = "Konum"; "Log Level" = "Günlük Kaydı Seviyesi"; "Logging" = "Günlük Kaydı"; "Logs" = "Günlük"; "Luxembourg" = "Lüksemburg"; "Macao" = "Macao"; "Madagascar" = "Madagaskar"; "Malawi" = "Malavi"; "Malaysia" = "Malezya"; "Maldives" = "Maldivler"; "Mali" = "Mali"; "Malta" = "Malta"; "Manual Configuration" = "Elle Yapılandırma"; "Marshall Islands" = "Marshall Adaları"; "Martinique" = "Martinik"; "Mauritania" = "Moritanya"; "Mauritius" = "Mauritius"; "Mayotte" = "Mayotte"; "Media" = "Ortam"; "Mexico" = "Meksika"; "Micronesia (Federated States of)" = "Mikronezya (Federal Devletleri)"; "Missing action." = "Eksik eylem."; "Missing job ID." = "İş kimliği eksik."; "Missing network name." = "Eksik ağ adı."; "Missing private key." = "Eksik özel anahtar."; "Moldova, Republic of" = "Moldova Cumhuriyeti"; "Monaco" = "Monako"; "Mongolia" = "Moğolistan"; "Montenegro" = "Karadağ"; "Montserrat" = "Montserrat"; "Morocco" = "Fas"; "Mozambique" = "Mozambik"; "Myanmar" = "Myanmar"; "Name" = "Ad"; "Namibia" = "Namibya"; "Nauru" = "Nauru"; "Nepal" = "Nepal"; "Netherlands" = "Hollanda"; "Network" = "Ağ"; "Network Printer" = "Ağ Yazıcısı"; "Networking" = "Ağ"; "New Caledonia" = "Yeni Kaledonya"; "New Zealand" = "Yeni Zelanda"; "Nicaragua" = "Nikaragua"; "Niger" = "Nijer"; "Nigeria" = "Nijerya"; "Niue" = "Niue"; "No default printer set." = "Öntanımlı yazıcı ayarlanmadı."; "No jobs in history." = "Geçmişte iş yok."; "Norfolk Island" = "Norfolk Adası"; "North Macedonia" = "Kuzey Makedonya"; "Northern Mariana Islands" = "Kuzey Mariana Adaları"; "Norway" = "Norveç"; "Not set" = "Ayarlanmadı"; "Off" = "Kapalı"; "Offset" = "Ofset"; "Oman" = "Umman"; "Options:" = "Seçenekler:"; "Organization" = "Organizasyon"; "Organization Name" = "Organizasyon Adı"; "Other Settings" = "Diğer Ayarlar"; "Pakistan" = "Pakistan"; "Palau" = "Palau"; "Palestine, State of" = "Filistin Devleti"; "Panama" = "Panama"; "Papua New Guinea" = "Papua Yeni Gine"; "Paraguay" = "Paraguay"; "Password" = "Parola"; "Password changed." = "Parola değiştirildi."; "Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit." = "Parola en az sekiz karakter uzunluğunda olmalı ve en az bir büyük harf, bir küçük harf ve bir rakam içermelidir."; "Passwords do not match." = "Parolalar eşleşmiyor."; "Pause Printing" = "Yazdırmayı Duraklat"; "Peru" = "Peru"; "Philippines" = "Filipinler"; "Pitcairn" = "Pitcairn"; "Please enter a hostname or IP address for the printer." = "Lütfen yazıcı için bir ana makine adı veya IP adresi girin."; "Please enter a printer name." = "Lütfen bir yazıcı adı girin."; "Please select a device." = "Lütfen bir aygıt seçin."; "Please select a driver." = "Lütfen bir sürücü seçin."; "Please select a valid log level." = "Lütfen geçerli bir günlük kaydı seviyesi seçin."; "Poland" = "Polonya"; "Portrait" = "Portre"; "Portugal" = "Portekiz"; "Primary DNS" = "Birincil DNS"; "Print Group" = "Yazdırma Grubu"; "Print Test Page" = "Test Sayfası Yazdır"; "Print job options:" = "Yazdırma işi seçenekleri:"; "Printer identified." = "Yazıcı tanımlandı."; "Printer is currently active." = "Yazıcı şu anda etkin."; "Printer names must start with a letter or underscore and cannot contain special characters." = "Yazıcı adları bir harf veya alt çizgi ile başlamalıdır ve özel karakterler içeremez."; "Printer options:" = "Yazıcı seçenekleri:"; "Printer paused." = "Yazıcı duraklatıldı."; "Printer pausing." = "Yazıcı duraklatılıyor."; "Printer resuming." = "Yazıcı devam ettiriliyor."; "Printers" = "Yazıcılar"; "Printing Defaults" = "Öntanımlı Yazdırma Ayarları"; "Puerto Rico" = "Porto Riko"; "Qatar" = "Katar"; "Queued %s" = "%s sıraya alındı"; "Release Held New Jobs" = "Bekletilen Yeni İşleri Serbest Bırak"; "Release Job" = "İşi Serbest Bırak"; "Released held new jobs." = "Bekletilen yeni işler serbest bırakıldı."; "Reprint Job" = "İşi Yeniden Yazdır"; "Reprinted job." = "İş yeniden yazdırıldı."; "Resume Printing" = "Yazdırmayı Devam Ettir"; "Reverse Landscape" = "Ters Manzara"; "Reverse Portrait" = "Ters Portre"; "Romania" = "Romanya"; /* Running, STATE since DATE REASONS */ "Running, %s since %s%s." = "Çalışıyor, %s %s'den beri %s."; "Russian Federation" = "Rusya Federasyonu"; "Rwanda" = "Ruanda"; "Réunion" = "Réunion"; "Saint Barthélemy" = "Saint Barthélemy"; "Saint Helena, Ascension and Tristan da Cunha" = "Saint Helena, Ascension ve Tristan da Cunha"; "Saint Kitts and Nevis" = "Saint Kitts ve Nevis"; "Saint Lucia" = "Saint Lucia"; "Saint Martin (French part)" = "Saint Martin (Fransız kısmı)"; "Saint Pierre and Miquelon" = "Saint Pierre ve Miquelon"; "Saint Vincent and the Grenadines" = "Saint Vincent ve Grenadinler"; "Samoa" = "Samoa"; "San Marino" = "San Marino"; "Sao Tome and Principe" = "Sao Tome ve Principe"; "Saudi Arabia" = "Suudi Arabistan"; "Save Changes" = "Değişiklikleri Kaydet"; "Secondary DNS" = "İkincil DNS"; "Security" = "Güvenlik"; "Select Driver" = "Sürücü Seç"; "Senegal" = "Senegal"; "Serbia" = "Sırbistan"; "Server is not running." = "Sunucu çalışmıyor."; "Set Access Password" = "Erişim Parolası Ayarla"; "Set as Default" = "Öntanımlı Olarak Ayarla"; "Seychelles" = "Seyşeller"; "Sierra Leone" = "Sierra Leone"; "Singapore" = "Singapur"; "Sint Maarten (Dutch part)" = "Sint Maarten (Hollanda kısmı)"; "Slovakia" = "Slovakya"; "Slovenia" = "Slovenya"; "Solomon Islands" = "Solomon Adaları"; "Somalia" = "Somali"; "South Africa" = "Güney Afrika"; "South Georgia and the South Sandwich Islands" = "Güney Georgia ve Güney Sandwich Adaları"; "South Sudan" = "Güney Sudan"; "Spain" = "İspanya"; "Sri Lanka" = "Sri Lanka"; "Started %s" = "%s başlatıldı"; "Status" = "Durum"; "Sub-commands:" = "Alt komutlar:"; "Sudan" = "Sudan"; "Supplies" = "Malzemeler"; "Suriname" = "Surinam"; "Svalbard and Jan Mayen" = "Svalbard ve Jan Mayen"; "Sweden" = "İsveç"; "Switzerland" = "İsviçre"; "Syrian Arab Republic" = "Suriye Arap Cumhuriyeti"; "Taiwan, Province of China" = "Tayvan, Çin Eyaleti"; "Tajikistan" = "Tacikistan"; "Tanzania, United Republic of" = "Tanzanya Birleşik Cumhuriyeti"; "Test page printed." = "Test sayfası yazdırıldı."; "Thailand" = "Tayland"; "This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA." = "Bu form, güvenilir bir TLS sertifikası almak için Sertifika Yetkilisine (Certificate Authority - 'CA') gönderebileceğiniz bir sertifika imzalama isteği (certificate signing request - 'CSR') oluşturur. Özel anahtar, CA'dan aldığınız sertifika ile kullanılmak üzere ayrı olarak kaydedilir."; "This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers." = "Bu form, güvenli yazdırma için yeni bir 'kendi tarafından imzalanan' TLS sertifikası oluşturur. Kendi tarafından imzalanan sertifikalara web tarayıcıları tarafından otomatik olarak güvenilmez."; "This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately." = "Bu form, bir Sertifika Yetkilisinden ('CA') aldığınız güvenilir bir TLS sertifikasını kuracaktır. Kurulduktan sonra hemen kullanılacaktır."; "Timor-Leste" = "Timor-Leste"; "Togo" = "Togo"; "Tokelau" = "Tokelau"; "Tonga" = "Tonga"; "Trinidad and Tobago" = "Trinidad ve Tobago"; "Tunisia" = "Tunus"; "Turkey" = "Türkiye"; "Turkmenistan" = "Türkmenistan"; "Turks and Caicos Islands" = "Turks ve Caicos Adaları"; "Tuvalu" = "Tuvalu"; "Uganda" = "Uganda"; "Ukraine" = "Ukrayna"; "Unable to access test print file." = "Test yazdırma dosyasına erişilemiyor."; "Unable to copy print job." = "Yazdırma işi kopyalanamıyor."; "Unable to create certificate request." = "Sertifika isteği oluşturulamıyor."; "Unable to create certificate." = "Sertifika oluşturulamıyor."; "Unable to create test print job." = "Test yazdırma işi oluşturulamıyor."; "Unable to identify printer." = "Yazıcı tanımlanamıyor."; "Unable to lookup address." = "Adres aranamıyor."; "Unable to use that driver." = "Bu sürücü kullanılamıyor."; "United Arab Emirates" = "Birleşik Arap Emirlikleri"; "United Kingdom" = "Birleşik Krallık"; "United Kingdom of Great Britain and Northern Ireland" = "Büyük Britanya ve Kuzey İrlanda Birleşik Krallığı"; "United States Minor Outlying Islands" = "Amerika Birleşik Devletleri Küçük Dış Adaları"; "United States of America" = "Amerika Birleşik Devletleri"; "Unknown" = "Bilinmeyen"; "Unknown action." = "Bilinmeyen eylem."; "Unknown form action." = "Bilinmeyen form eylemi."; "Unknown form request." = "Bilinmeyen form isteği."; "Updating Network Configuration" = "Ağ Yapılandırması Güncelleniyor"; "Uruguay" = "Uruguay"; "Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\n" = "Kullanım: %s ALT-KOMUT [SEÇENEKLER] [DOSYA-ADI]\n"; "Use My Position" = "Konumumu Kullan"; "Users" = "Kullanıcılar"; "Uzbekistan" = "Özbekistan"; "Vanuatu" = "Vanuatu"; "Venezuela (Bolivarian Republic of)" = "Venezuela Bolivar Cumhuriyeti"; "Version %s" = "Sürüm %s"; "Viet Nam" = "Vietnam"; "View Logs" = "Günlükleri Görüntüle"; "Virgin Islands (British)" = "Virgin Adaları (İngiliz)"; "Virgin Islands (U.S.)" = "Virgin Adaları (ABD)"; "Wallis and Futuna" = "Wallis ve Futuna"; "Warning" = "Uyarı"; "Western Sahara" = "Batı Sahra"; "Wi-Fi Configuration" = "Wi-Fi Yapılandırması"; "Wi-Fi Network" = "Wi-Fi Ağı"; "Width" = "Genişlik"; "Wrong old password." = "Yanlış eski parola."; "Yemen" = "Yemen"; "Zambia" = "Zambiya"; "Zimbabwe" = "Zimbabve"; "at %02d:%02d:%02d" = "%02d:%02d:%02d"; /* IPP attribute, keyword, and enum (integer) localizations */ "copies" = "Kopya Sayısı"; "default printer" = "öntanımlı yazıcı"; "finishings" = "Sonlandırıcı"; "finishings.10" = "Katla"; "finishings.100" = "Z katla"; "finishings.101" = "Mühendislik Z katla"; "finishings.11" = "Kes"; "finishings.12" = "Balya"; "finishings.13" = "Kitapçık yapıcısı"; "finishings.15" = "Kapla"; "finishings.16" = "Katmanla"; "finishings.20" = "Sol üstten zımbala"; "finishings.21" = "Sol alttan zımbala"; "finishings.22" = "Sağ üstten zımbala"; "finishings.23" = "Sağ alttan zımbala"; "finishings.24" = "Kenar dikişi solda"; "finishings.25" = "Kenar dikişi üstte"; "finishings.26" = "Kenar dikişi sağda"; "finishings.27" = "Kenar dikişi altta"; "finishings.28" = "Solda 2 zımba"; "finishings.29" = "Üstte 2 zımba"; "finishings.3" = "Hiçbiri"; "finishings.30" = "Sağda 2 zımba"; "finishings.31" = "Altta 2 zımba"; "finishings.32" = "Solda 3 zımba"; "finishings.33" = "Üstte 3 zımba"; "finishings.34" = "Sağda 3 zımba"; "finishings.35" = "Altta 3 zımba"; "finishings.4" = "Zımba"; "finishings.5" = "Delgeç"; "finishings.50" = "Sola bağla"; "finishings.51" = "Üste bağla"; "finishings.52" = "Sağa bağla"; "finishings.53" = "Alta bağla"; "finishings.6" = "Kapak"; "finishings.60" = "Her sayfadan sonra kes"; "finishings.61" = "Her belgeden sonra kes"; "finishings.62" = "Her kümeden sonra kes"; "finishings.63" = "Her işten sonra kes"; "finishings.7" = "Bağla"; "finishings.70" = "Sol üstten del"; "finishings.71" = "Sol alttan del"; "finishings.72" = "Sağ üstten del"; "finishings.73" = "Sağ alttan del"; "finishings.74" = "Soldan 2 delik del"; "finishings.75" = "Üstten 2 delik del"; "finishings.76" = "Sağdan 2 delik del"; "finishings.77" = "Alttan 2 delik del"; "finishings.78" = "Soldan 3 delik del"; "finishings.79" = "Üstten 3 delik del"; "finishings.8" = "Tel dikiş"; "finishings.80" = "Sağdan 3 delik del"; "finishings.81" = "Alttan 3 delik del"; "finishings.82" = "Soldan 4 delik del"; "finishings.83" = "Üstten 4 delik del"; "finishings.84" = "Sağdan 4 delik del"; "finishings.85" = "Alttan 4 delik del"; "finishings.86" = "Soldan çoklu delik del"; "finishings.87" = "Üstten çoklu delik del"; "finishings.88" = "Sağdan çoklu delik del"; "finishings.89" = "Alttan çoklu delik del"; "finishings.9" = "Kenar dikişi"; "finishings.90" = "Akordeon katlama"; "finishings.91" = "Çift kapı katlama"; "finishings.92" = "Kapı katlama"; "finishings.93" = "Yarım katlama"; "finishings.94" = "Yarım Z katlama"; "finishings.95" = "Sol kapı katlama"; "finishings.96" = "Mektup katlama"; "finishings.97" = "Paralel katlama"; "finishings.98" = "Poster katlama"; "finishings.99" = "Sağ kapı katlama"; "holding new jobs" = "yeni işler bekletiliyor"; "job-state-reasons.aborted-by-system" = "Durduruluyor."; "job-state-reasons.compression-error" = "Sıkıştırma açılması hatası."; "job-state-reasons.document-format-error" = "Belge biçimi hatası."; "job-state-reasons.document-password-error" = "Belge parolası hatası."; "job-state-reasons.document-permission-error" = "Belge izin hatası."; "job-state-reasons.document-unprintable-error" = "Belge yazdırılamaz hatası."; "job-state-reasons.errors-detected" = "Hatalar algılandı."; "job-state-reasons.job-canceled-at-device" = "Yazıcıda iptal edildi."; "job-state-reasons.job-canceled-by-user" = "Kullanıcı tarafından iptal edildi."; "job-state-reasons.job-completed-successfully" = "Yazdırıldı."; "job-state-reasons.job-completed-with-errors" = "Hatalarla yazdırıldı."; "job-state-reasons.job-completed-with-warnings" = "Uyarılarla yazdırıldı."; "job-state-reasons.job-data-insufficient" = "Yetersiz veri."; "job-state-reasons.job-fetchable" = "Alınabilir."; "job-state-reasons.job-incoming" = "Geliyor."; "job-state-reasons.job-printing" = "Yazdırılıyor."; "job-state-reasons.job-queued" = "Yazdırmaya hazırlanıyor."; "job-state-reasons.job-spooling" = "Biriktiriliyor."; "job-state-reasons.none" = "Bekliyor."; "job-state-reasons.printer-stopped" = "Yazıcı çevrim dışı."; "job-state-reasons.printer-stopped-partly" = "Yazıcı kısmen durduruldu."; "job-state-reasons.processing-to-stop-point" = "Durduruluyor."; "job-state-reasons.queued-in-device" = "Hazır."; "job-state-reasons.warnings-detected" = "Uyarılar algılandı."; "job-state.3" = "Bekliyor"; "job-state.4" = "Bekletildi"; "job-state.5" = "İşleniyor"; "job-state.6" = "Durduruldu"; "job-state.7" = "İptal edildi"; "job-state.8" = "Sonlandırıldı"; "job-state.9" = "Tamamlandı"; "joining" = "katılıyor"; "media" = "Ortam"; "media-col" = "Ortam"; "media-size" = "Ortam Boyutu"; "media-size-name" = "Ortam Boyutu"; "media-source" = "Giriş Tepsisi"; "media-source.alternate" = "Alternatif"; "media-source.alternate-roll" = "Alternatif silindir"; "media-source.auto" = "Otomatik"; "media-source.bottom" = "Alt"; "media-source.by-pass-tray" = "Çok amaçlı tepsi"; "media-source.center" = "Orta"; "media-source.disc" = "Disk"; "media-source.envelope" = "Zarf"; "media-source.hagaki" = "Hagaki"; "media-source.large-capacity" = "Büyük kapasite"; "media-source.left" = "Sol"; "media-source.main" = "Ana"; "media-source.main-roll" = "Ana silindir"; "media-source.manual" = "El ile"; "media-source.middle" = "Orta"; "media-source.photo" = "Fotoğraf"; "media-source.rear" = "Arka"; "media-source.right" = "Sağ"; "media-source.roll-1" = "Silindir 1"; "media-source.roll-10" = "Silindir 10"; "media-source.roll-2" = "Silindir 2"; "media-source.roll-3" = "Silindir 3"; "media-source.roll-4" = "Silindir 4"; "media-source.roll-5" = "Silindir 5"; "media-source.roll-6" = "Silindir 6"; "media-source.roll-7" = "Silindir 7"; "media-source.roll-8" = "Silindir 8"; "media-source.roll-9" = "Silindir 9"; "media-source.side" = "Yan"; "media-source.top" = "Üst"; "media-source.tray-1" = "Tepsi 1"; "media-source.tray-10" = "Tepsi 10"; "media-source.tray-11" = "Tepsi 11"; "media-source.tray-12" = "Tepsi 12"; "media-source.tray-13" = "Tepsi 13"; "media-source.tray-14" = "Tepsi 14"; "media-source.tray-15" = "Tepsi 15"; "media-source.tray-16" = "Tepsi 16"; "media-source.tray-17" = "Tepsi 17"; "media-source.tray-18" = "Tepsi 18"; "media-source.tray-19" = "Tepsi 19"; "media-source.tray-2" = "Tepsi 2"; "media-source.tray-20" = "Tepsi 20"; "media-source.tray-3" = "Tepsi 3"; "media-source.tray-4" = "Tepsi 4"; "media-source.tray-5" = "Tepsi 5"; "media-source.tray-6" = "Tepsi 6"; "media-source.tray-7" = "Tepsi 7"; "media-source.tray-8" = "Tepsi 8"; "media-source.tray-9" = "Tepsi 9"; "media-tracking" = "Ortam İzleme"; "media-tracking.continuous" = "Sürekli"; "media-tracking.gap" = "Boşluk"; "media-tracking.mark" = "İşaret"; "media-tracking.web" = "Web"; "media-type" = "Ortam Türü"; "media-type.aluminum" = "Alüminyum"; "media-type.auto" = "Otomatik"; "media-type.back-print-film" = "Arka baskı filmi"; "media-type.cardboard" = "Karton"; "media-type.cardstock" = "Kart"; "media-type.cd" = "CD"; "media-type.continuous" = "Sürekli"; "media-type.continuous-long" = "Sürekli uzun"; "media-type.continuous-short" = "Sürekli kısa"; "media-type.corrugated-board" = "Oluklu karton"; "media-type.disc" = "Optik disk"; "media-type.disc-glossy" = "Parlak optik disk"; "media-type.disc-high-gloss" = "Çok parlak optik disk"; "media-type.disc-matte" = "Mat optik disk"; "media-type.disc-satin" = "Saten optik disk"; "media-type.disc-semi-gloss" = "Yarı parlak optik disk"; "media-type.double-wall" = "Çift duvar"; "media-type.dry-film" = "Kuru film"; "media-type.dvd" = "DVD"; "media-type.embossing-foil" = "Kabartma folyo"; "media-type.end-board" = "Bitiş tahtası"; "media-type.envelope" = "Zarf"; "media-type.envelope-archival" = "Arşiv zarfı"; "media-type.envelope-bond" = "Bond zarfı"; "media-type.envelope-coated" = "Kaplamalı zarf"; "media-type.envelope-cotton" = "Pamuk zarf"; "media-type.envelope-fine" = "İnce zarf"; "media-type.envelope-heavyweight" = "Ağır zarf"; "media-type.envelope-inkjet" = "Mürekkep püskürtmeli zarf"; "media-type.envelope-lightweight" = "Hafif zarf"; "media-type.envelope-plain" = "Düz zarf"; "media-type.envelope-preprinted" = "Önceden baskılı zarf"; "media-type.envelope-window" = "Pencereli zarf"; "media-type.fabric" = "Kumaş"; "media-type.fabric-archival" = "Arşiv kumaşı"; "media-type.fabric-glossy" = "Parlak kumaş"; "media-type.fabric-high-gloss" = "Çok parlak kumaş"; "media-type.fabric-matte" = "Mat kumaş"; "media-type.fabric-semi-gloss" = "Yarı parlak kumaş"; "media-type.fabric-waterproof" = "Su geçirmez kumaş"; "media-type.film" = "Film"; "media-type.flexo-base" = "Flekso taban"; "media-type.flexo-photo-polymer" = "Flekso fotoğraf polimeri"; "media-type.flute" = "Oluk"; "media-type.foil" = "Folyo"; "media-type.full-cut-tabs" = "Tam kesim sekmeler"; "media-type.glass" = "Cam"; "media-type.glass-colored" = "Cam renkli"; "media-type.glass-opaque" = "Cam opak"; "media-type.glass-surfaced" = "Cam yüzeyli"; "media-type.glass-textured" = "Cam dokulu"; "media-type.gravure-cylinder" = "Gravür silindiri"; "media-type.image-setter-paper" = "Görüntü ayarlayıcı kağıt"; "media-type.imaging-cylinder" = "Görüntüleme silindiri"; "media-type.labels" = "Etiketler"; "media-type.labels-colored" = "Renkli etiketler"; "media-type.labels-glossy" = "Parlak etiketler"; "media-type.labels-high-gloss" = "Çok parlak etiketler"; "media-type.labels-inkjet" = "Mürekkep püskürtmeli etiketler"; "media-type.labels-matte" = "Mat etiketler"; "media-type.labels-permanent" = "Kalıcı etiketler"; "media-type.labels-satin" = "Saten etiketler"; "media-type.labels-security" = "Güvenlik etiketleri"; "media-type.labels-semi-gloss" = "Yarı parlak etiketler"; "media-type.laminating-foil" = "Katmanlama folyosu"; "media-type.letterhead" = "Antetli kağıt"; "media-type.metal" = "Metal"; "media-type.metal-glossy" = "Metal parlak"; "media-type.metal-high-gloss" = "Metal çok parlak"; "media-type.metal-matte" = "Metal mat"; "media-type.metal-satin" = "Metal saten"; "media-type.metal-semi-gloss" = "Metal yarı parlak"; "media-type.mounting-tape" = "Montaj bandı"; "media-type.multi-layer" = "Çok katmanlı"; "media-type.multi-part-form" = "Çok parçalı form"; "media-type.other" = "Diğer"; "media-type.paper" = "Kağıt"; "media-type.photographic" = "Fotoğraf kağıdı"; "media-type.photographic-archival" = "Fotoğraf arşivi"; "media-type.photographic-film" = "Fotoğraf filmi"; "media-type.photographic-glossy" = "Parlak fotoğraf kağıdı"; "media-type.photographic-high-gloss" = "Çok parlak fotoğraf kağıdı"; "media-type.photographic-matte" = "Mat fotoğraf kağıdı"; "media-type.photographic-satin" = "Saten fotoğraf kağıdı"; "media-type.photographic-semi-gloss" = "Yarı parlak fotoğraf kağıdı"; "media-type.plastic" = "Plastik"; "media-type.plastic-archival" = "Plastik arşiv"; "media-type.plastic-colored" = "Plastik renkli"; "media-type.plastic-glossy" = "Plastik parlak"; "media-type.plastic-high-gloss" = "Plastik çok parlak"; "media-type.plastic-matte" = "Plastik mat"; "media-type.plastic-satin" = "Plastik saten"; "media-type.plastic-semi-gloss" = "Plastik yarı parlak"; "media-type.plate" = "Levha"; "media-type.polyester" = "Polyester"; "media-type.pre-cut-tabs" = "Önceden kesilmiş sekmeler"; "media-type.roll" = "Rulo"; "media-type.screen" = "Ekran"; "media-type.screen-paged" = "Ekran sayfalı"; "media-type.self-adhesive" = "Kendinden yapışkanlı"; "media-type.self-adhesive-film" = "Kendinden yapışkanlı film"; "media-type.shrink-foil" = "Daralan folyo"; "media-type.single-face" = "Tek yüz"; "media-type.single-wall" = "Tek duvar"; "media-type.sleeve" = "Kol"; "media-type.stationery" = "Kırtasiye"; "media-type.stationery-archival" = "Kırtasiye arşiv"; "media-type.stationery-coated" = "Kaplamalı kağıt"; "media-type.stationery-cotton" = "Kırtasiye pamuk"; "media-type.stationery-fine" = "Parşömen kağıt"; "media-type.stationery-heavyweight" = "Ağır kağıt"; "media-type.stationery-heavyweight-coated" = "Kırtasiye ağır kaplamalı"; "media-type.stationery-inkjet" = "Kırtasiye mürekkep püskürtmeli kağıt"; "media-type.stationery-letterhead" = "Antetli kağıt"; "media-type.stationery-lightweight" = "Hafif kağıt"; "media-type.stationery-preprinted" = "Önceden basılmış kağıt"; "media-type.stationery-prepunched" = "Delikli kağıt"; "media-type.tab-stock" = "Sekme stoğu"; "media-type.tractor" = "Traktör"; "media-type.transfer" = "Aktarım"; "media-type.transparency" = "Şeffaflık"; "media-type.triple-wall" = "Üçlü duvar"; "media-type.wet-film" = "Islak film"; "media.choice_iso_a4_210x297mm_na_letter_8.5x11in" = "A4 veya ABD Mektup"; "media.iso_2a0_1189x1682mm" = "2a0"; "media.iso_a0_841x1189mm" = "A0"; "media.iso_a0x3_1189x2523mm" = "A0x3"; "media.iso_a10_26x37mm" = "A10"; "media.iso_a1_594x841mm" = "A1"; "media.iso_a1x3_841x1783mm" = "A1x3"; "media.iso_a1x4_841x2378mm" = "A1x4"; "media.iso_a2_420x594mm" = "A2"; "media.iso_a2x3_594x1261mm" = "A2x3"; "media.iso_a2x4_594x1682mm" = "A2x4"; "media.iso_a2x5_594x2102mm" = "A2x5"; "media.iso_a3-extra_322x445mm" = "A3 (ek)"; "media.iso_a3_297x420mm" = "A3"; "media.iso_a3x3_420x891mm" = "A3x3"; "media.iso_a3x4_420x1189mm" = "A3x4"; "media.iso_a3x5_420x1486mm" = "A3x5"; "media.iso_a3x6_420x1783mm" = "A3x6"; "media.iso_a3x7_420x2080mm" = "A3x7"; "media.iso_a4-extra_235.5x322.3mm" = "A4 (ek)"; "media.iso_a4-tab_225x297mm" = "A4 (sekme)"; "media.iso_a4_210x297mm" = "A4"; "media.iso_a4x3_297x630mm" = "A4x3"; "media.iso_a4x4_297x841mm" = "A4x4"; "media.iso_a4x5_297x1051mm" = "A4x5"; "media.iso_a4x6_297x1261mm" = "A4x6"; "media.iso_a4x7_297x1471mm" = "A4x7"; "media.iso_a4x8_297x1682mm" = "A4x8"; "media.iso_a4x9_297x1892mm" = "A4x9"; "media.iso_a5-extra_174x235mm" = "A5 (ek)"; "media.iso_a5_148x210mm" = "A5"; "media.iso_a6_105x148mm" = "A6"; "media.iso_a7_74x105mm" = "A7"; "media.iso_a8_52x74mm" = "A8"; "media.iso_a9_37x52mm" = "A9"; "media.iso_b0_1000x1414mm" = "B0"; "media.iso_b10_31x44mm" = "B10"; "media.iso_b1_707x1000mm" = "B1"; "media.iso_b2_500x707mm" = "B2"; "media.iso_b3_353x500mm" = "B3"; "media.iso_b4_250x353mm" = "B4"; "media.iso_b5-extra_201x276mm" = "B5 (ek)"; "media.iso_b5_176x250mm" = "B5 Zarf"; "media.iso_b6_125x176mm" = "B6"; "media.iso_b6c4_125x324mm" = "B6/C4Zarf"; "media.iso_b7_88x125mm" = "B7"; "media.iso_b8_62x88mm" = "B8"; "media.iso_b9_44x62mm" = "B9"; "media.iso_c0_917x1297mm" = "C0 Zarf"; "media.iso_c10_28x40mm" = "C10 Zarf"; "media.iso_c1_648x917mm" = "C1 Zarf"; "media.iso_c2_458x648mm" = "C2 Zarf"; "media.iso_c3_324x458mm" = "C3 Zarf"; "media.iso_c4_229x324mm" = "C4 Zarf"; "media.iso_c5_162x229mm" = "C5 Zarf"; "media.iso_c6_114x162mm" = "C6 Zarf"; "media.iso_c6c5_114x229mm" = "C6/C5 Zarf"; "media.iso_c7_81x114mm" = "C7 Zarf"; "media.iso_c7c6_81x162mm" = "C7/C6 Zarf"; "media.iso_c8_57x81mm" = "C8 Zarf"; "media.iso_c9_40x57mm" = "C9 Zarf"; "media.iso_dl_110x220mm" = "DL Zarf"; "media.iso_ra0_860x1220mm" = "ISO RA0"; "media.iso_ra1_610x860mm" = "ISO RA1"; "media.iso_ra2_430x610mm" = "ISO RA2"; "media.iso_ra3_305x430mm" = "ISO RA3"; "media.iso_ra4_215x305mm" = "ISO RA4"; "media.iso_sra0_900x1280mm" = "ISO SRA0"; "media.iso_sra1_640x900mm" = "ISO SRA1"; "media.iso_sra2_450x640mm" = "ISO SRA2"; "media.iso_sra3_320x450mm" = "ISO SRA3"; "media.iso_sra4_225x320mm" = "ISO SRA4"; "media.jis_b0_1030x1456mm" = "JIS B0"; "media.jis_b10_32x45mm" = "JIS B10"; "media.jis_b1_728x1030mm" = "JIS B1"; "media.jis_b2_515x728mm" = "JIS B2"; "media.jis_b3_364x515mm" = "JIS B3"; "media.jis_b4_257x364mm" = "JIS B4"; "media.jis_b5_182x257mm" = "JIS B5"; "media.jis_b6_128x182mm" = "JIS B6"; "media.jis_b7_91x128mm" = "JIS B7"; "media.jis_b8_64x91mm" = "JIS B8"; "media.jis_b9_45x64mm" = "JIS B9"; "media.jis_exec_216x330mm" = "JIS Yönetici"; "media.jpn_chou2_111.1x146mm" = "Zarf Chou 2"; "media.jpn_chou3_120x235mm" = "Zarf Chou 3"; "media.jpn_chou40_90x225mm" = "Zarf Chou 40"; "media.jpn_chou4_90x205mm" = "Zarf Chou 4"; "media.jpn_hagaki_100x148mm" = "Hagaki"; "media.jpn_kahu_240x322.1mm" = "Zarf Kahu"; "media.jpn_kaku2_240x332mm" = "Zarf Kahu 2"; "media.jpn_oufuku_148x200mm" = "Oufuku Cevap Kartpostalı"; "media.jpn_you4_105x235mm" = "Zarf Sen 4"; "media.na_a2_4.375x5.75in" = "Zarf A2"; "media.na_c5_6.5x9.5in" = "Zarf C5"; "media.na_executive_7.25x10.5in" = "Yönetici"; "media.na_fanfold-eur_8.5x12in" = "Avrupa Yelpaze"; "media.na_fanfold-us_11x14.875in" = "ABD Yelpaze"; "media.na_foolscap_8.5x13in" = "Büyük Dosya Kağıdı"; "media.na_invoice_5.5x8.5in" = "Beyanat"; "media.na_legal-extra_9.5x15in" = "ABD Yasal (Ek)"; "media.na_legal_8.5x14in" = "ABD Yasal"; "media.na_letter-extra_9.5x12in" = "ABD Mektup (Ek)"; "media.na_letter-plus_8.5x12.69in" = "ABD Mektup (Artı)"; "media.na_letter_8.5x11in" = "ABD Mektup"; "media.na_monarch_3.875x7.5in" = "Kraliyet Zarfı"; "media.na_number-10_4.125x9.5in" = "Zarf #10"; "media.na_number-11_4.5x10.375in" = "Zarf #11"; "media.na_number-12_4.75x11in" = "Zarf #12"; "media.na_number-14_5x11.5in" = "Zarf #14"; "media.na_number-9_3.875x8.875in" = "Zarf #9"; "media.na_personal_3.625x6.5in" = "Kişisel Zarf"; "media.na_quarto_8.5x10.83in" = "Çeyrek"; "media.om_folio-sp_215x315mm" = "Folyo"; "media.om_folio_210x330mm" = "Folyo (Özel)"; "media.om_invite_220x220mm" = "Davetiye Zarfı"; "media.om_italian_110x230mm" = "İtalyan Zarfı"; "media.om_juuro-ku-kai_198x275mm" = "198 x 275mm"; "media.om_large-photo_200x300" = "200 x 300"; "media.om_medium-photo_130x180mm" = "130 x 180mm"; "media.om_pa-kai_267x389mm" = "267 x 389mm"; "media.om_postfix_114x229mm" = "Postfix Zarfı"; "media.prc_10_324x458mm" = "Çin Zarfı #10"; "media.prc_16k_146x215mm" = "Çin 16k"; "media.prc_1_102x165mm" = "Çin Zarfı #1"; "media.prc_2_102x176mm" = "Çin Zarfı #2"; "media.prc_32k_97x151mm" = "Çin 32k"; "media.prc_3_125x176mm" = "Çin Zarfı #3"; "media.prc_4_110x208mm" = "Çin Zarfı #4"; "media.prc_5_110x220mm" = "Çin Zarfı #5"; "media.prc_6_120x320mm" = "Çin Zarfı #6"; "media.prc_7_160x230mm" = "Çin Zarfı #7"; "media.prc_8_120x309mm" = "Çin Zarfı #8"; "media.roc_16k_7.75x10.75in" = "ROC 16k"; "media.roc_8k_10.75x15.5in" = "ROC 8k"; "not configured" = "yapılandırılmadı"; "not visible" = "görünür değil"; "off" = "kapalı"; "on" = "açık"; "orientation-requested" = "Yön"; "orientation-requested.3" = "Portre"; "orientation-requested.4" = "Manzara"; "orientation-requested.5" = "Ters manzara"; "orientation-requested.6" = "Ters portre"; "orientation-requested.7" = "Hiçbiri"; "output-bin" = "Çıkış Tepsisi"; "output-bin.auto" = "Otomatik"; "output-bin.bottom" = "Alt"; "output-bin.center" = "Orta"; "output-bin.face-down" = "Yüzü aşağı dönük"; "output-bin.face-up" = "Yüzü yukarı dönük"; "output-bin.large-capacity" = "Büyük kapasite"; "output-bin.left" = "Sol"; "output-bin.mailbox-1" = "Posta kutusu 1"; "output-bin.mailbox-10" = "Posta kutusu 10"; "output-bin.mailbox-2" = "Posta kutusu 2"; "output-bin.mailbox-3" = "Posta kutusu 3"; "output-bin.mailbox-4" = "Posta kutusu 4"; "output-bin.mailbox-5" = "Posta kutusu 5"; "output-bin.mailbox-6" = "Posta kutusu 6"; "output-bin.mailbox-7" = "Posta kutusu 7"; "output-bin.mailbox-8" = "Posta kutusu 8"; "output-bin.mailbox-9" = "Posta kutusu 9"; "output-bin.middle" = "Orta"; "output-bin.my-mailbox" = "Posta kutum"; "output-bin.rear" = "Arka"; "output-bin.right" = "Sağ"; "output-bin.side" = "Yan"; "output-bin.stacker-1" = "Yığıcı 1"; "output-bin.stacker-10" = "Yığıcı 10"; "output-bin.stacker-2" = "Yığıcı 2"; "output-bin.stacker-3" = "Yığıcı 3"; "output-bin.stacker-4" = "Yığıcı 4"; "output-bin.stacker-5" = "Yığıcı 5"; "output-bin.stacker-6" = "Yığıcı 6"; "output-bin.stacker-7" = "Yığıcı 7"; "output-bin.stacker-8" = "Yığıcı 8"; "output-bin.stacker-9" = "Yığıcı 9"; "output-bin.top" = "Üst"; "output-bin.tray-1" = "Tepsi 1"; "output-bin.tray-10" = "Tepsi 10"; "output-bin.tray-2" = "Tepsi 2"; "output-bin.tray-3" = "Tepsi 3"; "output-bin.tray-4" = "Tepsi 4"; "output-bin.tray-5" = "Tepsi 5"; "output-bin.tray-6" = "Tepsi 6"; "output-bin.tray-7" = "Tepsi 7"; "output-bin.tray-8" = "Tepsi 8"; "output-bin.tray-9" = "Tepsi 9"; "print-color-mode" = "Yazdırma Modu"; "print-color-mode.auto" = "Otomatik"; "print-color-mode.auto-monochrome" = "Otomatik tek renkli"; "print-color-mode.bi-level" = "Metin"; "print-color-mode.color" = "Renk"; "print-color-mode.highlight" = "Vurgula"; "print-color-mode.monochrome" = "Tek renkli"; "print-color-mode.process-bi-level" = "Metin işle"; "print-color-mode.process-monochrome" = "Tek renkli işle"; "print-content-optimize" = "İyileştir"; "print-content-optimize.auto" = "Otomatik"; "print-content-optimize.graphic" = "Grafik"; "print-content-optimize.photo" = "Fotoğraf"; "print-content-optimize.text" = "Metin"; "print-content-optimize.text-and-graphic" = "Metin ve grafikler"; "print-darkness" = "Yazdırma Koyuluğu"; "print-quality" = "Yazdırma Kalitesi"; "print-quality.3" = "Taslak"; "print-quality.4" = "Normal"; "print-quality.5" = "En iyi"; "print-scaling" = "Ölçekleme"; "print-scaling.auto" = "Otomatik"; "print-scaling.auto-fit" = "Otomatik sığdır"; "print-scaling.fill" = "Doldur"; "print-scaling.fit" = "Sığdır"; "print-scaling.none" = "Hiçbiri"; "print-speed" = "Yazdırma Hızı"; "printer-resolution" = "Çözünürlük"; "printer-state-reasons.cover-open" = "Kapak açık."; "printer-state-reasons.door-open" = "Kapı açık."; "printer-state-reasons.identify-printer-requested" = "Yazıcı tanımla."; "printer-state-reasons.input-tray-missing" = "Kağıt tepsisi eksik."; "printer-state-reasons.marker-supply-empty" = "Mürekkep bitti."; "printer-state-reasons.marker-supply-low" = "Mürekkep az kaldı."; "printer-state-reasons.marker-waste-almost-full" = "Atık kutusu neredeyse dolu."; "printer-state-reasons.marker-waste-full" = "Atık kutusu dolu."; "printer-state-reasons.media-empty" = "Kağıt bitti."; "printer-state-reasons.media-jam" = "Kağıt sıkıştı."; "printer-state-reasons.media-low" = "Kağıdı yakında değiştir."; "printer-state-reasons.media-needed" = "Kağıt yükle."; "printer-state-reasons.none" = "Hazır."; "printer-state-reasons.offline" = "Çevrim dışı."; "printer-state-reasons.other" = "Yazıcıya bakın."; "printer-state-reasons.spool-area-full" = "Yazıcı meşgul."; "printer-state-reasons.toner-empty" = "Toner bitti."; "printer-state-reasons.toner-low" = "Toner az kaldı."; "printer-state.3" = "Boşta"; "printer-state.4" = "İşleniyor"; "printer-state.5" = "Durduruldu"; "sides" = "2 Taraflı Yazdırma"; "sides.one-sided" = "Kapalı"; "sides.two-sided-long-edge" = "Açık (portre)"; "sides.two-sided-short-edge" = "Açık (manzara)"; "unable to join" = "katılamıyor"; "yesterday at %02d:%02d:%02d" = "dün, %02d:%02d:%02d"; "Åland Islands" = "Åland Adaları"; pappl-1.4.9/pappl/strings/tr_strings.h000066400000000000000000001567701476704353100200470ustar00rootroot00000000000000static const char *tr_strings = "\" -a Cancel all jobs (cancel).\" = \" -a Tüm işleri iptal et (cancel).\";\n" "\" -c COPIES\" = \" -c KOPYA\";\n" "\" -d PRINTER Specify printer.\" = \" -d YAZICI Yazıcı belirt.\";\n" "\" -j JOB-ID Specify job ID (cancel).\" = \" -j İŞ-NO İş numarası belirt (cancel).\";\n" "\" -m DRIVER-NAME Specify driver (add/modify).\" = \" -m SÜRÜCÜ-ADI Sürücü belirt (add/modify).\";\n" "\" -n COPIES Specify number of copies (submit).\" = \" -n KOPYA Kopya sayısını belirt (submit).\";\n" "\" -o %s=%s (default)\" = \" -o %s=%s (default)\";\n" "\" -o NAME=VALUE Specify option (add,modify,server,submit).\" = \" -o AD=DEĞER Seçenek belirt (add,modify,server,submit).\";\n" "\" -o print-darkness=-100 to 100\" = \" -o print-darkness=-100 ila 100\";\n" "\" -o printer-darkness=0 to 100\" = \" -o printer-darkness=0 ila 100\";\n" "\" -o printer-geo-location='geo:LATITUDE,LONGITUDE'\" = \" -o printer-geo-location='geo:ENLEM,BOYLAM'\";\n" "\" -o printer-location='LOCATION'\" = \" -o printer-location='KONUM'\";\n" "\" -o printer-organization='ORGANIZATION'\" = \" -o printer-organization='ORGANİZASYON'\";\n" "\" -o printer-organizational-unit='UNIT/SECTION'\" = \" -o printer-organizational-unit='BİRİM/BÖLÜM'\";\n" "\" -u URI Specify ipp: or ipps: printer/server.\" = \" -u URI ipp: veya ipps: yazıcı/sunucu belirt.\";\n" "\" -v DEVICE-URI Specify socket: or usb: device (add/modify).\" = \" -v AYGIT-URI socket: veya usb: aygıt belirt (add/modify).\";\n" "\" add PRINTER Add a printer.\" = \" add YAZICI Yazıcı ekle.\";\n" "\" autoadd Automatically add supported printers.\" = \" autoadd Desteklenen yazıcıları otomatik olarak ekle.\";\n" "\" cancel Cancel one or more jobs.\" = \" cancel Bir veya daha fazla işi iptal et.\";\n" "\" default Set the default printer.\" = \" default Öntanımlı yazıcıyı ayarla.\";\n" "\" delete Delete a printer.\" = \" delete Yazıcı sil.\";\n" "\" devices List devices.\" = \" devices Aygıtları listele.\";\n" "\" drivers List drivers.\" = \" drivers Sürücüleri listele.\";\n" "\" jobs List jobs.\" = \" jobs İşleri listele.\";\n" "\" modify Modify a printer.\" = \" modify Yazıcı düzenle.\";\n" "\" options List printer options.\" = \" options Yazıcı seçeneklerini listele.\";\n" "\" pause Pause printing for a printer.\" = \" pause Bir yazıcı için yazdırmayı duraklat.\";\n" "\" printers List printers.\" = \" printers Yazıcıları listele.\";\n" "\" resume Resume printing for a printer.\" = \" resume Bir yazıcı için yazdırmayı devam ettir.\";\n" "\" server Run a server.\" = \" server Sunucu çalıştır.\";\n" "\" shutdown Shutdown a running server.\" = \" shutdown Çalışan bir sunucuyu kapat.\";\n" "\" status Show server/printer/job status.\" = \" status Sunucu/yazıcı/iş durumunu göster.\";\n" "\" submit Submit a file for printing.\" = \" submit Yazdırmak için bir dosya gönder.\";\n" "\"%04d-%02d-%02d at %02d:%02d:%02d\" = \"%04d-%02d-%02d, %02d:%02d:%02d\";\n" "\"%d days ago at %02d:%02d:%02d\" = \"%d gün önce, %02d:%02d:%02d'de\";\n" "\"%d inches/sec\" = \"%d inç/s\";\n" "\"%d job\" = \"%d iş\";\n" /* Media size in millimeters */ "\"%d x %dmm\" = \"%d x %dmm\";\n" "\"%ddpi\" = \"%ddpi\";\n" "\"%dx%ddpi\" = \"%dx%ddpi\";\n" /* Media size in inches */ "\"%g x %g\\\"\" = \"%g x %g\\\"\";\n" /* size (type+borderless) */ "\"%s (%s%s)\" = \"%s (%s%s)\";\n" /* size (type+borderless) from source/tray */ "\"%s (%s%s) from %s\" = \"%s (%s%s) kaynak: %s\";\n" /* Source/Tray Media */ "\"%s Media\" = \"%s Ortamı\";\n" "\"%s: Bad 'server-port' value.\" = \"%s: Hatalı 'sunucu-bağlantı noktası' değeri.\";\n" "\"%s: Bad job ID.\" = \"%s: Hatalı iş numarası.\";\n" "\"%s: Bad printer URI '%s'.\" = \"%s: Hatalı yazıcı URI'si: '%s'.\";\n" "\"%s: Cannot specify more than one sub-command.\" = \"%s: Birden fazla alt komut belirtilemez.\";\n" "\"%s: Empty print file received on the standard input.\" = \"%s: Standart girişte boş yazdırma dosyası alındı.\";\n" "\"%s: Failed to create a system.\" = \"%s: Sistem oluşturulamadı.\";\n" "\"%s: Missing '-d PRINTER'.\" = \"%s: '-d YAZICI' eksik.\";\n" "\"%s: Missing '-m DRIVER-NAME'.\" = \"%s: '-m SÜRÜCÜ-ADI' eksik.\";\n" "\"%s: Missing '-v DEVICE-URI'.\" = \"%s: '-v AYGIT-URI' eksik.\";\n" "\"%s: Missing copy count after '-n'.\" = \"%s: '-n' seçeneğinden sonra kopya sayısı eksik.\";\n" "\"%s: Missing device URI after '-v'.\" = \"%s: '-v' seçeneğinden sonra aygıt URI'si eksik.\";\n" "\"%s: Missing driver name after '-m'.\" = \"%s: '-m' seçeneğinden sonra sürücü adı eksik.\";\n" "\"%s: Missing filename after '--'.\" = \"%s: '--' sonrasında dosya adı eksik.\";\n" "\"%s: Missing hostname after '-h'.\" = \"%s: '-h' seçeneğinden sonra ana makine adı eksik.\";\n" "\"%s: Missing job ID after '-j'.\" = \"%s: '-j' seçeneğinden sonra iş numarası eksik.\";\n" "\"%s: Missing option(s) after '-o'.\" = \"%s: '-o' sonrasında seçenek(ler) eksik.\";\n" "\"%s: Missing printer URI after '-u'.\" = \"%s: '-u' seçeneğinden sonra yazıcı URI'si eksik.\";\n" "\"%s: Missing printer name after '-d'.\" = \"%s: '-d' seçeneğinden sonra yazıcı adı eksik.\";\n" "\"%s: Missing space after '-o'.\" = \"%s: '-o' seçeneğinden sonra boşluk eksik.\";\n" "\"%s: Missing title after '-t'.\" = \"%s: '-t' seçeneğinden sonra başlık eksik.\";\n" "\"%s: No default printer available.\" = \"%s: Kullanılabilir öntanımlı yazıcı yok.\";\n" "\"%s: No files to print.\" = \"%s: Yazdırılacak dosya yok.\";\n" "\"%s: Server is not running.\" = \"%s: Sunucu çalışmıyor.\";\n" "\"%s: Sub-command '%s' does not accept files.\" = \"%s: '%s' alt komutu dosya kabul etmiyor.\";\n" "\"%s: Sub-command 'autoadd' is not supported.\" = \"%s: 'autoadd' alt komutu desteklenmiyor.\";\n" "\"%s: Too many files.\" = \"%s: Çok fazla dosya.\";\n" "\"%s: Unable to access '%s': %s\" = \"%s: '%s' erişilebilir değil: %s\";\n" "\"%s: Unable to add printer: %s\" = \"%s: Yazıcı eklenemiyor: %s\";\n" "\"%s: Unable to cancel job: %s\" = \"%s: İş iptal edilemiyor: %s\";\n" "\"%s: Unable to connect to printer at '%s:%d': %s\" = \"%s: '%s:%d' konumunda yazıcıya bağlanılamıyor: %s\";\n" "\"%s: Unable to connect to server: %s\" = \"%s: Sunucuya bağlanılamıyor: %s\";\n" "\"%s: Unable to create temporary file: %s\" = \"%s: Geçici dosya oluşturulamıyor: %s\";\n" "\"%s: Unable to delete printer: %s\" = \"%s: Yazıcı silinemiyor: %s\";\n" "\"%s: Unable to get available devices: %s\" = \"%s: Kullanılabilir aygıtlar alınamıyor: %s\";\n" "\"%s: Unable to get information for '%s': %s\" = \"%s: '%s' için bilgi alınamıyor: %s\";\n" "\"%s: Unable to get information for printer: %s\" = \"%s: Yazıcı için bilgi alınamıyor: %s\";\n" "\"%s: Unable to get printer options: %s\" = \"%s: Yazıcı seçenekleri alınamıyor: %s\";\n" "\"%s: Unable to modify printer: %s\" = \"%s: Yazıcı düzenlenemiyor: %s\";\n" "\"%s: Unable to pause printer: %s\" = \"%s: Yazıcı duraklatılamıyor: %s\";\n" "\"%s: Unable to print '%s': %s\" = \"%s: '%s' yazdırılamıyor: %s\";\n" "\"%s: Unable to resume printer: %s\" = \"%s: Yazıcı devam ettirilemiyor: %s\";\n" "\"%s: Unable to set default printer: %s\" = \"%s: Öntanımlı yazıcı ayarlanamıyor: %s\";\n" "\"%s: Unable to shutdown server: %s\" = \"%s: Sunucu kapatılamıyor: %s\";\n" "\"%s: Unable to start server: %s\" = \"%s: Sunucu başlatılamıyor: %s\";\n" "\"%s: Unable to write to temporary file: %s\" = \"%s: Geçici dosyaya yazılamıyor: %s\";\n" "\"%s: Unknown option '%s'.\" = \"%s: Bilinmeyen seçenek '%s'.\";\n" "\"%s: Unknown option '-%c'.\" = \"%s: Bilinmeyen seçenek '-%c'.\";\n" "\"%s: Unknown sub-command '%s'.\" = \"%s: Bilinmeyen alt komut '%s'.\";\n" "\"%s: Unsupported URI scheme '%s'.\" = \"%s: Desteklenmeyen URI şeması '%s'.\";\n" "\"%s: Warning - user credentials are not supported in URIs.\" = \"%s: Uyarı - URI'lerde kullanıcı kimlik bilgileri desteklenmiyor.\";\n" "\", Borderless\" = \", Kenarlıksız\";\n" "\"A printer with that name already exists.\" = \"Bu ada sahip bir yazıcı zaten var.\";\n" "\"Aborted %s\" = \"%s sonlandırıldı\";\n" "\"Add Printer\" = \"Yazıcı Ekle\";\n" "\"Admin Group\" = \"Yönetici Grubu\";\n" "\"Afghanistan\" = \"Afganistan\";\n" "\"Albania\" = \"Arnavutluk\";\n" "\"Algeria\" = \"Cezayir\";\n" "\"American Samoa\" = \"Amerikan Samoası\";\n" "\"Andorra\" = \"Andorra\";\n" "\"Angola\" = \"Angola\";\n" "\"Anguilla\" = \"Anguilla\";\n" "\"Antarctica\" = \"Antarktika\";\n" "\"Antigua and Barbuda\" = \"Antigua ve Barbuda\";\n" "\"Argentina\" = \"Arjantin\";\n" "\"Armenia\" = \"Ermenistan\";\n" "\"Aruba\" = \"Aruba\";\n" "\"Australia\" = \"Avustralya\";\n" "\"Austria\" = \"Avusturya\";\n" "\"Auto\" = \"Otomatik\";\n" "\"Auto-Detect Driver\" = \"Sürücüyü Otomatik Algıla\";\n" "\"Azerbaijan\" = \"Azerbaycan\";\n" "\"Bad administration group.\" = \"Hatalı yönetim grubu.\";\n" "\"Bad port number.\" = \"Hatalı bağlantı noktası numarası.\";\n" "\"Bad print group.\" = \"Hatalı yazdırma grubu.\";\n" "\"Bad printer defaults.\" = \"Hatalı yazıcı öntanımlı değerleri.\";\n" "\"Bahamas\" = \"Bahamalar\";\n" "\"Bahrain\" = \"Bahreyn\";\n" "\"Bangladesh\" = \"Bangladeş\";\n" "\"Barbados\" = \"Barbados\";\n" "\"Belarus\" = \"Belarus\";\n" "\"Belgium\" = \"Belçika\";\n" "\"Belize\" = \"Belize\";\n" "\"Benin\" = \"Benin\";\n" "\"Bermuda\" = \"Bermuda\";\n" "\"Bhutan\" = \"Bhutan\";\n" "\"Bolivia (Plurinational State of)\" = \"Bolivya (Çokuluslu Devleti)\";\n" "\"Bonaire, Sint Eustatius and Saba\" = \"Bonaire, Sint Eustatius ve Saba\";\n" "\"Borderless\" = \"Kenarlıksız\";\n" "\"Bosnia and Herzegovina\" = \"Bosna Hersek\";\n" "\"Botswana\" = \"Botsvana\";\n" "\"Bouvet Island\" = \"Bouvet Adası\";\n" "\"Brazil\" = \"Brezilya\";\n" "\"British Indian Ocean Territory\" = \"Britanya Hint Okyanusu Toprakları\";\n" "\"Brunei Darussalam\" = \"Brunei Sultanlığı\";\n" "\"Bulgaria\" = \"Bulgaristan\";\n" "\"Burkina Faso\" = \"Burkina Faso\";\n" "\"Burundi\" = \"Burundi\";\n" "\"Cabo Verde\" = \"Yeşil Burun Adaları\";\n" "\"Cambodia\" = \"Kamboçya\";\n" "\"Cameroon\" = \"Kamerun\";\n" "\"Canada\" = \"Kanada\";\n" "\"Cancel All Jobs\" = \"Tüm İşleri İptal Et\";\n" "\"Cancel Job\" = \"İşi İptal Et\";\n" "\"Canceled %s\" = \"%s iptal edildi\";\n" "\"Canceling\" = \"İptal ediliyor\";\n" "\"Cayman Islands\" = \"Cayman Adaları\";\n" "\"Central African Republic\" = \"Orta Afrika Cumhuriyeti\";\n" "\"Certificate created.\" = \"Sertifika oluşturuldu.\";\n" "\"Certificate installed.\" = \"Sertifika kuruldu.\";\n" "\"Certificate request created.\" = \"Sertifika isteği oluşturuldu.\";\n" "\"Chad\" = \"Çad\";\n" "\"Change Access Password\" = \"Erişim Parolasını Değiştir\";\n" "\"Change Log Level\" = \"Günlük Kaydı Seviyesini Değiştir\";\n" "\"Change Network Settings\" = \"Ağ Ayarlarını Değiştir\";\n" "\"Change Wi-Fi Network\" = \"Wi-Fi Ağını Değiştir\";\n" "\"Changes Saved.\" = \"Değişiklikler Kaydedildi.\";\n" "\"Changes saved.\" = \"Değişiklikler kaydedildi.\";\n" "\"Chile\" = \"Şili\";\n" "\"China\" = \"Çin\";\n" "\"Christmas Island\" = \"Christmas Adası\";\n" "\"City/Locality\" = \"Şehir/Yerellik\";\n" "\"Cocos (Keeling) Islands\" = \"Cocos (Keeling) Adaları\";\n" "\"Colombia\" = \"Kolombiya\";\n" "\"Comoros\" = \"Komorlar\";\n" "\"Completed %s\" = \"%s tamamlandı\";\n" "\"Configuration\" = \"Yapılandırma\";\n" "\"Configure Media\" = \"Ortamı Yapılandır\";\n" "\"Confirm Cancel All\" = \"Tümünü İptal Etmeyi Onayla\";\n" "\"Confirm Delete Printer\" = \"Yazıcıyı Silmeyi Onayla\";\n" "\"Congo\" = \"Kongo\";\n" "\"Congo, Democratic Republic of the\" = \"Kongo Demokratik Cumhuriyeti\";\n" "\"Contact\" = \"İletişim\";\n" "\"Cook Islands\" = \"Cook Adaları\";\n" "\"Costa Rica\" = \"Kosta Rika\";\n" "\"Create Certificate Signing Request\" = \"Sertifika İmzalama İsteği Oluştur\";\n" "\"Create New Certificate\" = \"Yeni Sertifika Oluştur\";\n" "\"Create New TLS Certificate\" = \"Yeni TLS Sertifikası Oluştur\";\n" "\"Create TLS Certificate Request\" = \"TLS Sertifikası İsteği Oluştur\";\n" "\"Croatia\" = \"Hırvatistan\";\n" "\"Cuba\" = \"Küba\";\n" "\"Curaçao\" = \"Curaçao\";\n" "\"Current Password\" = \"Geçerli Parola\";\n" "\"Custom Size\" = \"Özel Boyut\";\n" "\"Cyprus\" = \"Kıbrıs\";\n" "\"Czechia\" = \"Çekya\";\n" "\"Côte d'Ivoire\" = \"Fildişi Sahili\";\n" "\"DHCP\" = \"DHCP\";\n" "\"DHCP w/Manual Address\" = \"DHCP ve Elle Adres\";\n" "\"DNS-SD Service Name\" = \"DNS-SD Hizmet Adı\";\n" "\"Debugging\" = \"Hata Ayıklama\";\n" "\"Default printer set.\" = \"Öntanımlı yazıcı ayarlandı.\";\n" "\"Delete\" = \"Sil\";\n" "\"Delete Printer\" = \"Yazıcı Sil\";\n" "\"Denmark\" = \"Danimarka\";\n" "\"Djibouti\" = \"Cibuti\";\n" "\"Domain Name\" = \"Etki Alanı Adı\";\n" "\"Dominica\" = \"Dominika\";\n" "\"Dominican Republic\" = \"Dominik Cumhuriyeti\";\n" "\"Download Certificate Request File\" = \"Sertifika İstek Dosyasını İndir\";\n" "\"Ecuador\" = \"Ekvador\";\n" "\"Egypt\" = \"Mısır\";\n" "\"El Salvador\" = \"El Salvador\";\n" "\"Equatorial Guinea\" = \"Equatorial Guinea\";\n" "\"Eritrea\" = \"Eritre\";\n" "\"Errors\" = \"Hatalar\";\n" "\"Estonia\" = \"Estonya\";\n" "\"Eswatini\" = \"Esvatini\";\n" "\"Ethiopia\" = \"Etiyopya\";\n" "\"Falkland Islands (Malvinas)\" = \"Falkland Adaları (Malvinas)\";\n" "\"Faroe Islands\" = \"Faroe Adaları\";\n" "\"Fatal Errors/Conditions\" = \"Ölümcül Hatalar/Koşullar\";\n" "\"Fiji\" = \"Fiji\";\n" "\"Finland\" = \"Finlandiya\";\n" "\"France\" = \"Fransa\";\n" "\"French Guiana\" = \"Fransız Guyanası\";\n" "\"French Polynesia\" = \"Fransız Polinezyası\";\n" "\"French Southern Territories\" = \"Fransız Güney Toprakları\";\n" "\"Gabon\" = \"Gabon\";\n" "\"Gambia\" = \"Gambiya\";\n" "\"Georgia\" = \"Gürcistan\";\n" "\"Germany\" = \"Almanya\";\n" "\"Ghana\" = \"Gana\";\n" "\"Gibraltar\" = \"Cebelitarık\";\n" "\"Greece\" = \"Yunanistan\";\n" "\"Greenland\" = \"Grönland\";\n" "\"Grenada\" = \"Grenada\";\n" "\"Group changes saved.\" = \"Grup değişiklikleri kaydedildi.\";\n" "\"Guadeloupe\" = \"Guadeloupe\";\n" "\"Guam\" = \"Guam\";\n" "\"Guatemala\" = \"Guatemala\";\n" "\"Guernsey\" = \"Guernsey\";\n" "\"Guinea\" = \"Gine\";\n" "\"Guinea-Bissau\" = \"Gine-Bissau\";\n" "\"Guyana\" = \"Guyana\";\n" "\"Haiti\" = \"Haiti\";\n" "\"Heard Island and McDonald Islands\" = \"Heard Adası ve McDonald Adaları\";\n" "\"Hidden SSID\" = \"Gizli SSID\";\n" "\"Hold Job\" = \"İşi Beklet\";\n" "\"Hold New Jobs\" = \"Yeni İşleri Beklet\";\n" "\"Holding new jobs.\" = \"Yeni işler bekletiliyor.\";\n" "\"Holy See\" = \"Vatikan\";\n" "\"Honduras\" = \"Honduras\";\n" "\"Hong Kong\" = \"Hong Kong\";\n" "\"Hostname\" = \"Ana Makine Adı\";\n" "\"Human-Readable Location\" = \"İnsan Tarafından Okunabilir Konum\";\n" "\"Hungary\" = \"Macaristan\";\n" "\"IPv4 Address\" = \"IPv4 Adresi\";\n" "\"IPv4 Configuration\" = \"IPv4 Yapılandırması\";\n" "\"IPv4 Gateway\" = \"IPv4 Ağ Geçidi\";\n" "\"IPv4 Netmask\" = \"IPv4 Ağ Maskesi\";\n" "\"IPv6 Address\" = \"IPv6 Adresi\";\n" "\"IPv6 Configuration\" = \"IPv6 Yapılandırması\";\n" "\"IPv6 Link-Local\" = \"IPv6 Yerel Bağlantı\";\n" "\"IPv6 Prefix Length\" = \"IPv6 Ön Ek Uzunluğu\";\n" "\"Iceland\" = \"İzlanda\";\n" "\"Identify Printer\" = \"Yazıcı Tanımla\";\n" "\"India\" = \"Hindistan\";\n" "\"Indonesia\" = \"Endonezya\";\n" "\"Informational\" = \"Bilgi\";\n" "\"Install TLS Certificate\" = \"TLS Sertifikası Kur\";\n" "\"Invalid IPv4 address.\" = \"Geçersiz IPv4 adresi.\";\n" "\"Invalid IPv4 netmask.\" = \"Geçersiz IPv4 ağ maskesi.\";\n" "\"Invalid IPv6 address.\" = \"Geçersiz IPv6 adresi.\";\n" "\"Invalid IPv6 prefix length.\" = \"Geçersiz IPv6 ön ek uzunluğu.\";\n" "\"Invalid Job ID.\" = \"Geçersiz İş Numarası.\";\n" "\"Invalid certificate or private key.\" = \"Geçersiz sertifika veya özel anahtar.\";\n" "\"Invalid form data.\" = \"Geçersiz form verisi.\";\n" "\"Invalid form submission.\" = \"Geçersiz form gönderimi.\";\n" "\"Invalid job ID.\" = \"Geçersiz iş numarası.\";\n" "\"Invalid network configuration.\" = \"Geçersiz ağ yapılandırması.\";\n" "\"Iran (Islamic Republic of)\" = \"İran (İslam Cumhuriyeti)\";\n" "\"Iraq\" = \"Irak\";\n" "\"Ireland\" = \"İrlanda\";\n" "\"Isle of Man\" = \"Man Adası\";\n" "\"Israel\" = \"İsrail\";\n" "\"Italy\" = \"İtalya\";\n" "\"Jamaica\" = \"Jamaika\";\n" "\"Japan\" = \"Japonya\";\n" "\"Jersey\" = \"Jersey\";\n" "\"Job #\" = \"İş #\";\n" "\"Job canceled.\" = \"İş iptal edildi.\";\n" "\"Job held.\" = \"İş bekletildi.\";\n" "\"Job released.\" = \"İş serbest bırakıldı.\";\n" "\"Jobs\" = \"İşler\";\n" "\"Joining Wi-Fi Network\" = \"Wi-Fi Ağına Bağlanıyor\";\n" "\"Jordan\" = \"Ürdün\";\n" "\"Kazakhstan\" = \"Kazakistan\";\n" "\"Kenya\" = \"Kenya\";\n" "\"Kiribati\" = \"Kiribati\";\n" "\"Korea (Democratic People's Republic of)\" = \"Kore (Demokratik Halk Cumhuriyeti)\";\n" "\"Korea, Republic of\" = \"Kore Cumhuriyeti\";\n" "\"Kuwait\" = \"Kuveyt\";\n" "\"Kyrgyzstan\" = \"Kırgızistan\";\n" "\"Landscape\" = \"Manzara\";\n" "\"Lao People's Democratic Republic\" = \"Lao Demokratik Halk Cumhuriyeti\";\n" "\"Latvia\" = \"Letonya\";\n" "\"Lebanon\" = \"Lübnan\";\n" "\"Lesotho\" = \"Lesotho\";\n" "\"Level\" = \"Seviye\";\n" "\"Liberia\" = \"Liberya\";\n" "\"Libya\" = \"Libya\";\n" "\"Liechtenstein\" = \"Lihtenştayn\";\n" "\"Lithuania\" = \"Litvanya\";\n" "\"Location\" = \"Konum\";\n" "\"Log Level\" = \"Günlük Kaydı Seviyesi\";\n" "\"Logging\" = \"Günlük Kaydı\";\n" "\"Logs\" = \"Günlük\";\n" "\"Luxembourg\" = \"Lüksemburg\";\n" "\"Macao\" = \"Macao\";\n" "\"Madagascar\" = \"Madagaskar\";\n" "\"Malawi\" = \"Malavi\";\n" "\"Malaysia\" = \"Malezya\";\n" "\"Maldives\" = \"Maldivler\";\n" "\"Mali\" = \"Mali\";\n" "\"Malta\" = \"Malta\";\n" "\"Manual Configuration\" = \"Elle Yapılandırma\";\n" "\"Marshall Islands\" = \"Marshall Adaları\";\n" "\"Martinique\" = \"Martinik\";\n" "\"Mauritania\" = \"Moritanya\";\n" "\"Mauritius\" = \"Mauritius\";\n" "\"Mayotte\" = \"Mayotte\";\n" "\"Media\" = \"Ortam\";\n" "\"Mexico\" = \"Meksika\";\n" "\"Micronesia (Federated States of)\" = \"Mikronezya (Federal Devletleri)\";\n" "\"Missing action.\" = \"Eksik eylem.\";\n" "\"Missing job ID.\" = \"İş kimliği eksik.\";\n" "\"Missing network name.\" = \"Eksik ağ adı.\";\n" "\"Missing private key.\" = \"Eksik özel anahtar.\";\n" "\"Moldova, Republic of\" = \"Moldova Cumhuriyeti\";\n" "\"Monaco\" = \"Monako\";\n" "\"Mongolia\" = \"Moğolistan\";\n" "\"Montenegro\" = \"Karadağ\";\n" "\"Montserrat\" = \"Montserrat\";\n" "\"Morocco\" = \"Fas\";\n" "\"Mozambique\" = \"Mozambik\";\n" "\"Myanmar\" = \"Myanmar\";\n" "\"Name\" = \"Ad\";\n" "\"Namibia\" = \"Namibya\";\n" "\"Nauru\" = \"Nauru\";\n" "\"Nepal\" = \"Nepal\";\n" "\"Netherlands\" = \"Hollanda\";\n" "\"Network\" = \"Ağ\";\n" "\"Network Printer\" = \"Ağ Yazıcısı\";\n" "\"Networking\" = \"Ağ\";\n" "\"New Caledonia\" = \"Yeni Kaledonya\";\n" "\"New Zealand\" = \"Yeni Zelanda\";\n" "\"Nicaragua\" = \"Nikaragua\";\n" "\"Niger\" = \"Nijer\";\n" "\"Nigeria\" = \"Nijerya\";\n" "\"Niue\" = \"Niue\";\n" "\"No default printer set.\" = \"Öntanımlı yazıcı ayarlanmadı.\";\n" "\"No jobs in history.\" = \"Geçmişte iş yok.\";\n" "\"Norfolk Island\" = \"Norfolk Adası\";\n" "\"North Macedonia\" = \"Kuzey Makedonya\";\n" "\"Northern Mariana Islands\" = \"Kuzey Mariana Adaları\";\n" "\"Norway\" = \"Norveç\";\n" "\"Not set\" = \"Ayarlanmadı\";\n" "\"Off\" = \"Kapalı\";\n" "\"Offset\" = \"Ofset\";\n" "\"Oman\" = \"Umman\";\n" "\"Options:\" = \"Seçenekler:\";\n" "\"Organization\" = \"Organizasyon\";\n" "\"Organization Name\" = \"Organizasyon Adı\";\n" "\"Other Settings\" = \"Diğer Ayarlar\";\n" "\"Pakistan\" = \"Pakistan\";\n" "\"Palau\" = \"Palau\";\n" "\"Palestine, State of\" = \"Filistin Devleti\";\n" "\"Panama\" = \"Panama\";\n" "\"Papua New Guinea\" = \"Papua Yeni Gine\";\n" "\"Paraguay\" = \"Paraguay\";\n" "\"Password\" = \"Parola\";\n" "\"Password changed.\" = \"Parola değiştirildi.\";\n" "\"Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit.\" = \"Parola en az sekiz karakter uzunluğunda olmalı ve en az bir büyük harf, bir küçük harf ve bir rakam içermelidir.\";\n" "\"Passwords do not match.\" = \"Parolalar eşleşmiyor.\";\n" "\"Pause Printing\" = \"Yazdırmayı Duraklat\";\n" "\"Peru\" = \"Peru\";\n" "\"Philippines\" = \"Filipinler\";\n" "\"Pitcairn\" = \"Pitcairn\";\n" "\"Please enter a hostname or IP address for the printer.\" = \"Lütfen yazıcı için bir ana makine adı veya IP adresi girin.\";\n" "\"Please enter a printer name.\" = \"Lütfen bir yazıcı adı girin.\";\n" "\"Please select a device.\" = \"Lütfen bir aygıt seçin.\";\n" "\"Please select a driver.\" = \"Lütfen bir sürücü seçin.\";\n" "\"Please select a valid log level.\" = \"Lütfen geçerli bir günlük kaydı seviyesi seçin.\";\n" "\"Poland\" = \"Polonya\";\n" "\"Portrait\" = \"Portre\";\n" "\"Portugal\" = \"Portekiz\";\n" "\"Primary DNS\" = \"Birincil DNS\";\n" "\"Print Group\" = \"Yazdırma Grubu\";\n" "\"Print Test Page\" = \"Test Sayfası Yazdır\";\n" "\"Print job options:\" = \"Yazdırma işi seçenekleri:\";\n" "\"Printer identified.\" = \"Yazıcı tanımlandı.\";\n" "\"Printer is currently active.\" = \"Yazıcı şu anda etkin.\";\n" "\"Printer names must start with a letter or underscore and cannot contain special characters.\" = \"Yazıcı adları bir harf veya alt çizgi ile başlamalıdır ve özel karakterler içeremez.\";\n" "\"Printer options:\" = \"Yazıcı seçenekleri:\";\n" "\"Printer paused.\" = \"Yazıcı duraklatıldı.\";\n" "\"Printer pausing.\" = \"Yazıcı duraklatılıyor.\";\n" "\"Printer resuming.\" = \"Yazıcı devam ettiriliyor.\";\n" "\"Printers\" = \"Yazıcılar\";\n" "\"Printing Defaults\" = \"Öntanımlı Yazdırma Ayarları\";\n" "\"Puerto Rico\" = \"Porto Riko\";\n" "\"Qatar\" = \"Katar\";\n" "\"Queued %s\" = \"%s sıraya alındı\";\n" "\"Release Held New Jobs\" = \"Bekletilen Yeni İşleri Serbest Bırak\";\n" "\"Release Job\" = \"İşi Serbest Bırak\";\n" "\"Released held new jobs.\" = \"Bekletilen yeni işler serbest bırakıldı.\";\n" "\"Reprint Job\" = \"İşi Yeniden Yazdır\";\n" "\"Reprinted job.\" = \"İş yeniden yazdırıldı.\";\n" "\"Resume Printing\" = \"Yazdırmayı Devam Ettir\";\n" "\"Reverse Landscape\" = \"Ters Manzara\";\n" "\"Reverse Portrait\" = \"Ters Portre\";\n" "\"Romania\" = \"Romanya\";\n" /* Running, STATE since DATE REASONS */ "\"Running, %s since %s%s.\" = \"Çalışıyor, %s %s'den beri %s.\";\n" "\"Russian Federation\" = \"Rusya Federasyonu\";\n" "\"Rwanda\" = \"Ruanda\";\n" "\"Réunion\" = \"Réunion\";\n" "\"Saint Barthélemy\" = \"Saint Barthélemy\";\n" "\"Saint Helena, Ascension and Tristan da Cunha\" = \"Saint Helena, Ascension ve Tristan da Cunha\";\n" "\"Saint Kitts and Nevis\" = \"Saint Kitts ve Nevis\";\n" "\"Saint Lucia\" = \"Saint Lucia\";\n" "\"Saint Martin (French part)\" = \"Saint Martin (Fransız kısmı)\";\n" "\"Saint Pierre and Miquelon\" = \"Saint Pierre ve Miquelon\";\n" "\"Saint Vincent and the Grenadines\" = \"Saint Vincent ve Grenadinler\";\n" "\"Samoa\" = \"Samoa\";\n" "\"San Marino\" = \"San Marino\";\n" "\"Sao Tome and Principe\" = \"Sao Tome ve Principe\";\n" "\"Saudi Arabia\" = \"Suudi Arabistan\";\n" "\"Save Changes\" = \"Değişiklikleri Kaydet\";\n" "\"Secondary DNS\" = \"İkincil DNS\";\n" "\"Security\" = \"Güvenlik\";\n" "\"Select Driver\" = \"Sürücü Seç\";\n" "\"Senegal\" = \"Senegal\";\n" "\"Serbia\" = \"Sırbistan\";\n" "\"Server is not running.\" = \"Sunucu çalışmıyor.\";\n" "\"Set Access Password\" = \"Erişim Parolası Ayarla\";\n" "\"Set as Default\" = \"Öntanımlı Olarak Ayarla\";\n" "\"Seychelles\" = \"Seyşeller\";\n" "\"Sierra Leone\" = \"Sierra Leone\";\n" "\"Singapore\" = \"Singapur\";\n" "\"Sint Maarten (Dutch part)\" = \"Sint Maarten (Hollanda kısmı)\";\n" "\"Slovakia\" = \"Slovakya\";\n" "\"Slovenia\" = \"Slovenya\";\n" "\"Solomon Islands\" = \"Solomon Adaları\";\n" "\"Somalia\" = \"Somali\";\n" "\"South Africa\" = \"Güney Afrika\";\n" "\"South Georgia and the South Sandwich Islands\" = \"Güney Georgia ve Güney Sandwich Adaları\";\n" "\"South Sudan\" = \"Güney Sudan\";\n" "\"Spain\" = \"İspanya\";\n" "\"Sri Lanka\" = \"Sri Lanka\";\n" "\"Started %s\" = \"%s başlatıldı\";\n" "\"Status\" = \"Durum\";\n" "\"Sub-commands:\" = \"Alt komutlar:\";\n" "\"Sudan\" = \"Sudan\";\n" "\"Supplies\" = \"Malzemeler\";\n" "\"Suriname\" = \"Surinam\";\n" "\"Svalbard and Jan Mayen\" = \"Svalbard ve Jan Mayen\";\n" "\"Sweden\" = \"İsveç\";\n" "\"Switzerland\" = \"İsviçre\";\n" "\"Syrian Arab Republic\" = \"Suriye Arap Cumhuriyeti\";\n" "\"Taiwan, Province of China\" = \"Tayvan, Çin Eyaleti\";\n" "\"Tajikistan\" = \"Tacikistan\";\n" "\"Tanzania, United Republic of\" = \"Tanzanya Birleşik Cumhuriyeti\";\n" "\"Test page printed.\" = \"Test sayfası yazdırıldı.\";\n" "\"Thailand\" = \"Tayland\";\n" "\"This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA.\" = \"Bu form, güvenilir bir TLS sertifikası almak için Sertifika Yetkilisine (Certificate Authority - 'CA') gönderebileceğiniz bir sertifika imzalama isteği (certificate signing request - 'CSR') oluşturur. Özel anahtar, CA'dan aldığınız sertifika ile kullanılmak üzere ayrı olarak kaydedilir.\";\n" "\"This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.\" = \"Bu form, güvenli yazdırma için yeni bir 'kendi tarafından imzalanan' TLS sertifikası oluşturur. Kendi tarafından imzalanan sertifikalara web tarayıcıları tarafından otomatik olarak güvenilmez.\";\n" "\"This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.\" = \"Bu form, bir Sertifika Yetkilisinden ('CA') aldığınız güvenilir bir TLS sertifikasını kuracaktır. Kurulduktan sonra hemen kullanılacaktır.\";\n" "\"Timor-Leste\" = \"Timor-Leste\";\n" "\"Togo\" = \"Togo\";\n" "\"Tokelau\" = \"Tokelau\";\n" "\"Tonga\" = \"Tonga\";\n" "\"Trinidad and Tobago\" = \"Trinidad ve Tobago\";\n" "\"Tunisia\" = \"Tunus\";\n" "\"Turkey\" = \"Türkiye\";\n" "\"Turkmenistan\" = \"Türkmenistan\";\n" "\"Turks and Caicos Islands\" = \"Turks ve Caicos Adaları\";\n" "\"Tuvalu\" = \"Tuvalu\";\n" "\"Uganda\" = \"Uganda\";\n" "\"Ukraine\" = \"Ukrayna\";\n" "\"Unable to access test print file.\" = \"Test yazdırma dosyasına erişilemiyor.\";\n" "\"Unable to copy print job.\" = \"Yazdırma işi kopyalanamıyor.\";\n" "\"Unable to create certificate request.\" = \"Sertifika isteği oluşturulamıyor.\";\n" "\"Unable to create certificate.\" = \"Sertifika oluşturulamıyor.\";\n" "\"Unable to create test print job.\" = \"Test yazdırma işi oluşturulamıyor.\";\n" "\"Unable to identify printer.\" = \"Yazıcı tanımlanamıyor.\";\n" "\"Unable to lookup address.\" = \"Adres aranamıyor.\";\n" "\"Unable to use that driver.\" = \"Bu sürücü kullanılamıyor.\";\n" "\"United Arab Emirates\" = \"Birleşik Arap Emirlikleri\";\n" "\"United Kingdom\" = \"Birleşik Krallık\";\n" "\"United Kingdom of Great Britain and Northern Ireland\" = \"Büyük Britanya ve Kuzey İrlanda Birleşik Krallığı\";\n" "\"United States Minor Outlying Islands\" = \"Amerika Birleşik Devletleri Küçük Dış Adaları\";\n" "\"United States of America\" = \"Amerika Birleşik Devletleri\";\n" "\"Unknown\" = \"Bilinmeyen\";\n" "\"Unknown action.\" = \"Bilinmeyen eylem.\";\n" "\"Unknown form action.\" = \"Bilinmeyen form eylemi.\";\n" "\"Unknown form request.\" = \"Bilinmeyen form isteği.\";\n" "\"Updating Network Configuration\" = \"Ağ Yapılandırması Güncelleniyor\";\n" "\"Uruguay\" = \"Uruguay\";\n" "\"Usage: %s SUB-COMMAND [OPTIONS] [FILENAME]\\n\" = \"Kullanım: %s ALT-KOMUT [SEÇENEKLER] [DOSYA-ADI]\\n\";\n" "\"Use My Position\" = \"Konumumu Kullan\";\n" "\"Users\" = \"Kullanıcılar\";\n" "\"Uzbekistan\" = \"Özbekistan\";\n" "\"Vanuatu\" = \"Vanuatu\";\n" "\"Venezuela (Bolivarian Republic of)\" = \"Venezuela Bolivar Cumhuriyeti\";\n" "\"Version %s\" = \"Sürüm %s\";\n" "\"Viet Nam\" = \"Vietnam\";\n" "\"View Logs\" = \"Günlükleri Görüntüle\";\n" "\"Virgin Islands (British)\" = \"Virgin Adaları (İngiliz)\";\n" "\"Virgin Islands (U.S.)\" = \"Virgin Adaları (ABD)\";\n" "\"Wallis and Futuna\" = \"Wallis ve Futuna\";\n" "\"Warning\" = \"Uyarı\";\n" "\"Western Sahara\" = \"Batı Sahra\";\n" "\"Wi-Fi Configuration\" = \"Wi-Fi Yapılandırması\";\n" "\"Wi-Fi Network\" = \"Wi-Fi Ağı\";\n" "\"Width\" = \"Genişlik\";\n" "\"Wrong old password.\" = \"Yanlış eski parola.\";\n" "\"Yemen\" = \"Yemen\";\n" "\"Zambia\" = \"Zambiya\";\n" "\"Zimbabwe\" = \"Zimbabve\";\n" "\"at %02d:%02d:%02d\" = \"%02d:%02d:%02d\";\n" /* IPP attribute, keyword, and enum (integer) localizations */ "\"copies\" = \"Kopya Sayısı\";\n" "\"default printer\" = \"öntanımlı yazıcı\";\n" "\"finishings\" = \"Sonlandırıcı\";\n" "\"finishings.10\" = \"Katla\";\n" "\"finishings.100\" = \"Z katla\";\n" "\"finishings.101\" = \"Mühendislik Z katla\";\n" "\"finishings.11\" = \"Kes\";\n" "\"finishings.12\" = \"Balya\";\n" "\"finishings.13\" = \"Kitapçık yapıcısı\";\n" "\"finishings.15\" = \"Kapla\";\n" "\"finishings.16\" = \"Katmanla\";\n" "\"finishings.20\" = \"Sol üstten zımbala\";\n" "\"finishings.21\" = \"Sol alttan zımbala\";\n" "\"finishings.22\" = \"Sağ üstten zımbala\";\n" "\"finishings.23\" = \"Sağ alttan zımbala\";\n" "\"finishings.24\" = \"Kenar dikişi solda\";\n" "\"finishings.25\" = \"Kenar dikişi üstte\";\n" "\"finishings.26\" = \"Kenar dikişi sağda\";\n" "\"finishings.27\" = \"Kenar dikişi altta\";\n" "\"finishings.28\" = \"Solda 2 zımba\";\n" "\"finishings.29\" = \"Üstte 2 zımba\";\n" "\"finishings.3\" = \"Hiçbiri\";\n" "\"finishings.30\" = \"Sağda 2 zımba\";\n" "\"finishings.31\" = \"Altta 2 zımba\";\n" "\"finishings.32\" = \"Solda 3 zımba\";\n" "\"finishings.33\" = \"Üstte 3 zımba\";\n" "\"finishings.34\" = \"Sağda 3 zımba\";\n" "\"finishings.35\" = \"Altta 3 zımba\";\n" "\"finishings.4\" = \"Zımba\";\n" "\"finishings.5\" = \"Delgeç\";\n" "\"finishings.50\" = \"Sola bağla\";\n" "\"finishings.51\" = \"Üste bağla\";\n" "\"finishings.52\" = \"Sağa bağla\";\n" "\"finishings.53\" = \"Alta bağla\";\n" "\"finishings.6\" = \"Kapak\";\n" "\"finishings.60\" = \"Her sayfadan sonra kes\";\n" "\"finishings.61\" = \"Her belgeden sonra kes\";\n" "\"finishings.62\" = \"Her kümeden sonra kes\";\n" "\"finishings.63\" = \"Her işten sonra kes\";\n" "\"finishings.7\" = \"Bağla\";\n" "\"finishings.70\" = \"Sol üstten del\";\n" "\"finishings.71\" = \"Sol alttan del\";\n" "\"finishings.72\" = \"Sağ üstten del\";\n" "\"finishings.73\" = \"Sağ alttan del\";\n" "\"finishings.74\" = \"Soldan 2 delik del\";\n" "\"finishings.75\" = \"Üstten 2 delik del\";\n" "\"finishings.76\" = \"Sağdan 2 delik del\";\n" "\"finishings.77\" = \"Alttan 2 delik del\";\n" "\"finishings.78\" = \"Soldan 3 delik del\";\n" "\"finishings.79\" = \"Üstten 3 delik del\";\n" "\"finishings.8\" = \"Tel dikiş\";\n" "\"finishings.80\" = \"Sağdan 3 delik del\";\n" "\"finishings.81\" = \"Alttan 3 delik del\";\n" "\"finishings.82\" = \"Soldan 4 delik del\";\n" "\"finishings.83\" = \"Üstten 4 delik del\";\n" "\"finishings.84\" = \"Sağdan 4 delik del\";\n" "\"finishings.85\" = \"Alttan 4 delik del\";\n" "\"finishings.86\" = \"Soldan çoklu delik del\";\n" "\"finishings.87\" = \"Üstten çoklu delik del\";\n" "\"finishings.88\" = \"Sağdan çoklu delik del\";\n" "\"finishings.89\" = \"Alttan çoklu delik del\";\n" "\"finishings.9\" = \"Kenar dikişi\";\n" "\"finishings.90\" = \"Akordeon katlama\";\n" "\"finishings.91\" = \"Çift kapı katlama\";\n" "\"finishings.92\" = \"Kapı katlama\";\n" "\"finishings.93\" = \"Yarım katlama\";\n" "\"finishings.94\" = \"Yarım Z katlama\";\n" "\"finishings.95\" = \"Sol kapı katlama\";\n" "\"finishings.96\" = \"Mektup katlama\";\n" "\"finishings.97\" = \"Paralel katlama\";\n" "\"finishings.98\" = \"Poster katlama\";\n" "\"finishings.99\" = \"Sağ kapı katlama\";\n" "\"holding new jobs\" = \"yeni işler bekletiliyor\";\n" "\"job-state-reasons.aborted-by-system\" = \"Durduruluyor.\";\n" "\"job-state-reasons.compression-error\" = \"Sıkıştırma açılması hatası.\";\n" "\"job-state-reasons.document-format-error\" = \"Belge biçimi hatası.\";\n" "\"job-state-reasons.document-password-error\" = \"Belge parolası hatası.\";\n" "\"job-state-reasons.document-permission-error\" = \"Belge izin hatası.\";\n" "\"job-state-reasons.document-unprintable-error\" = \"Belge yazdırılamaz hatası.\";\n" "\"job-state-reasons.errors-detected\" = \"Hatalar algılandı.\";\n" "\"job-state-reasons.job-canceled-at-device\" = \"Yazıcıda iptal edildi.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Kullanıcı tarafından iptal edildi.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Yazdırıldı.\";\n" "\"job-state-reasons.job-completed-with-errors\" = \"Hatalarla yazdırıldı.\";\n" "\"job-state-reasons.job-completed-with-warnings\" = \"Uyarılarla yazdırıldı.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Yetersiz veri.\";\n" "\"job-state-reasons.job-fetchable\" = \"Alınabilir.\";\n" "\"job-state-reasons.job-incoming\" = \"Geliyor.\";\n" "\"job-state-reasons.job-printing\" = \"Yazdırılıyor.\";\n" "\"job-state-reasons.job-queued\" = \"Yazdırmaya hazırlanıyor.\";\n" "\"job-state-reasons.job-spooling\" = \"Biriktiriliyor.\";\n" "\"job-state-reasons.none\" = \"Bekliyor.\";\n" "\"job-state-reasons.printer-stopped\" = \"Yazıcı çevrim dışı.\";\n" "\"job-state-reasons.printer-stopped-partly\" = \"Yazıcı kısmen durduruldu.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Durduruluyor.\";\n" "\"job-state-reasons.queued-in-device\" = \"Hazır.\";\n" "\"job-state-reasons.warnings-detected\" = \"Uyarılar algılandı.\";\n" "\"job-state.3\" = \"Bekliyor\";\n" "\"job-state.4\" = \"Bekletildi\";\n" "\"job-state.5\" = \"İşleniyor\";\n" "\"job-state.6\" = \"Durduruldu\";\n" "\"job-state.7\" = \"İptal edildi\";\n" "\"job-state.8\" = \"Sonlandırıldı\";\n" "\"job-state.9\" = \"Tamamlandı\";\n" "\"joining\" = \"katılıyor\";\n" "\"media\" = \"Ortam\";\n" "\"media-col\" = \"Ortam\";\n" "\"media-size\" = \"Ortam Boyutu\";\n" "\"media-size-name\" = \"Ortam Boyutu\";\n" "\"media-source\" = \"Giriş Tepsisi\";\n" "\"media-source.alternate\" = \"Alternatif\";\n" "\"media-source.alternate-roll\" = \"Alternatif silindir\";\n" "\"media-source.auto\" = \"Otomatik\";\n" "\"media-source.bottom\" = \"Alt\";\n" "\"media-source.by-pass-tray\" = \"Çok amaçlı tepsi\";\n" "\"media-source.center\" = \"Orta\";\n" "\"media-source.disc\" = \"Disk\";\n" "\"media-source.envelope\" = \"Zarf\";\n" "\"media-source.hagaki\" = \"Hagaki\";\n" "\"media-source.large-capacity\" = \"Büyük kapasite\";\n" "\"media-source.left\" = \"Sol\";\n" "\"media-source.main\" = \"Ana\";\n" "\"media-source.main-roll\" = \"Ana silindir\";\n" "\"media-source.manual\" = \"El ile\";\n" "\"media-source.middle\" = \"Orta\";\n" "\"media-source.photo\" = \"Fotoğraf\";\n" "\"media-source.rear\" = \"Arka\";\n" "\"media-source.right\" = \"Sağ\";\n" "\"media-source.roll-1\" = \"Silindir 1\";\n" "\"media-source.roll-10\" = \"Silindir 10\";\n" "\"media-source.roll-2\" = \"Silindir 2\";\n" "\"media-source.roll-3\" = \"Silindir 3\";\n" "\"media-source.roll-4\" = \"Silindir 4\";\n" "\"media-source.roll-5\" = \"Silindir 5\";\n" "\"media-source.roll-6\" = \"Silindir 6\";\n" "\"media-source.roll-7\" = \"Silindir 7\";\n" "\"media-source.roll-8\" = \"Silindir 8\";\n" "\"media-source.roll-9\" = \"Silindir 9\";\n" "\"media-source.side\" = \"Yan\";\n" "\"media-source.top\" = \"Üst\";\n" "\"media-source.tray-1\" = \"Tepsi 1\";\n" "\"media-source.tray-10\" = \"Tepsi 10\";\n" "\"media-source.tray-11\" = \"Tepsi 11\";\n" "\"media-source.tray-12\" = \"Tepsi 12\";\n" "\"media-source.tray-13\" = \"Tepsi 13\";\n" "\"media-source.tray-14\" = \"Tepsi 14\";\n" "\"media-source.tray-15\" = \"Tepsi 15\";\n" "\"media-source.tray-16\" = \"Tepsi 16\";\n" "\"media-source.tray-17\" = \"Tepsi 17\";\n" "\"media-source.tray-18\" = \"Tepsi 18\";\n" "\"media-source.tray-19\" = \"Tepsi 19\";\n" "\"media-source.tray-2\" = \"Tepsi 2\";\n" "\"media-source.tray-20\" = \"Tepsi 20\";\n" "\"media-source.tray-3\" = \"Tepsi 3\";\n" "\"media-source.tray-4\" = \"Tepsi 4\";\n" "\"media-source.tray-5\" = \"Tepsi 5\";\n" "\"media-source.tray-6\" = \"Tepsi 6\";\n" "\"media-source.tray-7\" = \"Tepsi 7\";\n" "\"media-source.tray-8\" = \"Tepsi 8\";\n" "\"media-source.tray-9\" = \"Tepsi 9\";\n" "\"media-tracking\" = \"Ortam İzleme\";\n" "\"media-tracking.continuous\" = \"Sürekli\";\n" "\"media-tracking.gap\" = \"Boşluk\";\n" "\"media-tracking.mark\" = \"İşaret\";\n" "\"media-tracking.web\" = \"Web\";\n" "\"media-type\" = \"Ortam Türü\";\n" "\"media-type.aluminum\" = \"Alüminyum\";\n" "\"media-type.auto\" = \"Otomatik\";\n" "\"media-type.back-print-film\" = \"Arka baskı filmi\";\n" "\"media-type.cardboard\" = \"Karton\";\n" "\"media-type.cardstock\" = \"Kart\";\n" "\"media-type.cd\" = \"CD\";\n" "\"media-type.continuous\" = \"Sürekli\";\n" "\"media-type.continuous-long\" = \"Sürekli uzun\";\n" "\"media-type.continuous-short\" = \"Sürekli kısa\";\n" "\"media-type.corrugated-board\" = \"Oluklu karton\";\n" "\"media-type.disc\" = \"Optik disk\";\n" "\"media-type.disc-glossy\" = \"Parlak optik disk\";\n" "\"media-type.disc-high-gloss\" = \"Çok parlak optik disk\";\n" "\"media-type.disc-matte\" = \"Mat optik disk\";\n" "\"media-type.disc-satin\" = \"Saten optik disk\";\n" "\"media-type.disc-semi-gloss\" = \"Yarı parlak optik disk\";\n" "\"media-type.double-wall\" = \"Çift duvar\";\n" "\"media-type.dry-film\" = \"Kuru film\";\n" "\"media-type.dvd\" = \"DVD\";\n" "\"media-type.embossing-foil\" = \"Kabartma folyo\";\n" "\"media-type.end-board\" = \"Bitiş tahtası\";\n" "\"media-type.envelope\" = \"Zarf\";\n" "\"media-type.envelope-archival\" = \"Arşiv zarfı\";\n" "\"media-type.envelope-bond\" = \"Bond zarfı\";\n" "\"media-type.envelope-coated\" = \"Kaplamalı zarf\";\n" "\"media-type.envelope-cotton\" = \"Pamuk zarf\";\n" "\"media-type.envelope-fine\" = \"İnce zarf\";\n" "\"media-type.envelope-heavyweight\" = \"Ağır zarf\";\n" "\"media-type.envelope-inkjet\" = \"Mürekkep püskürtmeli zarf\";\n" "\"media-type.envelope-lightweight\" = \"Hafif zarf\";\n" "\"media-type.envelope-plain\" = \"Düz zarf\";\n" "\"media-type.envelope-preprinted\" = \"Önceden baskılı zarf\";\n" "\"media-type.envelope-window\" = \"Pencereli zarf\";\n" "\"media-type.fabric\" = \"Kumaş\";\n" "\"media-type.fabric-archival\" = \"Arşiv kumaşı\";\n" "\"media-type.fabric-glossy\" = \"Parlak kumaş\";\n" "\"media-type.fabric-high-gloss\" = \"Çok parlak kumaş\";\n" "\"media-type.fabric-matte\" = \"Mat kumaş\";\n" "\"media-type.fabric-semi-gloss\" = \"Yarı parlak kumaş\";\n" "\"media-type.fabric-waterproof\" = \"Su geçirmez kumaş\";\n" "\"media-type.film\" = \"Film\";\n" "\"media-type.flexo-base\" = \"Flekso taban\";\n" "\"media-type.flexo-photo-polymer\" = \"Flekso fotoğraf polimeri\";\n" "\"media-type.flute\" = \"Oluk\";\n" "\"media-type.foil\" = \"Folyo\";\n" "\"media-type.full-cut-tabs\" = \"Tam kesim sekmeler\";\n" "\"media-type.glass\" = \"Cam\";\n" "\"media-type.glass-colored\" = \"Cam renkli\";\n" "\"media-type.glass-opaque\" = \"Cam opak\";\n" "\"media-type.glass-surfaced\" = \"Cam yüzeyli\";\n" "\"media-type.glass-textured\" = \"Cam dokulu\";\n" "\"media-type.gravure-cylinder\" = \"Gravür silindiri\";\n" "\"media-type.image-setter-paper\" = \"Görüntü ayarlayıcı kağıt\";\n" "\"media-type.imaging-cylinder\" = \"Görüntüleme silindiri\";\n" "\"media-type.labels\" = \"Etiketler\";\n" "\"media-type.labels-colored\" = \"Renkli etiketler\";\n" "\"media-type.labels-glossy\" = \"Parlak etiketler\";\n" "\"media-type.labels-high-gloss\" = \"Çok parlak etiketler\";\n" "\"media-type.labels-inkjet\" = \"Mürekkep püskürtmeli etiketler\";\n" "\"media-type.labels-matte\" = \"Mat etiketler\";\n" "\"media-type.labels-permanent\" = \"Kalıcı etiketler\";\n" "\"media-type.labels-satin\" = \"Saten etiketler\";\n" "\"media-type.labels-security\" = \"Güvenlik etiketleri\";\n" "\"media-type.labels-semi-gloss\" = \"Yarı parlak etiketler\";\n" "\"media-type.laminating-foil\" = \"Katmanlama folyosu\";\n" "\"media-type.letterhead\" = \"Antetli kağıt\";\n" "\"media-type.metal\" = \"Metal\";\n" "\"media-type.metal-glossy\" = \"Metal parlak\";\n" "\"media-type.metal-high-gloss\" = \"Metal çok parlak\";\n" "\"media-type.metal-matte\" = \"Metal mat\";\n" "\"media-type.metal-satin\" = \"Metal saten\";\n" "\"media-type.metal-semi-gloss\" = \"Metal yarı parlak\";\n" "\"media-type.mounting-tape\" = \"Montaj bandı\";\n" "\"media-type.multi-layer\" = \"Çok katmanlı\";\n" "\"media-type.multi-part-form\" = \"Çok parçalı form\";\n" "\"media-type.other\" = \"Diğer\";\n" "\"media-type.paper\" = \"Kağıt\";\n" "\"media-type.photographic\" = \"Fotoğraf kağıdı\";\n" "\"media-type.photographic-archival\" = \"Fotoğraf arşivi\";\n" "\"media-type.photographic-film\" = \"Fotoğraf filmi\";\n" "\"media-type.photographic-glossy\" = \"Parlak fotoğraf kağıdı\";\n" "\"media-type.photographic-high-gloss\" = \"Çok parlak fotoğraf kağıdı\";\n" "\"media-type.photographic-matte\" = \"Mat fotoğraf kağıdı\";\n" "\"media-type.photographic-satin\" = \"Saten fotoğraf kağıdı\";\n" "\"media-type.photographic-semi-gloss\" = \"Yarı parlak fotoğraf kağıdı\";\n" "\"media-type.plastic\" = \"Plastik\";\n" "\"media-type.plastic-archival\" = \"Plastik arşiv\";\n" "\"media-type.plastic-colored\" = \"Plastik renkli\";\n" "\"media-type.plastic-glossy\" = \"Plastik parlak\";\n" "\"media-type.plastic-high-gloss\" = \"Plastik çok parlak\";\n" "\"media-type.plastic-matte\" = \"Plastik mat\";\n" "\"media-type.plastic-satin\" = \"Plastik saten\";\n" "\"media-type.plastic-semi-gloss\" = \"Plastik yarı parlak\";\n" "\"media-type.plate\" = \"Levha\";\n" "\"media-type.polyester\" = \"Polyester\";\n" "\"media-type.pre-cut-tabs\" = \"Önceden kesilmiş sekmeler\";\n" "\"media-type.roll\" = \"Rulo\";\n" "\"media-type.screen\" = \"Ekran\";\n" "\"media-type.screen-paged\" = \"Ekran sayfalı\";\n" "\"media-type.self-adhesive\" = \"Kendinden yapışkanlı\";\n" "\"media-type.self-adhesive-film\" = \"Kendinden yapışkanlı film\";\n" "\"media-type.shrink-foil\" = \"Daralan folyo\";\n" "\"media-type.single-face\" = \"Tek yüz\";\n" "\"media-type.single-wall\" = \"Tek duvar\";\n" "\"media-type.sleeve\" = \"Kol\";\n" "\"media-type.stationery\" = \"Kırtasiye\";\n" "\"media-type.stationery-archival\" = \"Kırtasiye arşiv\";\n" "\"media-type.stationery-coated\" = \"Kaplamalı kağıt\";\n" "\"media-type.stationery-cotton\" = \"Kırtasiye pamuk\";\n" "\"media-type.stationery-fine\" = \"Parşömen kağıt\";\n" "\"media-type.stationery-heavyweight\" = \"Ağır kağıt\";\n" "\"media-type.stationery-heavyweight-coated\" = \"Kırtasiye ağır kaplamalı\";\n" "\"media-type.stationery-inkjet\" = \"Kırtasiye mürekkep püskürtmeli kağıt\";\n" "\"media-type.stationery-letterhead\" = \"Antetli kağıt\";\n" "\"media-type.stationery-lightweight\" = \"Hafif kağıt\";\n" "\"media-type.stationery-preprinted\" = \"Önceden basılmış kağıt\";\n" "\"media-type.stationery-prepunched\" = \"Delikli kağıt\";\n" "\"media-type.tab-stock\" = \"Sekme stoğu\";\n" "\"media-type.tractor\" = \"Traktör\";\n" "\"media-type.transfer\" = \"Aktarım\";\n" "\"media-type.transparency\" = \"Şeffaflık\";\n" "\"media-type.triple-wall\" = \"Üçlü duvar\";\n" "\"media-type.wet-film\" = \"Islak film\";\n" "\"media.choice_iso_a4_210x297mm_na_letter_8.5x11in\" = \"A4 veya ABD Mektup\";\n" "\"media.iso_2a0_1189x1682mm\" = \"2a0\";\n" "\"media.iso_a0_841x1189mm\" = \"A0\";\n" "\"media.iso_a0x3_1189x2523mm\" = \"A0x3\";\n" "\"media.iso_a10_26x37mm\" = \"A10\";\n" "\"media.iso_a1_594x841mm\" = \"A1\";\n" "\"media.iso_a1x3_841x1783mm\" = \"A1x3\";\n" "\"media.iso_a1x4_841x2378mm\" = \"A1x4\";\n" "\"media.iso_a2_420x594mm\" = \"A2\";\n" "\"media.iso_a2x3_594x1261mm\" = \"A2x3\";\n" "\"media.iso_a2x4_594x1682mm\" = \"A2x4\";\n" "\"media.iso_a2x5_594x2102mm\" = \"A2x5\";\n" "\"media.iso_a3-extra_322x445mm\" = \"A3 (ek)\";\n" "\"media.iso_a3_297x420mm\" = \"A3\";\n" "\"media.iso_a3x3_420x891mm\" = \"A3x3\";\n" "\"media.iso_a3x4_420x1189mm\" = \"A3x4\";\n" "\"media.iso_a3x5_420x1486mm\" = \"A3x5\";\n" "\"media.iso_a3x6_420x1783mm\" = \"A3x6\";\n" "\"media.iso_a3x7_420x2080mm\" = \"A3x7\";\n" "\"media.iso_a4-extra_235.5x322.3mm\" = \"A4 (ek)\";\n" "\"media.iso_a4-tab_225x297mm\" = \"A4 (sekme)\";\n" "\"media.iso_a4_210x297mm\" = \"A4\";\n" "\"media.iso_a4x3_297x630mm\" = \"A4x3\";\n" "\"media.iso_a4x4_297x841mm\" = \"A4x4\";\n" "\"media.iso_a4x5_297x1051mm\" = \"A4x5\";\n" "\"media.iso_a4x6_297x1261mm\" = \"A4x6\";\n" "\"media.iso_a4x7_297x1471mm\" = \"A4x7\";\n" "\"media.iso_a4x8_297x1682mm\" = \"A4x8\";\n" "\"media.iso_a4x9_297x1892mm\" = \"A4x9\";\n" "\"media.iso_a5-extra_174x235mm\" = \"A5 (ek)\";\n" "\"media.iso_a5_148x210mm\" = \"A5\";\n" "\"media.iso_a6_105x148mm\" = \"A6\";\n" "\"media.iso_a7_74x105mm\" = \"A7\";\n" "\"media.iso_a8_52x74mm\" = \"A8\";\n" "\"media.iso_a9_37x52mm\" = \"A9\";\n" "\"media.iso_b0_1000x1414mm\" = \"B0\";\n" "\"media.iso_b10_31x44mm\" = \"B10\";\n" "\"media.iso_b1_707x1000mm\" = \"B1\";\n" "\"media.iso_b2_500x707mm\" = \"B2\";\n" "\"media.iso_b3_353x500mm\" = \"B3\";\n" "\"media.iso_b4_250x353mm\" = \"B4\";\n" "\"media.iso_b5-extra_201x276mm\" = \"B5 (ek)\";\n" "\"media.iso_b5_176x250mm\" = \"B5 Zarf\";\n" "\"media.iso_b6_125x176mm\" = \"B6\";\n" "\"media.iso_b6c4_125x324mm\" = \"B6/C4Zarf\";\n" "\"media.iso_b7_88x125mm\" = \"B7\";\n" "\"media.iso_b8_62x88mm\" = \"B8\";\n" "\"media.iso_b9_44x62mm\" = \"B9\";\n" "\"media.iso_c0_917x1297mm\" = \"C0 Zarf\";\n" "\"media.iso_c10_28x40mm\" = \"C10 Zarf\";\n" "\"media.iso_c1_648x917mm\" = \"C1 Zarf\";\n" "\"media.iso_c2_458x648mm\" = \"C2 Zarf\";\n" "\"media.iso_c3_324x458mm\" = \"C3 Zarf\";\n" "\"media.iso_c4_229x324mm\" = \"C4 Zarf\";\n" "\"media.iso_c5_162x229mm\" = \"C5 Zarf\";\n" "\"media.iso_c6_114x162mm\" = \"C6 Zarf\";\n" "\"media.iso_c6c5_114x229mm\" = \"C6/C5 Zarf\";\n" "\"media.iso_c7_81x114mm\" = \"C7 Zarf\";\n" "\"media.iso_c7c6_81x162mm\" = \"C7/C6 Zarf\";\n" "\"media.iso_c8_57x81mm\" = \"C8 Zarf\";\n" "\"media.iso_c9_40x57mm\" = \"C9 Zarf\";\n" "\"media.iso_dl_110x220mm\" = \"DL Zarf\";\n" "\"media.iso_ra0_860x1220mm\" = \"ISO RA0\";\n" "\"media.iso_ra1_610x860mm\" = \"ISO RA1\";\n" "\"media.iso_ra2_430x610mm\" = \"ISO RA2\";\n" "\"media.iso_ra3_305x430mm\" = \"ISO RA3\";\n" "\"media.iso_ra4_215x305mm\" = \"ISO RA4\";\n" "\"media.iso_sra0_900x1280mm\" = \"ISO SRA0\";\n" "\"media.iso_sra1_640x900mm\" = \"ISO SRA1\";\n" "\"media.iso_sra2_450x640mm\" = \"ISO SRA2\";\n" "\"media.iso_sra3_320x450mm\" = \"ISO SRA3\";\n" "\"media.iso_sra4_225x320mm\" = \"ISO SRA4\";\n" "\"media.jis_b0_1030x1456mm\" = \"JIS B0\";\n" "\"media.jis_b10_32x45mm\" = \"JIS B10\";\n" "\"media.jis_b1_728x1030mm\" = \"JIS B1\";\n" "\"media.jis_b2_515x728mm\" = \"JIS B2\";\n" "\"media.jis_b3_364x515mm\" = \"JIS B3\";\n" "\"media.jis_b4_257x364mm\" = \"JIS B4\";\n" "\"media.jis_b5_182x257mm\" = \"JIS B5\";\n" "\"media.jis_b6_128x182mm\" = \"JIS B6\";\n" "\"media.jis_b7_91x128mm\" = \"JIS B7\";\n" "\"media.jis_b8_64x91mm\" = \"JIS B8\";\n" "\"media.jis_b9_45x64mm\" = \"JIS B9\";\n" "\"media.jis_exec_216x330mm\" = \"JIS Yönetici\";\n" "\"media.jpn_chou2_111.1x146mm\" = \"Zarf Chou 2\";\n" "\"media.jpn_chou3_120x235mm\" = \"Zarf Chou 3\";\n" "\"media.jpn_chou40_90x225mm\" = \"Zarf Chou 40\";\n" "\"media.jpn_chou4_90x205mm\" = \"Zarf Chou 4\";\n" "\"media.jpn_hagaki_100x148mm\" = \"Hagaki\";\n" "\"media.jpn_kahu_240x322.1mm\" = \"Zarf Kahu\";\n" "\"media.jpn_kaku2_240x332mm\" = \"Zarf Kahu 2\";\n" "\"media.jpn_oufuku_148x200mm\" = \"Oufuku Cevap Kartpostalı\";\n" "\"media.jpn_you4_105x235mm\" = \"Zarf Sen 4\";\n" "\"media.na_a2_4.375x5.75in\" = \"Zarf A2\";\n" "\"media.na_c5_6.5x9.5in\" = \"Zarf C5\";\n" "\"media.na_executive_7.25x10.5in\" = \"Yönetici\";\n" "\"media.na_fanfold-eur_8.5x12in\" = \"Avrupa Yelpaze\";\n" "\"media.na_fanfold-us_11x14.875in\" = \"ABD Yelpaze\";\n" "\"media.na_foolscap_8.5x13in\" = \"Büyük Dosya Kağıdı\";\n" "\"media.na_invoice_5.5x8.5in\" = \"Beyanat\";\n" "\"media.na_legal-extra_9.5x15in\" = \"ABD Yasal (Ek)\";\n" "\"media.na_legal_8.5x14in\" = \"ABD Yasal\";\n" "\"media.na_letter-extra_9.5x12in\" = \"ABD Mektup (Ek)\";\n" "\"media.na_letter-plus_8.5x12.69in\" = \"ABD Mektup (Artı)\";\n" "\"media.na_letter_8.5x11in\" = \"ABD Mektup\";\n" "\"media.na_monarch_3.875x7.5in\" = \"Kraliyet Zarfı\";\n" "\"media.na_number-10_4.125x9.5in\" = \"Zarf #10\";\n" "\"media.na_number-11_4.5x10.375in\" = \"Zarf #11\";\n" "\"media.na_number-12_4.75x11in\" = \"Zarf #12\";\n" "\"media.na_number-14_5x11.5in\" = \"Zarf #14\";\n" "\"media.na_number-9_3.875x8.875in\" = \"Zarf #9\";\n" "\"media.na_personal_3.625x6.5in\" = \"Kişisel Zarf\";\n" "\"media.na_quarto_8.5x10.83in\" = \"Çeyrek\";\n" "\"media.om_folio-sp_215x315mm\" = \"Folyo\";\n" "\"media.om_folio_210x330mm\" = \"Folyo (Özel)\";\n" "\"media.om_invite_220x220mm\" = \"Davetiye Zarfı\";\n" "\"media.om_italian_110x230mm\" = \"İtalyan Zarfı\";\n" "\"media.om_juuro-ku-kai_198x275mm\" = \"198 x 275mm\";\n" "\"media.om_large-photo_200x300\" = \"200 x 300\";\n" "\"media.om_medium-photo_130x180mm\" = \"130 x 180mm\";\n" "\"media.om_pa-kai_267x389mm\" = \"267 x 389mm\";\n" "\"media.om_postfix_114x229mm\" = \"Postfix Zarfı\";\n" "\"media.prc_10_324x458mm\" = \"Çin Zarfı #10\";\n" "\"media.prc_16k_146x215mm\" = \"Çin 16k\";\n" "\"media.prc_1_102x165mm\" = \"Çin Zarfı #1\";\n" "\"media.prc_2_102x176mm\" = \"Çin Zarfı #2\";\n" "\"media.prc_32k_97x151mm\" = \"Çin 32k\";\n" "\"media.prc_3_125x176mm\" = \"Çin Zarfı #3\";\n" "\"media.prc_4_110x208mm\" = \"Çin Zarfı #4\";\n" "\"media.prc_5_110x220mm\" = \"Çin Zarfı #5\";\n" "\"media.prc_6_120x320mm\" = \"Çin Zarfı #6\";\n" "\"media.prc_7_160x230mm\" = \"Çin Zarfı #7\";\n" "\"media.prc_8_120x309mm\" = \"Çin Zarfı #8\";\n" "\"media.roc_16k_7.75x10.75in\" = \"ROC 16k\";\n" "\"media.roc_8k_10.75x15.5in\" = \"ROC 8k\";\n" "\"not configured\" = \"yapılandırılmadı\";\n" "\"not visible\" = \"görünür değil\";\n" "\"off\" = \"kapalı\";\n" "\"on\" = \"açık\";\n" "\"orientation-requested\" = \"Yön\";\n" "\"orientation-requested.3\" = \"Portre\";\n" "\"orientation-requested.4\" = \"Manzara\";\n" "\"orientation-requested.5\" = \"Ters manzara\";\n" "\"orientation-requested.6\" = \"Ters portre\";\n" "\"orientation-requested.7\" = \"Hiçbiri\";\n" "\"output-bin\" = \"Çıkış Tepsisi\";\n" "\"output-bin.auto\" = \"Otomatik\";\n" "\"output-bin.bottom\" = \"Alt\";\n" "\"output-bin.center\" = \"Orta\";\n" "\"output-bin.face-down\" = \"Yüzü aşağı dönük\";\n" "\"output-bin.face-up\" = \"Yüzü yukarı dönük\";\n" "\"output-bin.large-capacity\" = \"Büyük kapasite\";\n" "\"output-bin.left\" = \"Sol\";\n" "\"output-bin.mailbox-1\" = \"Posta kutusu 1\";\n" "\"output-bin.mailbox-10\" = \"Posta kutusu 10\";\n" "\"output-bin.mailbox-2\" = \"Posta kutusu 2\";\n" "\"output-bin.mailbox-3\" = \"Posta kutusu 3\";\n" "\"output-bin.mailbox-4\" = \"Posta kutusu 4\";\n" "\"output-bin.mailbox-5\" = \"Posta kutusu 5\";\n" "\"output-bin.mailbox-6\" = \"Posta kutusu 6\";\n" "\"output-bin.mailbox-7\" = \"Posta kutusu 7\";\n" "\"output-bin.mailbox-8\" = \"Posta kutusu 8\";\n" "\"output-bin.mailbox-9\" = \"Posta kutusu 9\";\n" "\"output-bin.middle\" = \"Orta\";\n" "\"output-bin.my-mailbox\" = \"Posta kutum\";\n" "\"output-bin.rear\" = \"Arka\";\n" "\"output-bin.right\" = \"Sağ\";\n" "\"output-bin.side\" = \"Yan\";\n" "\"output-bin.stacker-1\" = \"Yığıcı 1\";\n" "\"output-bin.stacker-10\" = \"Yığıcı 10\";\n" "\"output-bin.stacker-2\" = \"Yığıcı 2\";\n" "\"output-bin.stacker-3\" = \"Yığıcı 3\";\n" "\"output-bin.stacker-4\" = \"Yığıcı 4\";\n" "\"output-bin.stacker-5\" = \"Yığıcı 5\";\n" "\"output-bin.stacker-6\" = \"Yığıcı 6\";\n" "\"output-bin.stacker-7\" = \"Yığıcı 7\";\n" "\"output-bin.stacker-8\" = \"Yığıcı 8\";\n" "\"output-bin.stacker-9\" = \"Yığıcı 9\";\n" "\"output-bin.top\" = \"Üst\";\n" "\"output-bin.tray-1\" = \"Tepsi 1\";\n" "\"output-bin.tray-10\" = \"Tepsi 10\";\n" "\"output-bin.tray-2\" = \"Tepsi 2\";\n" "\"output-bin.tray-3\" = \"Tepsi 3\";\n" "\"output-bin.tray-4\" = \"Tepsi 4\";\n" "\"output-bin.tray-5\" = \"Tepsi 5\";\n" "\"output-bin.tray-6\" = \"Tepsi 6\";\n" "\"output-bin.tray-7\" = \"Tepsi 7\";\n" "\"output-bin.tray-8\" = \"Tepsi 8\";\n" "\"output-bin.tray-9\" = \"Tepsi 9\";\n" "\"print-color-mode\" = \"Yazdırma Modu\";\n" "\"print-color-mode.auto\" = \"Otomatik\";\n" "\"print-color-mode.auto-monochrome\" = \"Otomatik tek renkli\";\n" "\"print-color-mode.bi-level\" = \"Metin\";\n" "\"print-color-mode.color\" = \"Renk\";\n" "\"print-color-mode.highlight\" = \"Vurgula\";\n" "\"print-color-mode.monochrome\" = \"Tek renkli\";\n" "\"print-color-mode.process-bi-level\" = \"Metin işle\";\n" "\"print-color-mode.process-monochrome\" = \"Tek renkli işle\";\n" "\"print-content-optimize\" = \"İyileştir\";\n" "\"print-content-optimize.auto\" = \"Otomatik\";\n" "\"print-content-optimize.graphic\" = \"Grafik\";\n" "\"print-content-optimize.photo\" = \"Fotoğraf\";\n" "\"print-content-optimize.text\" = \"Metin\";\n" "\"print-content-optimize.text-and-graphic\" = \"Metin ve grafikler\";\n" "\"print-darkness\" = \"Yazdırma Koyuluğu\";\n" "\"print-quality\" = \"Yazdırma Kalitesi\";\n" "\"print-quality.3\" = \"Taslak\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"En iyi\";\n" "\"print-scaling\" = \"Ölçekleme\";\n" "\"print-scaling.auto\" = \"Otomatik\";\n" "\"print-scaling.auto-fit\" = \"Otomatik sığdır\";\n" "\"print-scaling.fill\" = \"Doldur\";\n" "\"print-scaling.fit\" = \"Sığdır\";\n" "\"print-scaling.none\" = \"Hiçbiri\";\n" "\"print-speed\" = \"Yazdırma Hızı\";\n" "\"printer-resolution\" = \"Çözünürlük\";\n" "\"printer-state-reasons.cover-open\" = \"Kapak açık.\";\n" "\"printer-state-reasons.door-open\" = \"Kapı açık.\";\n" "\"printer-state-reasons.identify-printer-requested\" = \"Yazıcı tanımla.\";\n" "\"printer-state-reasons.input-tray-missing\" = \"Kağıt tepsisi eksik.\";\n" "\"printer-state-reasons.marker-supply-empty\" = \"Mürekkep bitti.\";\n" "\"printer-state-reasons.marker-supply-low\" = \"Mürekkep az kaldı.\";\n" "\"printer-state-reasons.marker-waste-almost-full\" = \"Atık kutusu neredeyse dolu.\";\n" "\"printer-state-reasons.marker-waste-full\" = \"Atık kutusu dolu.\";\n" "\"printer-state-reasons.media-empty\" = \"Kağıt bitti.\";\n" "\"printer-state-reasons.media-jam\" = \"Kağıt sıkıştı.\";\n" "\"printer-state-reasons.media-low\" = \"Kağıdı yakında değiştir.\";\n" "\"printer-state-reasons.media-needed\" = \"Kağıt yükle.\";\n" "\"printer-state-reasons.none\" = \"Hazır.\";\n" "\"printer-state-reasons.offline\" = \"Çevrim dışı.\";\n" "\"printer-state-reasons.other\" = \"Yazıcıya bakın.\";\n" "\"printer-state-reasons.spool-area-full\" = \"Yazıcı meşgul.\";\n" "\"printer-state-reasons.toner-empty\" = \"Toner bitti.\";\n" "\"printer-state-reasons.toner-low\" = \"Toner az kaldı.\";\n" "\"printer-state.3\" = \"Boşta\";\n" "\"printer-state.4\" = \"İşleniyor\";\n" "\"printer-state.5\" = \"Durduruldu\";\n" "\"sides\" = \"2 Taraflı Yazdırma\";\n" "\"sides.one-sided\" = \"Kapalı\";\n" "\"sides.two-sided-long-edge\" = \"Açık (portre)\";\n" "\"sides.two-sided-short-edge\" = \"Açık (manzara)\";\n" "\"unable to join\" = \"katılamıyor\";\n" "\"yesterday at %02d:%02d:%02d\" = \"dün, %02d:%02d:%02d\";\n" "\"Åland Islands\" = \"Åland Adaları\";\n"; pappl-1.4.9/pappl/strings/zh-Hans.strings000066400000000000000000000000001476704353100203710ustar00rootroot00000000000000pappl-1.4.9/pappl/strings/zh-Hant.strings000066400000000000000000000000001476704353100203720ustar00rootroot00000000000000pappl-1.4.9/pappl/style.css000066400000000000000000000316701476704353100156500ustar00rootroot00000000000000/* Base styles */ @import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Source+Code+Pro&display=swap'); body { background: white; color: black; font-family: 'Open Sans', sans-serif; font-size: 16px; margin: 0; } code, kbd, pre, tt, input[type=email], input[type=number], input[type=password], input[type=tel], input[type=text], textarea { font-family: 'Source Code Pro', monospace; } pre { white-space: pre-wrap; } /* Header */ .header { background: black; color: white; width: 100%; } .header2 { background: #333; color: white; width: 100%; } /* Navigation */ div.nav { color: #ccc; vertical-align: middle; } .header div.nav { font-size: 24px; line-height: 40px; } .header2 div.nav { font-size: 20px; line-height: 35px; } .header a.btn, .header a.btn:visited, .header2 a.btn, .header2 a.btn:visited { color: #ccc; text-decoration: none; white-space: nowrap; } .header a.btn:hover, .header2 a.btn:hover { color: #eee; } .header a.btn:active, .header2 a.btn:active { color: #fff; } .header span.active, .header2 span.active { color: #fff; white-space: nowrap; } .header a.btn, .header span.active, .header span.spacer { padding: 0 30px 0 0; } .header2 a.btn, .header2 span.active { padding: 0 20px 0 0; } div.nav img { height: 24px; margin-right: 10px; vertical-align: middle; } span.spacer { color: #ccc; } span.spacer:after { content: "⋮"; } /* Interior Content */ .content { margin: 20px 0 44px; } form { display: inline-block; } div.btn { display: inline-block; line-height: 32px; } .content a.btn, .content a.btn:visited, button, input[type=submit], select { border: none; border-radius: 5px; cursor: pointer; font-family: inherit; font-size: 14px; font-weight: normal; padding: 4px 8px; text-decoration: none; white-space: nowrap; -moz-appearance: none; -webkit-appearance: none; } .content a.btn, .content a.btn:visited, button, input[type=submit] { background: #333; color: #ccc; } .content a.btn:hover, button:hover, input[type=submit]:hover { background: #333; color: #eee; } .content a.btn:active, button:active, input[type=submit]:active { background: #444; color: #fff; } input[type=email], input[type=password], input[type=tel], input[type=text] { padding: 4px 8px; } input[type=number] { appearance: textfield; padding: 4px 0 4px 8px; } input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } input[type=email]:disabled, input[type=number]:disabled, input[type=password]:disabled, input[type=tel]:disabled, input[type=text]:disabled { border: none; color: black; font-size: 16px; padding: 0; } select { background: #ccc url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23000000' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; color: black; padding: 4px 32px 4px 8px; } select:hover { background: #ddd url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23000000' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; } textarea { width: 100%; } label.image input[type=radio] { position: absolute; opacity: 0; width: 0; height: 0; } label.image input[type=radio] + img { border-radius: 5px; cursor: pointer; padding: 2px; } label.image input[type=radio]:checked + img { background: rgba(127,127,127,.5); } div.switch { display: inline-flex; } div.switch input { border: 0; clip: rect(0,0,0,0); height: 1px; overflow: hidden; position: absolute !important; width: 1px; } div.switch label { background-color: #ddd; border: 1px solid rgba(0,0,0,0.2); color: black; font-family: monospace; font-size: 11px; line-height: 1; margin-right: -1px; padding: 6px 8px; text-align: center; transition: all 0.2s ease-in-out; } div.switch label:first-of-type { border-radius: 5px 0 0 5px; } div.switch label:last-of-type { border-radius: 0 5px 5px 0; } div.switch input:checked + label { background-color: #333; color: #ddd; } label.switch { position: relative; display: inline-block; width: 30px; height: 17px; margin-bottom: 5px; margin-left: 2px; vertical-align: middle; } label.switch input { opacity: 0; width: 0; height: 0; } img.password-show, img.password-hide { cursor: pointer; margin-left: -25px; padding-bottom: 5px; vertical-align: bottom; } img.password-hide { content: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZXllLXNsYXNoIiB2aWV3Qm94PSIwIDAgMTYgMTYiPg0KICA8cGF0aCBkPSJNMTMuMzU5IDExLjIzOEMxNS4wNiA5LjcyIDE2IDggMTYgOHMtMy01LjUtOC01LjVhNy4wMjggNy4wMjggMCAwIDAtMi43OS41ODhsLjc3Ljc3MUE1Ljk0NCA1Ljk0NCAwIDAgMSA4IDMuNWMyLjEyIDAgMy44NzkgMS4xNjggNS4xNjggMi40NTdBMTMuMTM0IDEzLjEzNCAwIDAgMSAxNC44MjggOGMtLjA1OC4wODctLjEyMi4xODMtLjE5NS4yODgtLjMzNS40OC0uODMgMS4xMi0xLjQ2NSAxLjc1NS0uMTY1LjE2NS0uMzM3LjMyOC0uNTE3LjQ4NmwuNzA4LjcwOXoiLz4NCiAgPHBhdGggZD0iTTExLjI5NyA5LjE3NmEzLjUgMy41IDAgMCAwLTQuNDc0LTQuNDc0bC44MjMuODIzYTIuNSAyLjUgMCAwIDEgMi44MjkgMi44MjlsLjgyMi44MjJ6bS0yLjk0MyAxLjI5OS44MjIuODIyYTMuNSAzLjUgMCAwIDEtNC40NzQtNC40NzRsLjgyMy44MjNhMi41IDIuNSAwIDAgMCAyLjgyOSAyLjgyOXoiLz4NCiAgPHBhdGggZD0iTTMuMzUgNS40N2MtLjE4LjE2LS4zNTMuMzIyLS41MTguNDg3QTEzLjEzNCAxMy4xMzQgMCAwIDAgMS4xNzIgOGwuMTk1LjI4OGMuMzM1LjQ4LjgzIDEuMTIgMS40NjUgMS43NTVDNC4xMjEgMTEuMzMyIDUuODgxIDEyLjUgOCAxMi41Yy43MTYgMCAxLjM5LS4xMzMgMi4wMi0uMzZsLjc3Ljc3MkE3LjAyOSA3LjAyOSAwIDAgMSA4IDEzLjVDMyAxMy41IDAgOCAwIDhzLjkzOS0xLjcyMSAyLjY0MS0zLjIzOGwuNzA4LjcwOXptMTAuMjk2IDguODg0LTEyLTEyIC43MDgtLjcwOCAxMiAxMi0uNzA4LjcwOHoiLz4NCjwvc3ZnPg==); } img.password-show { content: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZXllIiB2aWV3Qm94PSIwIDAgMTYgMTYiPg0KICA8cGF0aCBkPSJNMTYgOHMtMy01LjUtOC01LjVTMCA4IDAgOHMzIDUuNSA4IDUuNVMxNiA4IDE2IDh6TTEuMTczIDhhMTMuMTMzIDEzLjEzMyAwIDAgMSAxLjY2LTIuMDQzQzQuMTIgNC42NjggNS44OCAzLjUgOCAzLjVjMi4xMiAwIDMuODc5IDEuMTY4IDUuMTY4IDIuNDU3QTEzLjEzMyAxMy4xMzMgMCAwIDEgMTQuODI4IDhjLS4wNTguMDg3LS4xMjIuMTgzLS4xOTUuMjg4LS4zMzUuNDgtLjgzIDEuMTItMS40NjUgMS43NTVDMTEuODc5IDExLjMzMiAxMC4xMTkgMTIuNSA4IDEyLjVjLTIuMTIgMC0zLjg3OS0xLjE2OC01LjE2OC0yLjQ1N0ExMy4xMzQgMTMuMTM0IDAgMCAxIDEuMTcyIDh6Ii8+DQogIDxwYXRoIGQ9Ik04IDUuNWEyLjUgMi41IDAgMSAwIDAgNSAyLjUgMi41IDAgMCAwIDAtNXpNNC41IDhhMy41IDMuNSAwIDEgMSA3IDAgMy41IDMuNSAwIDAgMS03IDB6Ii8+DQo8L3N2Zz4=); } div.pager { padding: 10px 0; text-align: center; } div.log { background: #333; border: solid thin rgba(127,127,127,.5); color: #ccc; height: 30em; margin-top: 20px; overflow: scroll; width: 100%; } div.log pre { padding: 10px; } /* Footer */ .footer { background: rgba(224,224,224,.9); bottom: 0; color: #777; font-size: 12px; height: 24px; left: 0; position: fixed; right: 0; width: 100%; } .footer a { color: #c66; } /* Grid System - Rows and Columns */ .row { position: relative; width: 100%; } .row::after { clear: both; content: ""; display: table; width: 0; } .row [class^="col-"] { float: left; margin: 20px 0 0 2%; min-height: 1px; padding: 5px 0; } .row:first-child [class^="col-"] { margin: 0 0 0 2%; } h1:first-child, h2:first-child, h3:first-child, .row p:first-child { margin-top: 0; } .row p:last-child, .rounded p:last-child { margin-bottom: 0; } .col-1 { width: 6.1666%; } .col-2 { width: 14.3333%; } .col-3 { width: 22.5%; } .col-4 { width: 30.6666%; } .col-5 { width: 38.8333%; } .col-6 { width: 47%; } .col-7 { width: 55.1666%; } .col-8 { width: 63.3333%; } .col-9 { width: 71.5%; } .col-10 { width: 79.6666%; } .col-11 { width: 87.8333%; } .col-12 { width: 96%; } /* Inline Styles */ span.badge { background: #c00; border-radius: 8px; color: #fff; font-size: 14px; font-weight: bold; padding: 1px 6px; } span.bar { box-shadow: 1px 1px 2px rgba(51,51,51,0.25); font-size: 20px; line-height: 20px; } img.idle, img.processing, img.stopped { border-radius: 10px; float: left; height: 64px; margin-right: 10px; padding: 5px; width: 64px; } img.idle { background-color: rgba(0,192,0,0.5); } img.processing { background-color: rgba(224,224,0,0.5); } img.stopped { background-color: rgba(192,0,0,0.5); } .shaded { background-color: rgba(127,127,127,.25); } h1.title { border-bottom: solid 2px black; clear: both; } h2.title { border-bottom: solid 1px #555; clear: both; color: #555; } .title a:link, .title a:visited { color: inherit; text-decoration: none; } .title a.btn, .title a.btn:visited { color: #ccc; vertical-align: 25%; } .title a.btn:hover, .title a.btn:active { color: #fff; } /* Animations */ .banner { animation: banner 3s 1s 1 forwards; background: rgba(160,160,224,0.5); border-radius: 5px; margin: 10px 0; padding: 10px; } @keyframes banner { 0% { background: rgba(160,160,224,0.5); } 100% { background: rgba(160,160,160,0.5); } } .spinner > div { width: 18px; height: 18px; border-radius: 100%; display: inline-block; animation: spinner 1.4s infinite ease-in-out both; } .spinner .bounce1 { animation-delay: -0.32s; } .spinner .bounce2 { animation-delay: -0.16s; } @keyframes spinner { 0%, 80%, 100% { transform: scale(0); background: rgba(160,160,160,0.5); } 40% { transform: scale(1.0); background: rgba(160,160,224,0.5); } } /* Form Tables */ table.form { border-collapse: collapse; margin-top: 10px; min-width: 50%; } table.form td, table.form th { line-height: 30px; padding: 5px 2px; vertical-align: top; } table.form th { text-align: right; } iframe#map { width: 300px; height: 200px; } /* List Tables */ table.list { border-bottom: solid thin black; border-collapse: collapse; clear: both; width: 100%; } table.list tr:nth-child(even) { background: #fcfcfc; } table.list tr:nth-child(odd) { background: #f0f0f0; } table.list th { background: white; border-bottom: solid thin black; text-align: left; vertical-align: bottom; } table.list td { margin: 0; padding: 5px; vertical-align: top; } /* Meter Tables for Supply Levels */ table.meter { border-collapse: collapse; margin-top: 10px; min-width: 50%; max-width: 600px; } table.meter thead td { border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; height: 4px; line-height: 4px; padding: 0; width: 20%; } table.meter tfoot td { border-left: 1px solid black; border-right: 1px solid black; border-top: 1px solid black; height: 4px; line-height: 4px; padding: 0; width: 20%; } table.meter td { padding: 5px 0; } table.meter th { border-right: 1px solid black; padding: 5px; text-align: right; } /* Small Device Overrides */ @media only screen and (min-device-width: 320px) and (max-device-width: 480px), only screen and (min-device-width: 320px) and (max-device-width: 568px) { .content { margin: 20px 0 20px; } .footer { height: auto; position: relative; } .row [class^="col-"] { width: 96%; } iframe#map { width: 200px; height: 200px; } } /* Dark Mode Overrides */ @media (prefers-color-scheme: dark) { body { background: black; color: #ccc; } span.bar { box-shadow: 1px 1px 5px rgba(255,255,255,0.5); } h1.title { border-bottom: solid 2px #ccc; } h2.title { border-bottom: solid 1px #999; color: #999; } input[type=email], input[type=text], input[type=password], input[type=number] { background: #333; color: #ccc; } select { background: #333 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23CCCCCC' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; color: #ccc; padding: 4px 32px 4px 8px; } select:hover { background: #444 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23DDDDDD' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; } div.switch label { background-color: #333; border: 1px solid rgba(191,191,191,0.2); color: #ccc; } div.switch input:checked + label { background-color: #ddd; color: #333; } table.list { border-bottom: solid thin #ccc; } table.list tr:nth-child(even) { background: #222; color: #ccc; } table.list tr:nth-child(odd) { background: #333; } table.list th { background: black; border-bottom: solid thin #ccc; } table.meter thead td { border-bottom: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; } table.meter tfoot td { border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 1px solid #ccc; } table.meter th { border-right: 1px solid #ccc; } } pappl-1.4.9/pappl/subscription-ipp.c000066400000000000000000000445411476704353100174550ustar00rootroot00000000000000// // IPP subscription processing for the Printer Application Framework // // Copyright © 2022-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // Local functions... // static pappl_subscription_t *find_subscription(pappl_client_t *client); // // '_papplSubscriptionIPPCancel()' - Cancel a subscription. // void _papplSubscriptionIPPCancel( pappl_client_t *client) // I - Client { pappl_subscription_t *sub; // Subscription // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } // Find the subscription... if ((sub = find_subscription(client)) == NULL) return; // Cancel it... papplSubscriptionCancel(sub); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // '_papplSubscriptionIPPCreate()' - Create subscriptions. // void _papplSubscriptionIPPCreate( pappl_client_t *client) // I - Client { pappl_subscription_t *sub; // Subscription ipp_attribute_t *attr; // Subscription attribute const char *username; // Most authenticated username int num_subs = 0, // Number of subscriptions ok_subs = 0; // Number of good subscriptions // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } if (ippGetOperation(client->request) == IPP_OP_CREATE_JOB_SUBSCRIPTIONS && !client->job) { // Get the job target for the subscription... int job_id; // Job ID if ((attr = ippFindAttribute(client->request, "notify-job-id", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing \"notify-job-id\" attribute."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetCount(attr) != 1 || (job_id = ippGetInteger(attr, 0)) < 1) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad \"notify-job-id\" attribute."); return; } else if ((client->job = papplPrinterFindJob(client->printer, job_id)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job #%d not found.", job_id); return; } } // For the Create-xxx-Subscriptions operations, queue up a successful-ok // response... if (ippGetOperation(client->request) == IPP_OP_CREATE_JOB_SUBSCRIPTIONS || ippGetOperation(client->request) == IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS || ippGetOperation(client->request) == IPP_OP_CREATE_SYSTEM_SUBSCRIPTIONS) papplClientRespondIPP(client, IPP_STATUS_OK, NULL); if (client->username[0]) username = client->username; else if ((username = ippGetString(ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME), 0, NULL)) == NULL) username = "anonymous"; // Skip past the initial attributes to the first subscription group. attr = ippGetFirstAttribute(client->request); while (attr && ippGetGroupTag(attr) != IPP_TAG_SUBSCRIPTION) attr = ippGetNextAttribute(client->request); while (attr) { const char *attrname, // Attribute name *pull_method = NULL, // "notify-pull-method" value *language = "en"; // "notify-natural-language" value pappl_event_t events = PAPPL_EVENT_NONE; // "notify-events" bit field const void *data = NULL; // "notify-user-data" value, if any cups_len_t datalen = 0; // "notify-user-data" value length int interval = 0, // "notify-time-interval" value lease = PAPPL_LEASE_DEFAULT; // "notify-lease-duration" value ipp_status_t status = IPP_STATUS_OK; // "notify-status-code" value num_subs ++; while (attr) { if ((attrname = ippGetName(attr)) == NULL) break; if (!strcmp(attrname, "notify-recipient-uri")) { // Don't allow push notifications... status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } else if (!strcmp(attrname, "notify-pull-method")) { // Allow "ippget" pull method... pull_method = ippGetString(attr, 0, NULL); if (ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetCount(attr) != 1 || !pull_method || strcmp(pull_method, "ippget")) { ippCopyAttribute(client->response, attr, 0); pull_method = NULL; status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; } } else if (!strcmp(attrname, "notify-charset")) { // Only allow "utf-8" and "us-ascii" character sets... const char *charset = ippGetString(attr, 0, NULL); // "notify-charset" value if (ippGetValueTag(attr) != IPP_TAG_CHARSET || ippGetCount(attr) != 1 || !charset || (strcmp(charset, "us-ascii") && strcmp(charset, "utf-8"))) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } } else if (!strcmp(attrname, "notify-natural-language")) { language = ippGetString(attr, 0, NULL); if (ippGetValueTag(attr) != IPP_TAG_LANGUAGE || ippGetCount(attr) != 1) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } } else if (!strcmp(attrname, "notify-user-data")) { if (ippGetValueTag(attr) != IPP_TAG_STRING || ippGetCount(attr) != 1 || (data = ippGetOctetString(attr, 0, &datalen)) == NULL || datalen > 63) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } } else if (!strcmp(attrname, "notify-events")) { if (ippGetValueTag(attr) != IPP_TAG_KEYWORD) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } else events = _papplSubscriptionEventImport(attr); } else if (!strcmp(attrname, "notify-lease-duration")) { if (ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetCount(attr) != 1 || (lease = ippGetInteger(attr, 0)) < 0) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } } else if (!strcmp(attrname, "notify-time-interval")) { if (ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetCount(attr) != 1 || (interval = ippGetInteger(attr, 0)) < 0) { status = IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES; ippCopyAttribute(client->response, attr, 0); } } attr = ippGetNextAttribute(client->request); } if (!pull_method || events == PAPPL_EVENT_NONE) status = IPP_STATUS_ERROR_BAD_REQUEST; if (num_subs > 1) ippAddSeparator(client->response); if (status) { // Just return a status code since something was wrong with this request... ippAddInteger(client->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM, "notify-status-code", status); } else if ((sub = papplSubscriptionCreate(client->system, client->printer, client->job, 0, events, username, language, data, (size_t)datalen, interval, lease)) != NULL) { // Return the subscription ID for this one... ippAddInteger(client->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-subscription-id", sub->subscription_id); ok_subs ++; } else { // Return a status code indicating that we weren't able to create the // subscription for an internal reason... ippAddInteger(client->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM, "notify-status-code", IPP_STATUS_ERROR_INTERNAL); } } // If we weren't able to create all of the requested subscriptions, return an // appropriate status code... if (ok_subs == 0 && num_subs != 0) ippSetStatusCode(client->response, IPP_STATUS_ERROR_IGNORED_ALL_SUBSCRIPTIONS); else if (ok_subs != num_subs) ippSetStatusCode(client->response, IPP_STATUS_OK_IGNORED_SUBSCRIPTIONS); } // // '_papplSubscriptionIPPGetAttributes()' - Get subscription attributes. // void _papplSubscriptionIPPGetAttributes( pappl_client_t *client) // I - Client { pappl_subscription_t *sub; // Subscription cups_array_t *ra; // Requested attributes // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } // Find the subscription... if ((sub = find_subscription(client)) == NULL) return; // Return attributes... ra = ippCreateRequestedArray(client->request); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(sub); _papplCopyAttributes(client->response, sub->attrs, ra, IPP_TAG_SUBSCRIPTION, false); _papplRWUnlock(sub); cupsArrayDelete(ra); } // // '_papplSubscriptionIPPGetNotifications()' - Get event notifications. // void _papplSubscriptionIPPGetNotifications( pappl_client_t *client) // I - Client { ipp_attribute_t *sub_ids, // notify-subscription-ids *seq_nums; // notify-sequence-numbers pappl_subscription_t *sub; // Current subscription bool notify_wait; // Wait for events? cups_len_t i, // Looping vars count; // Number of IDs int seq_num; // Sequence number ipp_t *event; // Current event int num_events = 0; // Number of events returned // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } // Get request attributes... if ((sub_ids = ippFindAttribute(client->request, "notify-subscription-ids", IPP_TAG_INTEGER)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing \"notify-subscription-ids\" attribute."); return; } count = ippGetCount(sub_ids); seq_nums = ippFindAttribute(client->request, "notify-sequence-numbers", IPP_TAG_INTEGER); notify_wait = ippGetBoolean(ippFindAttribute(client->request, "notify-wait", IPP_TAG_BOOLEAN), 0); if (seq_nums && count != ippGetCount(seq_nums)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "The \"notify-subscription-ids\" and \"notify-sequence-numbers\" attributes have different lengths."); return; } do { for (i = 0; i < count; i ++) { if ((sub = papplSystemFindSubscription(client->system, ippGetInteger(sub_ids, i))) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Subscription #%d was not found.", ippGetInteger(sub_ids, i)); ippAddInteger(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER, "notify-subscription-ids", ippGetInteger(sub_ids, i)); break; } _papplRWLockRead(sub); seq_num = ippGetInteger(seq_nums, i); if (seq_num < sub->first_sequence) seq_num = sub->first_sequence; if (seq_num > sub->last_sequence) { // No more events... _papplRWUnlock(sub); continue; } // Copy events to the output... for (event = (ipp_t *)cupsArrayGetElement(sub->events, (cups_len_t)(seq_num - sub->first_sequence)); event; event = (ipp_t *)cupsArrayGetNext(sub->events)) { if (num_events == 0) { // This is the first event in the notification... papplClientRespondIPP(client, IPP_STATUS_OK, NULL); ippAddInteger(client->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-get-interval", 30); if (client->printer) ippAddInteger(client->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "printer-up-time", (int)(time(NULL) - client->printer->start_time)); else ippAddInteger(client->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "system-up-time", (int)(time(NULL) - client->system->start_time)); } else { // Add a separator between attribute groups... ippAddSeparator(client->response); } ippCopyAttributes(client->response, event, 0, NULL, NULL); num_events ++; } _papplRWUnlock(sub); } if (i < count || !notify_wait) { // Stop looping... break; } else if (num_events == 0) { // Wait up to 30 seconds for more events... struct timeval curtime; // Current time struct timespec timeout; // Timeout papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Waiting for events."); gettimeofday(&curtime, NULL); timeout.tv_sec = curtime.tv_sec + 30; timeout.tv_nsec = curtime.tv_usec * 1000; pthread_mutex_lock(&client->system->subscription_mutex); pthread_cond_timedwait(&client->system->subscription_cond, &client->system->subscription_mutex, &timeout); pthread_mutex_unlock(&client->system->subscription_mutex); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Done waiting for events."); // Don't wait again... notify_wait = false; } } while (num_events == 0); } // // '_papplSubscriptionIPPList()' - List all subscriptions for a printer or system. // void _papplSubscriptionIPPList( pappl_client_t *client) // I - Client { pappl_subscription_t *sub; // Subscription cups_array_t *ra; // Requested attributes bool my_subs; // my-subscriptions value int job_id, // notify-job-id value limit, // limit value, if any count = 0; // Number of subscriptions reported const char *username; // Most authenticated user name // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } // Get request attributes... job_id = ippGetInteger(ippFindAttribute(client->request, "notify-job-id", IPP_TAG_INTEGER), 0); limit = ippGetInteger(ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER), 0); my_subs = ippGetBoolean(ippFindAttribute(client->request, "my-subscriptions", IPP_TAG_BOOLEAN), 0); ra = ippCreateRequestedArray(client->request); if (client->username[0]) username = client->username; else if ((username = ippGetString(ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME), 0, NULL)) == NULL) username = "anonymous"; papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(client->system); for (sub = (pappl_subscription_t *)cupsArrayGetFirst(client->system->subscriptions); sub; sub = (pappl_subscription_t *)cupsArrayGetNext(client->system->subscriptions)) { if ((job_id > 0 && (!sub->job || sub->job->job_id != job_id)) || (job_id <= 0 && sub->job)) continue; if (my_subs && strcmp(username, sub->username)) continue; if (count > 0) ippAddSeparator(client->response); _papplRWLockRead(sub); _papplCopyAttributes(client->response, sub->attrs, ra, IPP_TAG_SUBSCRIPTION, false); _papplRWUnlock(sub); count ++; if (limit > 0 && count >= limit) break; } _papplRWUnlock(client->system); cupsArrayDelete(ra); } // // '_papplSubscriptionIPPRenew()' - Renew a subscription. // void _papplSubscriptionIPPRenew( pappl_client_t *client) // I - Client { pappl_subscription_t *sub; // Subscription ipp_attribute_t *attr; // "notify-lease-duration" attribute int lease; // Lease duration // Authorize access... if (client->printer) { if (!_papplPrinterIsAuthorized(client)) return; } else { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } } // Find the subscription... if ((sub = find_subscription(client)) == NULL) return; // Renew it... if ((attr = ippFindAttribute(client->request, "notify-lease-duration", IPP_TAG_ZERO)) == NULL) { lease = PAPPL_LEASE_DEFAULT; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetCount(attr) != 1 || (lease = ippGetInteger(attr, 0)) < 0) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad \"notify-lease-duration\" attribute."); return; } papplSubscriptionRenew(sub, lease); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'find_subscription()' - Find the referenced subscription. // static pappl_subscription_t * // O - Subscription or `NULL` on error find_subscription( pappl_client_t *client) // I - Client { ipp_attribute_t *sub_id; // "subscription-id" attribute pappl_subscription_t *sub; // Subscription if ((sub_id = ippFindAttribute(client->request, "notify-subscription-id", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing \"notify-subscription-id\" attribute."); return (NULL); } else if (ippGetGroupTag(sub_id) != IPP_TAG_OPERATION || ippGetValueTag(sub_id) != IPP_TAG_INTEGER || ippGetCount(sub_id) != 1 || ippGetInteger(sub_id, 0) < 1) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad \"notify-subscription-id\" attribute."); return (NULL); } else if ((sub = papplSystemFindSubscription(client->system, ippGetInteger(sub_id, 0))) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Subscription #%d was not found.", ippGetInteger(sub_id, 0)); return (NULL); } else if (client->printer && sub->printer != client->printer) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Subscription #%d is not assigned to the specified printer.", ippGetInteger(sub_id, 0)); return (NULL); } return (sub); } pappl-1.4.9/pappl/subscription-private.h000066400000000000000000000052471476704353100203440ustar00rootroot00000000000000// // Private subscription header file for the Printer Application Framework // // Copyright © 2022-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_SUBSCRIPTION_PRIVATE_H_ # define _PAPPL_SUBSCRIPTION_PRIVATE_H_ # include "base-private.h" # include "subscription.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Constants... // # define PAPPL_LEASE_DEFAULT 3600 // Default lease duration in seconds (1 hour) # define PAPPL_LEASE_MAX 86400 // Maximum lease duration in seconds (1 day) # define PAPPL_MAX_EVENTS 100 // Maximum events per subscription // // Types... // struct _pappl_subscription_s // Subscription data { pthread_rwlock_t rwlock; // Reader/writer lock int subscription_id; // Subscription ID # ifdef DEBUG char name[128]; // Subscription name (for debugging) # endif // DEBUG pappl_event_t mask; // IPP "notify-events" bit field pappl_printer_t *printer; // Printer, if any pappl_job_t *job; // Job, if any ipp_t *attrs; // Attributes char *language, // Language for notifications *username, // Owner *uuid; // UUID time_t expire; // Expiration date/time, if any int lease, // Lease duration interval; // Notification interval int first_sequence, // First notify-sequence-number used last_sequence; // Last notify-sequence-number used cups_array_t *events; // Events (ipp_t *'s) bool is_canceled; // Has this subscription been canceled? }; // // Globals... // extern const char * const _papplEvents[31]; // // Functions... // extern void _papplSubscriptionDelete(pappl_subscription_t *sub) _PAPPL_PRIVATE; extern ipp_attribute_t *_papplSubscriptionEventExport(ipp_t *ipp, const char *name, ipp_tag_t group_tag, pappl_event_t value) _PAPPL_PRIVATE; extern pappl_event_t _papplSubscriptionEventImport(ipp_attribute_t *value) _PAPPL_PRIVATE; extern const char *_papplSubscriptionEventString(pappl_event_t value) _PAPPL_PRIVATE; extern pappl_event_t _papplSubscriptionEventValue(const char *value) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPCancel(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPCreate(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPGetAttributes(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPGetNotifications(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPList(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplSubscriptionIPPRenew(pappl_client_t *client) _PAPPL_PRIVATE; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_SUBSCRIPTION_PRIVATE_H_ pappl-1.4.9/pappl/subscription.c000066400000000000000000000217541476704353100166700ustar00rootroot00000000000000// // System event subscription functions for the Printer Application Framework // // Copyright © 2022-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local globals... // const char * const _papplEvents[31] = { // IPP "notify-events" strings for bits "document-completed", "document-config-changed", "document-created", "document-fetchable", "document-state-changed", "document-stopped", "job-completed", "job-config-changed", "job-created", "job-fetchable", "job-progress", "job-state-changed", "job-stopped", "printer-config-changed", "printer-finishings-changed", "printer-media-changed", "printer-queue-order-changed", "printer-restarted", "printer-shutdown", "printer-state-changed", "printer-stopped", "resource-canceled", "resource-config-changed", "resource-created", "resource-installed", "resource-changed", "printer-created", "printer-deleted", "system-config-changed", "system-state-changed", "system-stopped" }; // // 'papplSubscriptionCancel()' - Cancel a subscription. // // This function cancels a subscription. // void papplSubscriptionCancel( pappl_subscription_t *sub) // I - Subscription { if (sub) sub->is_canceled = true; } // // 'papplSubscriptionCreate()' - Create a subscription. // // This function creates a new system, printer, or job event subscription. // pappl_subscription_t * // O - Subscription papplSubscriptionCreate( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any int sub_id, // I - Subscription ID or `0` for new pappl_event_t events, // I - Notification events const char *username, // I - Owner const char *language, // I - Language const void *data, // I - User data, if any size_t datalen, // I - Length of user data int interval, // I - Notification interval int lease) // I - Lease duration or `0` for unlimited { pappl_subscription_t *sub; // New subscription char uuid[256]; // "notify-subscription-uuid" value if (!system || !events) return (NULL); if ((sub = (pappl_subscription_t *)calloc(1, sizeof(pappl_subscription_t))) == NULL) return (NULL); pthread_rwlock_init(&sub->rwlock, NULL); sub->printer = printer; sub->job = job; sub->subscription_id = sub_id; sub->mask = events; sub->username = strdup(username); sub->language = strdup(language ? language : "en"); sub->interval = interval; sub->lease = lease; if (lease) sub->expire = time(NULL) + lease; else sub->expire = time(NULL) + PAPPL_LEASE_MAX; #ifdef DEBUG snprintf(sub->name, sizeof(sub->name), "sub%d", sub_id); #endif // DEBUG if (!_papplSystemAddSubscription(system, sub, sub_id)) { _papplSubscriptionDelete(sub); return (NULL); } sub->attrs = ippNew(); ippAddString(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_CHARSET), "notify-charset", NULL, "utf-8"); _papplSubscriptionEventExport(sub->attrs, "notify-events", IPP_TAG_SUBSCRIPTION, events); if (job) ippAddInteger(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-job-id", job->job_id); else ippAddInteger(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-lease-duration", sub->lease); ippAddString(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "notify-natural-language", NULL, sub->language); ippAddString(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-pull-method", NULL, "ippget"); ippAddInteger(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-subscription-id", sub->subscription_id); ippAddString(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_NAME), "notify-subscriber-user-name", NULL, sub->username); _papplSystemMakeUUID(system, printer ? printer->name : NULL, -sub->subscription_id, uuid, sizeof(uuid)); ippAddString(sub->attrs, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-subscription-uuid", NULL, uuid); if (data && datalen > 0) ippAddOctetString(sub->attrs, IPP_TAG_SUBSCRIPTION, "notify-user-data", data, (cups_len_t)datalen); sub->first_sequence = 1; sub->events = cupsArrayNew(NULL, NULL, NULL, 0, NULL, (cups_afree_cb_t)ippDelete); return (sub); } // // '_papplSubscriptionDelete()' - Free the memory used for a subscription. // void _papplSubscriptionDelete( pappl_subscription_t *sub) // I - Subscription { _papplRWLockWrite(sub); ippDelete(sub->attrs); free(sub->username); free(sub->language); cupsArrayDelete(sub->events); _papplRWUnlock(sub); pthread_rwlock_destroy(&sub->rwlock); free(sub); } // // '_papplSubscriptionEventExport()' - Convert an IPP "notify-events" bit field value to an attribute. // ipp_attribute_t * // O - IPP attribute _papplSubscriptionEventExport( ipp_t *ipp, // I - IPP message const char *name, // I - IPP attribute name ipp_tag_t group_tag, // I - IPP group pappl_event_t value) // I - IPP "notify-events" bit value { pappl_event_t event; // Current event cups_len_t i, // Looping var num_events = 0; // Number of event keywords const char *events[31]; // Event keywords for (i = 0, event = PAPPL_EVENT_DOCUMENT_COMPLETED; i < (int)(sizeof(_papplEvents) / sizeof(_papplEvents[0])); i ++, event *= 2) { if (value & event) events[num_events ++] = _papplEvents[i]; } if (num_events == 0) events[num_events ++] = "none"; return (ippAddStrings(ipp, group_tag, IPP_CONST_TAG(IPP_TAG_KEYWORD), name, num_events, NULL, events)); } // // '_papplSubscriptionEventImport()' - Convert an IPP "notify-events" attribute to a bit field value. // pappl_event_t // O - Bit field value _papplSubscriptionEventImport( ipp_attribute_t *value) // I - IPP attribute { pappl_event_t events; // Current event cups_len_t i, // Looping var count; // Number of event keywords for (events = PAPPL_EVENT_NONE, i = 0, count = ippGetCount(value); i < count; i ++) events |= _papplSubscriptionEventValue(ippGetString(value, i, NULL)); return (events); } // // '_papplSubscriptionEventString()' - Return the keyword value associated with the IPP "notify-events" bit value. // const char * // O - IPP "notify-events" keyword value _papplSubscriptionEventString( pappl_event_t value) // I - IPP "notify-events" bit value { if (value == PAPPL_EVENT_NONE) return ("none"); else return (_PAPPL_LOOKUP_STRING(value, _papplEvents)); } // // '_papplSubscriptionEventValue()' - Return the bit value associated with the IPP "notify-events" keyword value. // pappl_event_t // O - IPP "notify-events" bit value _papplSubscriptionEventValue( const char *value) // I - IPP "notify-events" keyword value { return ((pappl_event_t)_PAPPL_LOOKUP_VALUE(value, _papplEvents)); } // // 'papplSubscriptionGetEvents()' - Return a subscription's events. // // This function returns a subscription's events. // pappl_event_t // O - IPP "notify-events" bit field papplSubscriptionGetEvents( pappl_subscription_t *sub) // I - Subscription { return (sub ? sub->mask : PAPPL_EVENT_NONE); } // // 'papplSubscriptionGetID()' - Return a subscription's numeric identifier. // // This function returns a subscription's numeric identifier. // int // O - Subscription ID papplSubscriptionGetID( pappl_subscription_t *sub) // I - Subscription { return (sub ? sub->subscription_id : 0); } // // 'papplSubscriptionGetJob()' - Return a subscription's associated job, if any. // // This function returns a subscription's associated job, if any. // pappl_job_t * // O - Job or `NULL` if not a job subscription papplSubscriptionGetJob( pappl_subscription_t *sub) // I - Subscription { return (sub ? sub->job : NULL); } // // 'papplSubscriptionGetPrinter()' - Return a subscription's associated printer, if any. // // This function returns a subscription's associated printer, if any. // pappl_printer_t * // O - Printer or `NULL` if not a printer subscription papplSubscriptionGetPrinter( pappl_subscription_t *sub) // I - Subscription { return (sub ? sub->printer : NULL); } // // 'papplSubscriptionGetUsername()' - Return a subscription's owner. // // This function returns a subscription's owner. // const char * // O - Owner papplSubscriptionGetUsername( pappl_subscription_t *sub) // I - Subscription { return (sub ? sub->username : NULL); } // // 'papplSubscriptionRenew()' - Renew a subscription. // void papplSubscriptionRenew( pappl_subscription_t *sub, // I - Subscription int lease) // I - Lease duration in seconds (`0` for indefinite) { if (!sub || sub->is_canceled || sub->job) return; _papplRWLockWrite(sub); if (lease <= 0 || lease > PAPPL_LEASE_MAX) lease = PAPPL_LEASE_MAX; sub->lease = lease; sub->expire = time(NULL) + lease; _papplRWUnlock(sub); } pappl-1.4.9/pappl/subscription.h000066400000000000000000000111041476704353100166610ustar00rootroot00000000000000// // Public subscription header file for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_SUBSCRIPTION_H_ # define _PAPPL_SUBSCRIPTION_H_ # include "base.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Types... // enum pappl_event_e // IPP "notify-events" bit values { PAPPL_EVENT_DOCUMENT_COMPLETED = 0x00000001, // 'document-completed' PAPPL_EVENT_DOCUMENT_CONFIG_CHANGED = 0x00000002, // 'document-config-changed' PAPPL_EVENT_DOCUMENT_CREATED = 0x00000004, // 'document-created' PAPPL_EVENT_DOCUMENT_FETCHABLE = 0x00000008, // 'document-fetchable' PAPPL_EVENT_DOCUMENT_STATE_CHANGED = 0x00000010, // 'document-state-changed' PAPPL_EVENT_DOCUMENT_STOPPED = 0x00000020, // 'document-stopped' PAPPL_EVENT_JOB_COMPLETED = 0x00000040, // 'job-completed' PAPPL_EVENT_JOB_CONFIG_CHANGED = 0x00000080, // 'job-config-changed' PAPPL_EVENT_JOB_CREATED = 0x00000100, // 'job-created' PAPPL_EVENT_JOB_FETCHABLE = 0x00000200, // 'job-fetchable' PAPPL_EVENT_JOB_PROGRESS = 0x00000400, // 'job-progress' PAPPL_EVENT_JOB_STATE_CHANGED = 0x00000800, // 'job-state-changed' PAPPL_EVENT_JOB_STOPPED = 0x00001000, // 'job-stopped' PAPPL_EVENT_PRINTER_CONFIG_CHANGED = 0x00002000, // 'printer-config-changed' PAPPL_EVENT_PRINTER_FINISHINGS_CHANGED = 0x00004000, // 'printer-finishings-changed' PAPPL_EVENT_PRINTER_MEDIA_CHANGED = 0x00008000, // 'printer-media-changed' PAPPL_EVENT_PRINTER_QUEUE_ORDER_CHANGED = 0x00010000, // 'printer-queue-order-changed' PAPPL_EVENT_PRINTER_RESTARTED = 0x00020000, // 'printer-restarted' PAPPL_EVENT_PRINTER_SHUTDOWN = 0x00040000, // 'printer-shutdown' PAPPL_EVENT_PRINTER_STATE_CHANGED = 0x00080000, // 'printer-state-changed' PAPPL_EVENT_PRINTER_STOPPED = 0x00100000, // 'printer-stopped' PAPPL_EVENT_RESOURCE_CANCELED = 0x00200000, // 'resource-canceled' PAPPL_EVENT_RESOURCE_CONFIG_CHANGED = 0x00400000, // 'resource-config-changed' PAPPL_EVENT_RESOURCE_CREATED = 0x00800000, // 'resource-created' PAPPL_EVENT_RESOURCE_INSTALLED = 0x01000000, // 'resource-installed' PAPPL_EVENT_RESOURCE_STATE_CHANGED = 0x02000000, // 'resource-state-changed' PAPPL_EVENT_PRINTER_CREATED = 0x04000000, // 'printer-created' PAPPL_EVENT_PRINTER_DELETED = 0x08000000, // 'printer-deleted' PAPPL_EVENT_SYSTEM_CONFIG_CHANGED = 0x10000000, // 'system-config-changed' PAPPL_EVENT_SYSTEM_STATE_CHANGED = 0x20000000, // 'system-state-changed' PAPPL_EVENT_SYSTEM_STOPPED = 0x40000000, // 'system-stopped' PAPPL_EVENT_NONE = 0x00000000, // 'none' PAPPL_EVENT_DOCUMENT_ALL = 0x0000003f,// All 'document-xxx' events PAPPL_EVENT_DOCUMENT_STATE_ALL = 0x00000037, // All 'document-xxx' state events PAPPL_EVENT_JOB_ALL = 0x00001fc0, // All 'job-xxx' events PAPPL_EVENT_JOB_STATE_ALL = 0x00001940, // All 'job-xxx' state events PAPPL_EVENT_PRINTER_ALL = 0x001fe000, // All 'printer-xxx' events PAPPL_EVENT_PRINTER_CONFIG_ALL = 0x0000e000, // All 'printer-xxx' configuration events PAPPL_EVENT_PRINTER_STATE_ALL = 0x001e0000, // All 'printer-xxx' state events PAPPL_EVENT_ALL = 0x7fffffff // All events }; typedef unsigned int pappl_event_t; // Bitfield for IPP "notify-events" attribute typedef void (*pappl_event_cb_t)(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, void *data); // System event callback // // Functions... // extern void papplSubscriptionCancel(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern pappl_subscription_t *papplSubscriptionCreate(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, int sub_id, pappl_event_t events, const char *username, const char *natural_language, const void *data, size_t datalen, int interval, int lease) _PAPPL_PUBLIC; extern pappl_event_t papplSubscriptionGetEvents(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern int papplSubscriptionGetID(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern pappl_job_t *papplSubscriptionGetJob(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern pappl_printer_t *papplSubscriptionGetPrinter(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern const char *papplSubscriptionGetUsername(pappl_subscription_t *sub) _PAPPL_PUBLIC; extern void papplSubscriptionRenew(pappl_subscription_t *sub, int lease) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_SUBSCRIPTION_H_ pappl-1.4.9/pappl/system-accessors.c000066400000000000000000002037011476704353100174450ustar00rootroot00000000000000// // System accessor functions for the Printer Application Framework // // Copyright © 2020-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "system-private.h" #ifdef HAVE_LIBJPEG # include # ifndef JPEG_LIB_VERSION_MAJOR // Added in JPEGLIB 9 # define JPEG_LIB_VERSION_MAJOR 8 # define JPEG_LIB_VERSION_MINOR 0 # endif // !JPEG_LIB_VERSION_MAJOR #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG # include #endif // HAVE_LIBPNG #ifndef _WIN32 # include #endif // !_WIN32 // // Local functions... // static bool add_listeners(pappl_system_t *system, const char *name, int port, int family); static int compare_filters(_pappl_mime_filter_t *a, _pappl_mime_filter_t *b); static int compare_timers(_pappl_timer_t *a, _pappl_timer_t *b); static _pappl_mime_filter_t *copy_filter(_pappl_mime_filter_t *f); // // 'papplSystemAddListeners()' - Add network or domain socket listeners. // // This function adds socket listeners. The "name" parameter specifies the // listener address. Names starting with a slash (/) specify a UNIX domain // socket path, otherwise the name is treated as a fully-qualified domain name // or numeric IPv4 or IPv6 address. If name is `NULL`, the "any" addresses are // used ("0.0.0.0" and "[::]"). // // Listeners cannot be added after @link papplSystemRun@ is called. // bool // O - `true` on success, `false` on failure papplSystemAddListeners( pappl_system_t *system, // I - System const char *name) // I - Hostname, domain socket filename, or `NULL` { bool ret; // Return value if (!system) { return (false); } else if (system->is_running) { papplLog(system, PAPPL_LOGLEVEL_FATAL, "Tried to add listeners while system is running."); return (false); } #if !_WIN32 if (name && *name == '/') { // Add a domain socket listener... ret = add_listeners(system, name, 0, AF_LOCAL); if (ret && !system->domain_path) system->domain_path = strdup(name); } else #endif // !_WIN32 if (name && isdigit(*name & 255)) { // Add IPv4 listener... if (system->port) { ret = add_listeners(system, name, system->port, AF_INET); } else { int port; // Current port #if _WIN32 port = 7999; #else port = 7999 + (getuid() % 1000); #endif // _WIN32 do { port ++; ret = add_listeners(system, name, port, AF_INET); } while (!ret && port < 10000); if (ret) system->port = port; } } else if (name && *name == '[') { // Add IPv6 listener... if (system->port) { ret = add_listeners(system, name, system->port, AF_INET6); } else { int port; // Current port #if _WIN32 port = 7999; #else port = 7999 + (getuid() % 1000); #endif // _WIN32 do { port ++; ret = add_listeners(system, name, port, AF_INET6); } while (!ret && port < 10000); if (ret) system->port = port; } } else { // Add named listeners on both IPv4 and IPv6... if (name && strcasecmp(name, "*")) { // Listening on a specific hostname... _papplRWLockWrite(system); free(system->hostname); system->hostname = strdup(name); system->is_listenhost = true; _papplRWUnlock(system); } if (system->port) { ret = add_listeners(system, name, system->port, AF_INET) || add_listeners(system, name, system->port, AF_INET6); } else { int port; // Current port #if _WIN32 port = 7999; #else port = 7999 + (getuid() % 1000); #endif // _WIN32 do { port ++; ret = add_listeners(system, name, port, AF_INET); } while (!ret && port < 10000); if (ret) { system->port = port; add_listeners(system, name, port, AF_INET6); } } } return (ret); } // // 'papplSystemAddMIMEFilter()' - Add a file filter to the system. // // This function adds a file filter to the system to be used for processing // different kinds of document data in print jobs. The "srctype" and "dsttype" // arguments specify the source and destination MIME media types as constant // strings. A destination MIME media type of "image/pwg-raster" specifies a // filter that uses the driver's raster interface. Other destination types // imply direct submission to the output device using the `papplDeviceXxx` // functions. // // > Note: This function may not be called while the system is running. // void papplSystemAddMIMEFilter( pappl_system_t *system, // I - System const char *srctype, // I - Source MIME media type (constant) string const char *dsttype, // I - Destination MIME media type (constant) string pappl_mime_filter_cb_t cb, // I - Filter callback function void *data) // I - Filter callback data { _pappl_mime_filter_t key; // Search key if (!system || system->is_running || !srctype || !dsttype || !cb) return; if (!system->filters) system->filters = cupsArrayNew((cups_array_cb_t)compare_filters, NULL, NULL, 0, (cups_acopy_cb_t)copy_filter, (cups_afree_cb_t)free); key.src = srctype; key.dst = dsttype; key.cb = cb; key.cbdata = data; if (!cupsArrayFind(system->filters, &key)) { papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Adding '%s' to '%s' filter.", srctype, dsttype); cupsArrayAdd(system->filters, &key); } } // // 'papplSystemAddTimerCallback()' - Add a timer callback to a system. // // This function schedules a function that will be called on the main run loop // thread at the specified time and optionally every "interval" seconds // thereafter. The timing accuracy is typically within a few milliseconds but // is not guaranteed. Since the callback is run on the main run loop thread, // functions should create a new thread for any long-running operations. // // The callback function receives the "system" and "cb_data" pointers and // returns `true` to repeat the timer or `false` to remove it: // // ``` // bool my_timer_cb(pappl_system_t *system, void *cb_data) // { // ... do periodic task ... // return (true); // repeat the timer // } // ``` // bool // O - `true` on success, `false` on error papplSystemAddTimerCallback( pappl_system_t *system, // I - System time_t start, // I - Start time in seconds or `0` for the current time int interval, // I - Repeat interval in seconds or `0` for no repeat pappl_timer_cb_t cb, // I - Callback function void *cb_data) // I - Callback data { _pappl_timer_t *newt; // New timer // Range check input... if (!system || !cb || interval < 0) return (false); // Allocate the new timer... if ((newt = calloc(1, sizeof(_pappl_timer_t))) == NULL) return (false); _papplRWLockWrite(system); if (!system->timers) system->timers = cupsArrayNew((cups_array_cb_t)compare_timers, NULL, NULL, 0, NULL, NULL); newt->cb = cb; newt->cb_data = cb_data; newt->next = start ? start : time(NULL) + interval; newt->interval = interval; cupsArrayAdd(system->timers, newt); _papplRWUnlock(system); return (true); } // // '_papplSystemExportVersions()' - Export the firmware versions to IPP attributes... // void _papplSystemExportVersions( pappl_system_t *system, // I - System ipp_t *ipp, // I - IPP message ipp_tag_t group_tag, // I - Group (`IPP_TAG_PRINTER` or `IPP_TAG_SYSTEM`) cups_array_t *ra) // I - Requested attributes or `NULL` for all { cups_len_t i; // Looping var ipp_attribute_t *attr; // Attribute char name[128]; // Attribute name const char *name_prefix = (group_tag == IPP_TAG_PRINTER) ? "printer" : "system"; const char *values[20]; // String values char cups_sversion[32]; // String version of libcups #ifdef HAVE_LIBJPEG char jpeg_sversion[32]; // String version of libjpeg #endif // HAVE_LIBJPEG unsigned short version[4]; // Version of software components // "xxx-firmware-name" snprintf(name, sizeof(name), "%s-firmware-name", name_prefix); if (!ra || cupsArrayFind(ra, name)) { for (i = 0; i < system->num_versions; i ++) values[i] = system->versions[i].name; values[i ++] = "PAPPL"; values[i ++] = "libcups"; #ifdef HAVE_LIBJPEG values[i ++] = "libjpeg"; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG values[i ++] = "libpng"; #endif // HAVE_LIBPNG ippAddStrings(ipp, group_tag, IPP_TAG_NAME, name, i, NULL, values); } // "xxx-firmware-patches" snprintf(name, sizeof(name), "%s-firmware-patches", name_prefix); if (!ra || cupsArrayFind(ra, name)) { for (i = 0; i < system->num_versions; i ++) values[i] = system->versions[i].patches; values[i ++] = ""; // No patches for PAPPL values[i ++] = ""; // No patches for CUPS #ifdef HAVE_LIBJPEG values[i ++] = ""; // No patches for libjpeg #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG values[i ++] = ""; // No patches for libpng #endif // HAVE_LIBPNG ippAddStrings(ipp, group_tag, IPP_TAG_TEXT, name, i, NULL, values); } // "xxx-firmware-string-version" snprintf(name, sizeof(name), "%s-firmware-string-version", name_prefix); if (!ra || cupsArrayFind(ra, name)) { for (i = 0; i < system->num_versions; i ++) values[i] = system->versions[i].sversion; values[i ++] = PAPPL_VERSION; snprintf(cups_sversion, sizeof(cups_sversion), "%d.%d.%d", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR, CUPS_VERSION_PATCH); values[i ++] = cups_sversion; #ifdef HAVE_LIBJPEG snprintf(jpeg_sversion, sizeof(jpeg_sversion), "%d.%d", JPEG_LIB_VERSION_MAJOR, JPEG_LIB_VERSION_MINOR); values[i ++] = jpeg_sversion; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG values[i ++] = png_libpng_ver; #endif // HAVE_LIBPNG ippAddStrings(ipp, group_tag, IPP_TAG_TEXT, name, i, NULL, values); } // "xxx-firmware-version" snprintf(name, sizeof(name), "%s-firmware-version", name_prefix); if (!ra || cupsArrayFind(ra, name)) { for (i = 0, attr = NULL; i < system->num_versions; i ++) { if (attr) ippSetOctetString(ipp, &attr, ippGetCount(attr), system->versions[i].version, (int)sizeof(system->versions[i].version)); else attr = ippAddOctetString(ipp, group_tag, name, system->versions[i].version, (int)sizeof(system->versions[i].version)); } memset(version, 0, sizeof(version)); sscanf(PAPPL_VERSION, "%hu.%hu.%hu", version + 0, version + 1, version + 2); if (attr) ippSetOctetString(ipp, &attr, ippGetCount(attr), version, (int)sizeof(version)); else attr = ippAddOctetString(ipp, group_tag, name, version, (int)sizeof(version)); version[0] = CUPS_VERSION_MAJOR; version[1] = CUPS_VERSION_MINOR; version[2] = CUPS_VERSION_PATCH; ippSetOctetString(ipp, &attr, ippGetCount(attr), version, (int)sizeof(version)); #ifdef HAVE_LIBJPEG version[0] = JPEG_LIB_VERSION_MAJOR; version[1] = JPEG_LIB_VERSION_MINOR; version[2] = 0; ippSetOctetString(ipp, &attr, ippGetCount(attr), version, (int)sizeof(version)); #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG memset(version, 0, sizeof(version)); sscanf(png_libpng_ver, "%hu.%hu.%hu", version + 0, version + 1, version + 2); ippSetOctetString(ipp, &attr, ippGetCount(attr), version, (int)sizeof(version)); #endif // HAVE_LIBPNG } } // // '_papplSystemFindMIMEFilter()' - Find a filter for the given source and destination formats. // _pappl_mime_filter_t * // O - Filter data _papplSystemFindMIMEFilter( pappl_system_t *system, // I - System const char *srctype, // I - Source MIME media type string const char *dsttype) // I - Destination MIME media type string { _pappl_mime_filter_t key, // Search key *match; // Matching filter if (!system || !srctype || !dsttype) return (NULL); _papplRWLockRead(system); key.src = srctype; key.dst = dsttype; match = (_pappl_mime_filter_t *)cupsArrayFind(system->filters, &key); _papplRWUnlock(system); return (match); } // // 'papplSystemGetAdminGroup()' - Get the current administrative group, if any. // // This function copies the current administrative group, if any, to the // specified buffer. // char * // O - Admin group or `NULL` if none papplSystemGetAdminGroup( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->admin_group) { papplCopyString(buffer, system->admin_group, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetAuthService()' - Get the PAM authorization service, if any. // // This function returns the PAM authorization service being used by the system // for authentication, if any. // const char * // O - PAM authorization service or `NULL` if none papplSystemGetAuthService( pappl_system_t *system) // I - System { return (system ? system->auth_service : NULL); } // // 'papplSystemGetContact()' - Get the "system-contact" value. // // This function copies the current system contact information to the specified // buffer. // pappl_contact_t * // O - Contact papplSystemGetContact( pappl_system_t *system, // I - System pappl_contact_t *contact) // O - Contact { if (!system || !contact) { if (contact) memset(contact, 0, sizeof(pappl_contact_t)); return (contact); } _papplRWLockRead(system); *contact = system->contact; _papplRWUnlock(system); return (contact); } // // 'papplSystemGetDefaultPrinterID()' - Get the current "default-printer-id" value. // // This function returns the positive integer identifier for the current // default printer or `0` if there is no default printer. // int // O - "default-printer-id" value papplSystemGetDefaultPrinterID( pappl_system_t *system) // I - System { int ret = 0; // Return value if (system) { _papplRWLockRead(system); ret = system->default_printer_id; _papplRWUnlock(system); } return (ret); } // // 'papplSystemGetDefaultPrintGroup()' - Get the default print group, if any. // // This function copies the current default print group, if any, to the // specified buffer. // char * // O - Default print group or `NULL` if none papplSystemGetDefaultPrintGroup( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->default_print_group) { papplCopyString(buffer, system->default_print_group, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetDNSSDName()' - Get the current DNS-SD service name. // // This function copies the current DNS-SD service name of the system, if any, // to the specified buffer. // char * // O - Current DNS-SD service name or `NULL` for none papplSystemGetDNSSDName( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->dns_sd_name) { papplCopyString(buffer, system->dns_sd_name, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetFooterHTML()' - Get the footer HTML for the web interface, if any. // // This function returns the HTML for the web page footer, if any. The footer // HTML can be set using the @link papplSystemSetFooterHTML@ function. // const char * // O - Footer HTML or `NULL` if none papplSystemGetFooterHTML( pappl_system_t *system) // I - System { return (system ? system->footer_html : NULL); } // // 'papplSystemGetGeoLocation()' - Get the system geo-location string, if any. // // This function copies the current system geographic location as a "geo:" URI // to the specified buffer. // char * // O - "geo:" URI or `NULL` for none papplSystemGetGeoLocation( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->geo_location) { papplCopyString(buffer, system->geo_location, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetHostname()' - Get the system hostname. // // This function is deprecated. Use the @link papplSystemGetHostName@ function // instead. // // @deprecated@ @exclude all@ // char * // O - Hostname papplSystemGetHostname( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { return (papplSystemGetHostName(system, buffer, bufsize)); } // // 'papplSystemGetHostName()' - Get the system hostname. // // This function copies the current system hostname to the specified buffer. // char * // O - Hostname papplSystemGetHostName( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->hostname) { papplCopyString(buffer, system->hostname, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetHostPort()' - Get the port number for network connections to // the system. // // This function returns the port number that is used for network connections // to the system. // int // O - Port number papplSystemGetHostPort( pappl_system_t *system) // I - System { return (system ? system->port : 0); } // // 'papplSystemGetLocation()' - Get the system location string, if any. // // This function copies the current human-readable location, if any, to the // specified buffer. // char * // O - Location string or `NULL` for none papplSystemGetLocation( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->location) { papplCopyString(buffer, system->location, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetLogLevel()' - Get the system log level. // // This function returns the current system log level as an enumeration. // pappl_loglevel_t // O - Log level papplSystemGetLogLevel( pappl_system_t *system) // I - System { pappl_loglevel_t ret = PAPPL_LOGLEVEL_UNSPEC; // Return value if (system) { pthread_mutex_lock(&system->log_mutex); ret = system->log_level; pthread_mutex_unlock(&system->log_mutex); } return (ret); } // // 'papplSystemGetMaxClients()' - Get the maximum number of clients. // // This function gets the maximum number of simultaneous clients that are // allowed by the system. // int // O - Maximum number of clients papplSystemGetMaxClients( pappl_system_t *system) // I - System { int ret = 0; // Return value if (system) { _papplRWLockRead(system); ret = system->max_clients; _papplRWUnlock(system); } return (ret); } // // 'papplSystemGetMaxImageSize()' - Get the maximum supported size for images. // // This function retrieves the image size limits in bytes (uncompressed), // columns, and lines. // size_t // O - Maximum image size (uncompressed) papplSystemGetMaxImageSize( pappl_system_t *system, // I - System int *max_width, // O - Maximum width in columns int *max_height) // O - Maximum height in lines { size_t max_size; // Maximum image file size // Range check input... if (!system) { if (max_width) *max_width = 0; if (max_height) *max_height = 0; return (0); } // Grab a snapshot of the limits... _papplRWLockRead(system); max_size = system->max_image_size; if (max_width) *max_width = system->max_image_width; if (max_height) *max_height = system->max_image_height; _papplRWUnlock(system); return (max_size); } // // 'papplSystemGetMaxLogSize()' - Get the maximum log file size. // // This function gets the maximum log file size, which is only used when logging // directly to a file. When the limit is reached, the current log file is // renamed to "filename.O" and a new log file is created. Set the maximum size // to `0` to disable log file rotation. // // The default maximum log file size is 1MiB or `1048576` bytes. // size_t // O - Maximum log file size or `0` for none papplSystemGetMaxLogSize( pappl_system_t *system) // I - System { size_t ret = 0; // Return value if (system) { pthread_mutex_lock(&system->log_mutex); ret = system->log_max_size; pthread_mutex_unlock(&system->log_mutex); } return (ret); } // // 'papplSystemGetMaxSubscriptions()' - Get the maximum number of event subscriptions. // // This function gets the maximum number of event subscriptions that are // allowed. A maximum of `0` means there is no limit. // // The default maximum number of event subscriptions is 100. // size_t // O - Maximum number of subscriptions or `0` papplSystemGetMaxSubscriptions( pappl_system_t *system) // I - System { size_t ret = 0; // Return value if (system) { _papplRWLockRead(system); ret = system->max_subscriptions; _papplRWUnlock(system); } return (ret); } // // 'papplSystemGetName()' - Get the system name. // // This function copies the current system name to the specified buffer. // char * // O - Name string papplSystemGetName( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->name) { papplCopyString(buffer, system->name, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetNextPrinterID()' - Get the next "printer-id" value. // // This function returns the positive integer identifier that will be used for // the next printer that is created. // int // O - Next "printer-id" value papplSystemGetNextPrinterID( pappl_system_t *system) // I - System { int ret = 0; // Return value if (system) { _papplRWLockRead(system); ret = system->next_printer_id; _papplRWUnlock(system); } return (ret); } // // 'papplSystemGetOptions()' - Get the system options. // // This function returns the system options as a bitfield. // pappl_soptions_t // O - System options papplSystemGetOptions( pappl_system_t *system) // I - System { return (system ? system->options : PAPPL_SOPTIONS_NONE); } // // 'papplSystemGetOrganization()' - Get the system organization string, if any. // // This function copies the current organization name, if any, to the // specified buffer. // char * // O - Organization string or `NULL` for none papplSystemGetOrganization( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->organization) { papplCopyString(buffer, system->organization, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetOrganizationalUnit()' - Get the system organizational unit string, if any. // // This function copies the current organizational unit name, if any, to the // specified buffer. // char * // O - Organizational unit string or `NULL` for none papplSystemGetOrganizationalUnit( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { char *ret = NULL; // Return value if (system && buffer && bufsize > 0) { _papplRWLockRead(system); if (system->org_unit) { papplCopyString(buffer, system->org_unit, bufsize); ret = buffer; } else *buffer = '\0'; _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (ret); } // // 'papplSystemGetPassword()' - Get the current web site access password. // // This function copies the current web site password hash, if any, to the // specified buffer. // // Note: The access password is only used when the PAM authentication service // is not set. // char * // O - Password hash papplSystemGetPassword( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (system && buffer && bufsize > 0) { _papplRWLockRead(system); papplCopyString(buffer, system->password_hash, bufsize); _papplRWUnlock(system); } else if (buffer) *buffer = '\0'; return (buffer); } // // 'papplSystemGetPort()' - Get the port number for network connections to the // system. // // This function is deprecated. Use the @link papplSystemGetHostName@ function // instead. // // @deprecated@ @exclude all@ // int // O - Port number papplSystemGetPort( pappl_system_t *system) // I - System { return (system ? system->port : 0); } // // 'papplSystemGetServerHeader()' - Get the Server: header for HTTP responses. // // This function returns the value of the HTTP "Server:" header that is used // by the system. // const char * // O - Server: header string or `NULL` for none papplSystemGetServerHeader( pappl_system_t *system) // I - System { return (system ? system->server_header : NULL); } // // 'papplSystemGetSessionKey()' - Get the current session key. // // This function copies the current session key to the specified buffer. The // session key is used for web interface forms to provide CSRF protection and is // refreshed periodically. // char * // O - Session key papplSystemGetSessionKey( pappl_system_t *system, // I - System char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { time_t curtime = time(NULL); // Current time if (system && buffer && bufsize > 0) { pthread_mutex_lock(&system->session_mutex); if ((curtime - system->session_time) > 86400) { // Lock for updating the session key with random data... snprintf(system->session_key, sizeof(system->session_key), "%08x%08x%08x%08x%08x%08x%08x%08x", papplGetRand(), papplGetRand(), papplGetRand(), papplGetRand(), papplGetRand(), papplGetRand(), papplGetRand(), papplGetRand()); system->session_time = curtime; } papplCopyString(buffer, system->session_key, bufsize); pthread_mutex_unlock(&system->session_mutex); } else if (buffer) { *buffer = '\0'; } return (buffer); } // // 'papplSystemGetTLSOnly()' - Get the TLS-only state of the system. // // This function returns whether the system will only accept encrypted // connections. // bool // O - `true` if the system is only accepting TLS encrypted connections, `false` otherwise papplSystemGetTLSOnly( pappl_system_t *system) // I - System { return (system ? system->tls_only : false); } // // 'papplSystemGetUUID()' - Get the "system-uuid" value. // // This function returns the system's UUID value. // const char * // O - "system-uuid" value papplSystemGetUUID( pappl_system_t *system) // I - System { const char *ret = NULL; // Return value if (system) { _papplRWLockRead(system); ret = system->uuid; _papplRWUnlock(system); } return (ret); } // // 'papplSystemGetVersions()' - Get the firmware names and versions. // // This function copies the system firmware information to the specified buffer. // The return value is always the number of firmware versions that have been // set using the @link papplSystemSetVersions@ function, regardless of the // value of the "max_versions" argument. // int // O - Number of firmware versions papplSystemGetVersions( pappl_system_t *system, // I - System int max_versions, // I - Maximum number of versions to return pappl_version_t *versions) // O - Versions array or `NULL` for don't care { if (versions && max_versions > 0) memset(versions, 0, (size_t)max_versions * sizeof(pappl_version_t)); if (system && versions && system->num_versions > 0) { _papplRWLockRead(system); if (max_versions > (int)system->num_versions) memcpy(versions, system->versions, (size_t)system->num_versions * sizeof(pappl_version_t)); else memcpy(versions, system->versions, (size_t)max_versions * sizeof(pappl_version_t)); _papplRWUnlock(system); } return (system ? (int)system->num_versions : 0); } // // 'papplSystemHashPassword()' - Generate a password hash using salt and password strings. // // This function generates a password hash using the "salt" and "password" // strings. The "salt" string should be `NULL` to generate a new password hash // or the value of an existing password hash to verify that a given plaintext // "password" string matches the password hash. // // > Note: Hashed access passwords are only used when the PAM authentication // > service is not set. // char * // O - Hashed password papplSystemHashPassword( pappl_system_t *system, // I - System const char *salt, // I - Existing password hash or `NULL` to generate a new hash const char *password, // I - Plain-text password string char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { if (system && password && buffer && bufsize > 0) { char nonce[100], // Nonce string *ptr, // Pointer into string temp[256]; // Temporary hash unsigned char hash[32]; // SHA2-256 hash if (salt && strchr(salt, '~')) { // Copy existing nonce from the salt string... papplCopyString(nonce, salt, sizeof(nonce)); if ((ptr = strchr(nonce, '~')) != NULL) *ptr = '\0'; } else { // Generate a new random nonce... snprintf(nonce, sizeof(nonce), "%08x%08x", papplGetRand(), papplGetRand()); } snprintf(temp, sizeof(temp), "%s:%s", nonce, password); cupsHashData("sha2-256", temp, strlen(temp), hash, sizeof(hash)); cupsHashString(hash, sizeof(hash), temp, sizeof(temp)); snprintf(buffer, bufsize, "%s~%s", nonce, temp); } else if (buffer) *buffer = '\0'; return (buffer); } // // 'papplSystemIsRunning()' - Return whether the system is running. // // This function returns whether the system is running. // bool // O - `true` if the system is running, `false` otherwise papplSystemIsRunning( pappl_system_t *system) // I - System { bool is_running; // Return value // Range check input if (!system) return (false); _papplRWLockRead(system); is_running = system->is_running; _papplRWUnlock(system); return (is_running); } // // '_papplSystemIsShutdownNoLock()' - Return whether the system has been shutdown. // // This function returns whether the system is shutdown or scheduled to // shutdown. // bool // O - `true` if the system is shutdown, `false` otherwise _papplSystemIsShutdownNoLock( pappl_system_t *system) // I - System { return (!system->is_running || system->shutdown_time != 0); } // // 'papplSystemIsShutdown()' - Return whether the system has been shutdown. // // This function returns whether the system is shutdown or scheduled to // shutdown. // bool // O - `true` if the system is shutdown, `false` otherwise papplSystemIsShutdown( pappl_system_t *system) // I - System { bool ret = false; // Return value if (system) { _papplRWLockRead(system); ret = _papplSystemIsShutdownNoLock(system); _papplRWUnlock(system); } return (ret); } // // 'papplSystemIteratePrinters()' - Iterate all of the printers. // // This function iterates each of the printers managed by the system. The // "cb" function is called once per printer with the "system" and "data" values. // void papplSystemIteratePrinters( pappl_system_t *system, // I - System pappl_printer_cb_t cb, // I - Callback function void *data) // I - Callback data { cups_len_t i, // Looping var count; // Number of printers if (!system || !cb) return; // Loop through the printers. // // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the printers array. _papplRWLockRead(system); for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) (cb)((pappl_printer_t *)cupsArrayGetElement(system->printers, i), data); _papplRWUnlock(system); } // // 'papplSystemMatchDriver()' - Match a driver to an IEEE-1284 device ID. // const char * papplSystemMatchDriver( pappl_system_t *system, // I - System const char *device_id) // I - IEEE-1284 device ID string { cups_len_t i; // Looping var pappl_pr_driver_t *driver; // Current driver const char *drvstart, // Start of key/value pair *drvend, // End of key/value pair *didptr, // Pointer into device ID *didend; // End of device ID size_t drvlen, // Length of key/value pair didlen; // Length of device ID if (!system) return (NULL); didlen = strlen(device_id); for (i = system->num_drivers, driver = system->drivers; i > 0; i --, driver ++) { if (!driver->device_id) continue; // Parse each of the driver's device ID pairs and compare against the // supplied device ID... drvstart = driver->device_id; while (*drvstart) { // Skip leading semicolons and whitespace (not valid, but sometimes // present...) while (*drvstart == ';' || isspace(*drvstart & 255)) drvstart ++; if (!*drvstart) break; // Find the end of the current key:value pair... drvend = drvstart + 1; while (*drvend && *drvend != ';') drvend ++; if (*drvend == ';') drvend ++; drvlen = (size_t)(drvend - drvstart); // See if this string exists in the target device ID... didptr = device_id; didend = didptr + didlen - drvlen; while (didptr && didptr < didend) { if (!strncmp(didptr, drvstart, drvlen)) break; if ((didptr = strchr(didptr, ';')) != NULL) didptr ++; } if (!didptr || didptr >= didend) break; drvstart = drvend; } if (!*drvstart) break; } if (i > 0) return (driver->name); else return (NULL); } // // '_papplSystemNeedClean()' - Mark the system needing cleaning. // void _papplSystemNeedClean( pappl_system_t *system) // I - System { _papplRWLockWrite(system); if (!system->clean_time) system->clean_time = time(NULL) + 60; _papplRWUnlock(system); } // // 'papplSystemRemoveTimerCallback()' - Remove a timer callback. // // This function removes all matching timer callbacks from the specified system. // Both the callback function and data must match to remove a timer. // void papplSystemRemoveTimerCallback( pappl_system_t *system, // I - System pappl_timer_cb_t cb, // I - Callback function void *cb_data) // I - Callback data { _pappl_timer_t *t; // Current timer // Range check input... if (!system || !cb) return; // Loop through the timers and remove any matches... _papplRWLockWrite(system); for (t = (_pappl_timer_t *)cupsArrayGetFirst(system->timers); t; t = (_pappl_timer_t *)cupsArrayGetNext(system->timers)) { if (t->cb == cb && t->cb_data == cb_data) { cupsArrayRemove(system->timers, t); free(t); } } _papplRWUnlock(system); } // // 'papplSystemSetAdminGroup()' - Set the administrative group. // // This function sets the group name used for administrative requests such as // adding or deleting a printer. // // > Note: The administrative group is only used when the PAM authorization // > service is also set when the system is created. // void papplSystemSetAdminGroup( pappl_system_t *system, // I - System const char *value) // I - Admin group { if (system) { _papplRWLockWrite(system); free(system->admin_group); system->admin_group = value ? strdup(value) : NULL; #if !_WIN32 // TODO: Implement Windows admin group support if (system->admin_group && strcmp(system->admin_group, "none")) { char buffer[8192]; // Buffer for strings struct group grpbuf, // Group buffer *grp = NULL; // Admin group if (getgrnam_r(system->admin_group, &grpbuf, buffer, sizeof(buffer), &grp) || !grp) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to find admin group '%s'.", system->admin_group); else system->admin_gid = grp->gr_gid; } else #endif // !_WIN32 system->admin_gid = (gid_t)-1; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetAuthCallback()' - Set an authentication callback for the specified scheme. // // This function sets the authentication callback that is used for Client // requests. The authentication callback is used for every Client request // containing the WWW-Authenticate header (`HTTP_FIELD_WWW_AUTHENTICATE`). // The callback returns one of the following status codes: // // - `HTTP_STATUS_CONTINUE` if the authentication succeeded, // - `HTTP_STATUS_UNAUTHORIZED` if the authentication failed, or // - `HTTP_STATUS_FORBIDDEN` if the authentication succeeded but the user is // not part of the specified group. // // > Note: The authentication callback can only be set prior to calling // > @link papplSystemRun@. // void papplSystemSetAuthCallback( pappl_system_t *system, // I - System const char *auth_scheme, // I - Authentication scheme pappl_auth_cb_t auth_cb, // I - Callback function void *auth_cbdata) // I - Callback data { if (system && !system->is_running) { free(system->auth_scheme); system->auth_scheme = auth_scheme ? strdup(auth_scheme) : NULL; system->auth_cb = auth_cb; system->auth_cbdata = auth_cbdata; } } // // 'papplSystemSetContact()' - Set the "system-contact" value. // // This function sets the system contact value. // void papplSystemSetContact( pappl_system_t *system, // I - System pappl_contact_t *contact) // I - Contact { if (!system || !contact) return; _papplRWLockWrite(system); system->contact = *contact; _papplSystemConfigChanged(system); _papplRWUnlock(system); } // // 'papplSystemSetDefaultPrinterID()' - Set the "default-printer-id" value. // // This function sets the default printer using its unique positive integer // identifier. // void papplSystemSetDefaultPrinterID( pappl_system_t *system, // I - System int default_printer_id) // I - "default-printer-id" value { if (system) { _papplRWLockWrite(system); system->default_printer_id = default_printer_id; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetDefaultPrintGroup()' - Set the default print group. // // This function sets the default group name used for print requests. // // > Note: The default print group is only used when the PAM authorization // > service is also set when the system is created. // void papplSystemSetDefaultPrintGroup( pappl_system_t *system, // I - System const char *value) // I - Default print group or `NULL` for none { if (system) { _papplRWLockWrite(system); free(system->default_print_group); system->default_print_group = value ? strdup(value) : NULL; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetDNSSDName()' - Set the DNS-SD service name. // // This function sets the DNS-SD service name of the system. If `NULL`, the // DNS-SD registration is removed. // void papplSystemSetDNSSDName( pappl_system_t *system, // I - System const char *value) // I - DNS-SD service name or `NULL` for none { if (system) { _papplRWLockWrite(system); free(system->dns_sd_name); system->dns_sd_name = value ? strdup(value) : NULL; system->dns_sd_collision = false; system->dns_sd_serial = 0; _papplSystemConfigChanged(system); if (!value) _papplSystemUnregisterDNSSDNoLock(system); else _papplSystemRegisterDNSSDNoLock(system); _papplRWUnlock(system); } } // // 'papplSystemSetEventCallback()' - Set a callback for monitoring system events. // // This function sets a callback function to receive event notifications from // the system. // void papplSystemSetEventCallback( pappl_system_t *system, // I - System pappl_event_cb_t event_cb, // I - Event callback function void *event_data) // I - Event callback data { if (system && event_cb) { _papplRWLockWrite(system); system->event_cb = event_cb; system->event_data = event_data; _papplRWUnlock(system); } } // // 'papplSystemSetFooterHTML()' - Set the footer HTML for the web interface. // // This function sets the footer HTML for the web interface. // // > Note: The footer HTML can only be set prior to calling // > @link papplSystemRun@. // void papplSystemSetFooterHTML( pappl_system_t *system, // I - System const char *html) // I - Footer HTML or `NULL` for none { if (system && html && !system->is_running) { free(system->footer_html); system->footer_html = strdup(html); } } // // 'papplSystemSetGeoLocation()' - Set the geographic location string. // // This function sets the geographic location of the system as a "geo:" URI. // If `NULL`, the location is cleared. // void papplSystemSetGeoLocation( pappl_system_t *system, // I - System const char *value) // I - "geo:" URI or `NULL` for none { float lat, lon; // Latitude and longitude from geo: URI // Validate geo-location - must be NULL or a "geo:" URI... if (value && *value && sscanf(value, "geo:%f,%f", &lat, &lon) != 2) return; if (system) { _papplRWLockWrite(system); free(system->geo_location); system->geo_location = value && *value ? strdup(value) : NULL; _papplSystemConfigChanged(system); _papplSystemRegisterDNSSDNoLock(system); _papplRWUnlock(system); } } // // 'papplSystemSetHostname()' - Set the system hostname. // // This function is deprecated. Use the @link papplSystemSetHostName@ function // instead. // // @deprecated@ @exclude all@ // void papplSystemSetHostname( pappl_system_t *system, // I - System const char *value) // I - Hostname or `NULL` for default { papplSystemSetHostName(system, value); } // // '_papplSystemSetHostNameNoLock()' - Set the system hostname without locking. // // This function sets the system hostname. If `NULL`, the default hostname // is used. // void _papplSystemSetHostNameNoLock( pappl_system_t *system, // I - System const char *value) // I - Hostname or `NULL` for default { char temp[1024], // Temporary hostname string *ptr; // Pointer in temporary hostname if (system->is_listenhost) return; if (value) { #if !defined(__APPLE__) && !_WIN32 cups_file_t *fp; // Hostname file if ((fp = cupsFileOpen("/etc/hostname", "w")) != NULL) { cupsFilePrintf(fp, "%s\n", value); cupsFileClose(fp); } #endif // !__APPLE__ && !_WIN32 #ifdef HAVE_AVAHI _pappl_dns_sd_t master = _papplDNSSDInit(system); // DNS-SD master reference if (master) avahi_client_set_host_name(master, value); #endif // HAVE_AVAHI #if !_WIN32 sethostname(value, (int)strlen(value)); #endif // !_WIN32 } else { _papplDNSSDCopyHostName(temp, sizeof(temp)); if ((ptr = strstr(temp, ".lan")) != NULL && !ptr[4]) { // Replace hostname.lan with hostname.local papplCopyString(ptr, ".local", sizeof(temp) - (size_t)(ptr - temp)); } else if (!strrchr(temp, '.')) { // No domain information, so append .local to hostname... ptr = temp + strlen(temp); papplCopyString(ptr, ".local", sizeof(temp) - (size_t)(ptr - temp)); } value = temp; } if (system->hostname && strcasecmp(system->hostname, value) && system->is_running) { // Force an update of all DNS-SD registrations... system->dns_sd_host_changes = -1; } // Save the new hostname value free(system->hostname); system->hostname = strdup(value); // Set the system TLS credentials... cupsSetServerCredentials(NULL, system->hostname, 1); } // // 'papplSystemSetHostName()' - Set the system hostname. // // This function sets the system hostname. If `NULL`, the default hostname // is used. // void papplSystemSetHostName( pappl_system_t *system, // I - System const char *value) // I - Hostname or `NULL` for default { if (system) { _papplRWLockWrite(system); _papplSystemSetHostNameNoLock(system, value); _papplRWUnlock(system); } } // // 'papplSystemSetLocation()' - Set the system location string, if any. // // This function sets the human-readable location of the system. If `NULL`, // the location is cleared. // void papplSystemSetLocation( pappl_system_t *system, // I - System const char *value) // I - Location or `NULL` for none { if (system) { _papplRWLockWrite(system); free(system->location); system->location = value ? strdup(value) : NULL; _papplSystemConfigChanged(system); _papplSystemRegisterDNSSDNoLock(system); _papplRWUnlock(system); } } // // 'papplSystemSetLogLevel()' - Set the system log level // // This function sets the log level as an enumeration. // void papplSystemSetLogLevel( pappl_system_t *system, // I - System pappl_loglevel_t loglevel) // I - Log Level { if (system) { pthread_mutex_lock(&system->log_mutex); system->log_level = loglevel; _papplSystemConfigChanged(system); pthread_mutex_unlock(&system->log_mutex); } } // // 'papplSystemSetMaxClients()' - Set the maximum number of clients. // // This function sets the maximum number of simultaneous clients that are // allowed by the system from 0 (auto) to 32768 (half of the available TCP // port numbers). // // The default maximum number of clients is based on available system resources. // void papplSystemSetMaxClients( pappl_system_t *system, // I - System int max_clients) // I - Maximum number of clients or `0` for auto { if (!system) return; if (max_clients <= 0) { // Determine the maximum number of clients to support... #ifdef _WIN32 max_clients = 100; // Use a default of 100... #else struct rlimit file_limits, // Current file descriptor limits mem_limits; // Current memory limits max_clients = 100; // Use a default of 100... if (!getrlimit(RLIMIT_NOFILE, &file_limits) && !getrlimit(RLIMIT_DATA, &mem_limits)) { // Calculate a maximum number of clients... int max_files, max_mem; // Maximum files and memory if (file_limits.rlim_cur != file_limits.rlim_max && file_limits.rlim_cur < 65536) { // Try increasing the limit to the maximum allowed... if (file_limits.rlim_max > 65536) file_limits.rlim_cur = 65536; else file_limits.rlim_cur = file_limits.rlim_max; if (setrlimit(RLIMIT_NOFILE, &file_limits)) getrlimit(RLIMIT_NOFILE, &file_limits); } // Max clients based on file descriptors is 1/2 the limit... if (file_limits.rlim_cur == RLIM_INFINITY) max_files = 32768; else max_files = (int)(file_limits.rlim_cur / 2); // Max clients based on memory is 1/64k the limit... if (mem_limits.rlim_cur == RLIM_INFINITY) max_mem = 32768; else max_mem = (int)(mem_limits.rlim_cur / 65536); // Use min(max_files,max_mem)... if (max_files > max_mem) max_clients = max_mem; else max_clients = max_files; } #endif // _WIN32 } // Restrict max_clients to <= 32768... if (max_clients > 32768) max_clients = 32768; // Set the new value... _papplRWLockWrite(system); system->max_clients = max_clients; _papplSystemConfigChanged(system); _papplRWUnlock(system); } // // 'papplSystemSetMaxImageSize()' - Set the maximum allowed JPEG/PNG image sizes. // // This function sets the maximum size allowed for JPEG and PNG images. The // default limits are 16384x16384 and 1/10th the maximum memory the current // process can use or 1GiB, whichever is less. // void papplSystemSetMaxImageSize( pappl_system_t *system, // I - System size_t max_size, // I - Maximum image size (uncompressed) or `0` for default int max_width, // I - Maximum image width in columns or `0` for default int max_height) // I - Maximum image height in lines or `0` for default { // Range check input... if (!system || max_width < 0 || max_height < 0) return; if (max_size == 0) { // By default, limit images to 1/10th available memory... #if _WIN32 MEMORYSTATUSEX statex; // Memory status if (GlobalMemoryStatusEx(&statex)) max_size = (size_t)statex.ullTotalPhys / 10; else max_size = 16 * 1024 * 1024; #else struct rlimit limit; // Memory limits if (getrlimit(RLIMIT_DATA, &limit)) max_size = 16 * 1024 * 1024; else max_size = limit.rlim_cur / 10; #endif // _WIN32 } // Don't allow overlarge limits... if (max_size > (1024 * 1024 * 1024)) // Max 1GB total size max_size = 1024 * 1024 * 1024; if (max_width > 65535) // Max 65535 wide max_width = 65535; if (max_height > 65535) // Max 65535 high max_height = 65535; // Update values _papplRWLockWrite(system); system->max_image_size = max_size; system->max_image_width = max_width == 0 ? 16384 : max_width; system->max_image_height = max_height == 0 ? 16384 : max_height; _papplSystemConfigChanged(system); _papplRWUnlock(system); } // // 'papplSystemSetMaxLogSize()' - Set the maximum log file size in bytes. // // This function sets the maximum log file size in bytes, which is only used // when logging directly to a file. When the limit is reached, the current log // file is renamed to "filename.O" and a new log file is created. Set the // maximum size to `0` to disable log file rotation. // // The default maximum log file size is 1MiB or `1048576` bytes. // void papplSystemSetMaxLogSize( pappl_system_t *system, // I - System size_t maxsize) // I - Maximum log size in bytes or `0` for none { if (system) { pthread_mutex_lock(&system->log_mutex); system->log_max_size = maxsize; _papplSystemConfigChanged(system); pthread_mutex_unlock(&system->log_mutex); } } // // 'papplSystemSetMaxSubscriptions()' - Set the maximum number of event subscriptions. // // This function Sets the maximum number of event subscriptions that are // allowed. A maximum of `0` means there is no limit. // // The default maximum number of event subscriptions is `100`. // void papplSystemSetMaxSubscriptions( pappl_system_t *system, // I - System size_t max_subscriptions) // I - Maximum number of subscriptions or `0` for no limit { if (system) { _papplRWLockWrite(system); system->max_subscriptions = max_subscriptions; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetMIMECallback()' - Set the MIME typing callback for the system. // // This function sets a custom MIME typing callback for the system. The MIME // typing callback extends the built-in MIME typing support for other media // types that are supported by the application, typically vendor print formats. // // The callback function receives a buffer containing the initial bytes of the // document data, the length of the buffer, and the callback data. It can then // return `NULL` if the content is not recognized or a constant string // containing the MIME media type, for example "application/vnd.hp-pcl" for // HP PCL print data. // void papplSystemSetMIMECallback( pappl_system_t *system, // I - System pappl_mime_cb_t cb, // I - Callback function void *data) // I - Callback data { if (system) { _papplRWLockWrite(system); system->mime_cb = cb; system->mime_cbdata = data; _papplRWUnlock(system); } } // // 'papplSystemSetNetworkCallbacks()' - Set the network configuration callbacks. // // This function sets the network configuration callbacks for a system. The // "get" callback reads the configuration of all network interfaces and stores // them in an array of @link pappl_network_t@ structures that is passed to the // callback. The "set" callback writes the configuration of all network // interfaces and returns a boolean value indicating whether the configuration // has been written successfully. // void papplSystemSetNetworkCallbacks( pappl_system_t *system, // I - System pappl_network_get_cb_t get_cb, // I - "Get networks" callback pappl_network_set_cb_t set_cb, // I - "Set networks" callback void *cb_data) // I - Callback data { // Range check input... if (system && (get_cb != NULL) == (set_cb != NULL)) { _papplRWLockWrite(system); system->network_get_cb = get_cb; system->network_set_cb = set_cb; system->network_cbdata = cb_data; _papplRWUnlock(system); } } // // 'papplSystemSetNextPrinterID()' - Set the next "printer-id" value. // // This function sets the unique positive integer identifier that will be used // for the next printer that is created. It is typically only called as part // of restoring the state of a system. // // > Note: The next printer ID can only be set prior to calling // > @link papplSystemRun@. // void papplSystemSetNextPrinterID( pappl_system_t *system, // I - System int next_printer_id) // I - Next "printer-id" value { if (system && !system->is_running) { _papplRWLockWrite(system); system->next_printer_id = next_printer_id; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetOperationCallback()' - Set the IPP operation callback. // // This function sets a custom IPP operation handler for the system that is // called for any IPP operations that are not handled by the built-in IPP // services. // // > Note: The operation callback can only be set prior to calling // > @link papplSystemRun@. // void papplSystemSetOperationCallback( pappl_system_t *system, // I - System pappl_ipp_op_cb_t cb, // I - Callback function void *data) // I - Callback data { if (system && !system->is_running) { _papplRWLockWrite(system); system->op_cb = cb; system->op_cbdata = data; _papplRWUnlock(system); } } // // 'papplSystemSetOrganization()' - Set the system organization string, if any. // // This function sets the organization name for the system. If `NULL`, the // name is cleared. // void papplSystemSetOrganization( pappl_system_t *system, // I - System const char *value) // I - Organization or `NULL` for none { if (system) { _papplRWLockWrite(system); free(system->organization); system->organization = value ? strdup(value) : NULL; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetOrganizationalUnit()' - Set the system organizational unit // string, if any. // // This function sets the organizational unit name for the system. If `NULL`, // the name is cleared. // void papplSystemSetOrganizationalUnit( pappl_system_t *system, // I - System const char *value) // I - Organizational unit or `NULL` for none { if (system) { _papplRWLockWrite(system); free(system->org_unit); system->org_unit = value ? strdup(value) : NULL; _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetPassword()' - Set the access password hash string. // // This function sets the hash for the web access password. The hash string is // generated using the @link papplSystemHashPassword@ function. // // > Note: The access password is only used when the PAM authentication service // > is not set. // void papplSystemSetPassword( pappl_system_t *system, // I - System const char *hash) // I - Hash string { if (system && hash) { _papplRWLockWrite(system); papplCopyString(system->password_hash, hash, sizeof(system->password_hash)); _papplSystemConfigChanged(system); _papplRWUnlock(system); } } // // 'papplSystemSetPrinterDrivers()' - Set the list of drivers and the driver // callbacks. // // This function sets the lists of printer drivers, the optional auto-add // callback function, the optional creation callback, and the required driver // initialization callback function. // // The auto-add callback ("autoadd_cb") finds a compatible driver name for the // specified printer. It is used when the client or user specifies the "auto" // driver name, and for the "autoadd" sub-command for the `papplMainloop` API. // // The creation callback ("create_cb") is called at the end of printer creation // to make any common changes or additions to a new printer. It is typically // used to add extra web pages, add per-printer static resources, and/or // initialize the contact and location information. // // The driver initialization callback ("driver_cb") is called to initialize the // `pappl_pr_driver_data_t` structure, which provides all of the printer // capabilities and callbacks for printing. // void papplSystemSetPrinterDrivers( pappl_system_t *system, // I - System int num_drivers, // I - Number of drivers pappl_pr_driver_t *drivers, // I - Drivers pappl_pr_autoadd_cb_t autoadd_cb, // I - Auto-add callback function or `NULL` if none pappl_pr_create_cb_t create_cb, // I - Printer creation callback function or `NULL` if none pappl_pr_driver_cb_t driver_cb, // I - Driver initialization callback function void *data) // I - Callback data { if (system) { _papplRWLockWrite(system); system->num_drivers = (cups_len_t)num_drivers; system->drivers = drivers; system->autoadd_cb = autoadd_cb; system->create_cb = create_cb; system->driver_cb = driver_cb; system->driver_cbdata = data; _papplRWUnlock(system); } } // // 'papplSystemSetSaveCallback()' - Set the save callback. // // This function sets a callback that is used to periodically save the current // system state. Typically the callback function ("cb") is // @link papplSystemSaveState@ and the callback data ("data") is the name of // the state file: // // ``` // |papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, // | (void *)filename); // ``` // // > Note: The save callback can only be set prior to calling // > @link papplSystemRun@. // void papplSystemSetSaveCallback( pappl_system_t *system, // I - System pappl_save_cb_t cb, // I - Callback function void *data) // I - Callback data { if (system && !system->is_running) { _papplRWLockWrite(system); system->save_cb = cb; system->save_cbdata = data; _papplRWUnlock(system); } } // // 'papplSystemSetUUID()' - Set the system UUID. // // This function sets the system UUID value, overriding the default (generated) // value. It is typically used when restoring the state of a previous // incarnation of the system. // // > Note: The UUID can only be set prior to calling @link papplSystemRun@. // void papplSystemSetUUID( pappl_system_t *system, // I - System const char *value) // I - UUID { if (system && !system->is_running) { _papplRWLockWrite(system); free(system->uuid); if (value) { system->uuid = strdup(value); } else { char uuid[64]; // UUID value _papplSystemMakeUUID(system, NULL, 0, uuid, sizeof(uuid)); system->uuid = strdup(uuid); } _papplSystemRegisterDNSSDNoLock(system); _papplRWUnlock(system); } } // // 'papplSystemSetVersions()' - Set the firmware names and versions. // // This function sets the names and versions of each firmware/software component // of the printer application. // void papplSystemSetVersions( pappl_system_t *system, // I - System int num_versions, // I - Number of versions pappl_version_t *versions) // I - Firmware versions { if (system && num_versions && versions) { _papplRWLockWrite(system); if (num_versions > (int)(sizeof(system->versions) / sizeof(system->versions[0]))) system->num_versions = sizeof(system->versions) / sizeof(system->versions[0]); else system->num_versions = (cups_len_t)num_versions; memcpy(system->versions, versions, (size_t)system->num_versions * sizeof(pappl_version_t)); _papplRWUnlock(system); } } // // 'papplSystemSetWiFiCallbacks()' - Set Wi-Fi callbacks. // // This function sets the 802.11 Wi-Fi interface callbacks for the system. The // "join_cb" is used to join a Wi-Fi network, the "list_cb" is used to list // available networks, and the "status_cb" is used to query the current Wi-Fi // network connection status and Secure Set Identifier (SSID). The "join_cb" // and "status_cb" functions are used to support getting and setting the IPP // "printer-wifi-state", "printer-wifi-ssid", and "printer-wifi-password" // attributes, while the "list_cb" function enables changing the Wi-Fi network // from the network web interface, if enabled. // // Note: The Wi-Fi callbacks can only be set prior to calling // @link papplSystemRun@. // void papplSystemSetWiFiCallbacks( pappl_system_t *system, // I - System pappl_wifi_join_cb_t join_cb, // I - Join callback pappl_wifi_list_cb_t list_cb, // I - List callback pappl_wifi_status_cb_t status_cb, // I - Status callback void *data) // I - Callback data pointer { if (system && !system->is_running && join_cb && status_cb) { _papplRWLockWrite(system); system->wifi_join_cb = join_cb; system->wifi_list_cb = list_cb; system->wifi_status_cb = status_cb; system->wifi_cbdata = data; _papplRWUnlock(system); } } // // 'add_listeners()' - Create and add listener sockets to a system. // static bool // O - `true` on success or `false` on failure add_listeners( pappl_system_t *system, // I - System const char *name, // I - Host name or `NULL` for any address int port, // I - Port number int family) // I - Address family { bool ret = false; // Return value int sock; // Listener socket http_addrlist_t *addrlist, // Listen addresses *addr; // Current address char service[255]; // Service port if (name && (!strcmp(name, "*") || !*name)) name = NULL; snprintf(service, sizeof(service), "%d", port); if ((addrlist = httpAddrGetList(name, family, service)) == NULL) { if (name && *name == '/') papplLog(system, PAPPL_LOGLEVEL_INFO, "Unable to lookup address(es) for '%s': %s", name, cupsGetErrorString()); else papplLog(system, PAPPL_LOGLEVEL_INFO, "Unable to lookup address(es) for '%s:%d': %s", name ? name : "*", port, cupsGetErrorString()); } else { for (addr = addrlist; addr && system->num_listeners < _PAPPL_MAX_LISTENERS; addr = addr->next) { if ((sock = httpAddrListen(&(addrlist->addr), port)) < 0) { char temp[256]; // String address if (system->port) { if (name && *name == '/') papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create listener socket for '%s': %s", name, cupsGetErrorString()); else papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create listener socket for '%s:%d': %s", httpAddrGetString(&addr->addr, temp, (cups_len_t)sizeof(temp)), system->port, cupsGetErrorString()); } } else { ret = true; system->listeners[system->num_listeners].fd = sock; system->listeners[system->num_listeners ++].events = POLLIN; if (name && *name == '/') papplLog(system, PAPPL_LOGLEVEL_INFO, "Listening for connections on '%s'.", name); else papplLog(system, PAPPL_LOGLEVEL_INFO, "Listening for connections on '%s:%d'.", name ? name : "*", port); } } httpAddrFreeList(addrlist); } return (ret); } // // 'compare_filters()' - Compare two filters. // static int // O - Result of comparison compare_filters(_pappl_mime_filter_t *a,// I - First filter _pappl_mime_filter_t *b)// I - Second filter { int result = strcmp(a->src, b->src); if (!result) result = strcmp(a->dst, b->dst); return (result); } // // 'compare_timers()' - Compare two timers. // static int // O - Result of comparison compare_timers(_pappl_timer_t *a, // I - First timer _pappl_timer_t *b) // I - Second timer { if (a->next < b->next) return (-1); else if (a->next > b->next) return (1); else if (a < b) return (-1); else if (a > b) return (1); else return (0); } // // 'copy_filter()' - Copy a filter definition. // static _pappl_mime_filter_t * // O - New filter copy_filter(_pappl_mime_filter_t *f) // I - Filter definition { _pappl_mime_filter_t *newf = calloc(1, sizeof(_pappl_mime_filter_t)); // New filter if (newf) memcpy(newf, f, sizeof(_pappl_mime_filter_t)); return (newf); } pappl-1.4.9/pappl/system-ipp.c000066400000000000000000001126431476704353100162540ustar00rootroot00000000000000// // IPP processing for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // Local type... // typedef struct _pappl_attr_s // Input attribute structure { const char *name; // Attribute name ipp_tag_t value_tag; // Value tag cups_len_t max_count; // Max number of values } _pappl_attr_t; typedef struct _pappl_create_s // Printer creation callback data { pappl_client_t *client; // Client connection cups_array_t *ra; // "requested-attributes" array } _pappl_create_t; // // Local functions... // static void ipp_create_printer(pappl_client_t *client); static void ipp_create_printers(pappl_client_t *client); static void ipp_delete_printer(pappl_client_t *client); static void ipp_disable_all_printers(pappl_client_t *client); static void ipp_enable_all_printers(pappl_client_t *client); static void ipp_find_devices(pappl_client_t *client); static void ipp_find_drivers(pappl_client_t *client); static void ipp_get_printers(pappl_client_t *client); static void ipp_get_system_attributes(pappl_client_t *client); static void ipp_pause_all_printers(pappl_client_t *client); static void ipp_resume_all_printers(pappl_client_t *client); static void ipp_set_system_attributes(pappl_client_t *client); static void ipp_shutdown_all_printers(pappl_client_t *client); static void printer_create_cb(pappl_printer_t *printer, _pappl_create_t *data); // // '_papplSystemProcessIPP()' - Process an IPP System request. // void _papplSystemProcessIPP( pappl_client_t *client) // I - Client { switch ((int)ippGetOperation(client->request)) { case IPP_OP_CREATE_PRINTER : ipp_create_printer(client); break; case IPP_OP_DELETE_PRINTER : ipp_delete_printer(client); break; case IPP_OP_GET_PRINTERS : case IPP_OP_CUPS_GET_PRINTERS : ipp_get_printers(client); break; case IPP_OP_GET_PRINTER_ATTRIBUTES : case IPP_OP_CUPS_GET_DEFAULT : client->printer = papplSystemFindPrinter(client->system, NULL, client->system->default_printer_id, NULL); _papplPrinterProcessIPP(client); break; case IPP_OP_GET_SYSTEM_ATTRIBUTES : ipp_get_system_attributes(client); break; case IPP_OP_SET_SYSTEM_ATTRIBUTES : ipp_set_system_attributes(client); break; case IPP_OP_DISABLE_ALL_PRINTERS : ipp_disable_all_printers(client); break; case IPP_OP_ENABLE_ALL_PRINTERS : ipp_enable_all_printers(client); break; case IPP_OP_PAUSE_ALL_PRINTERS : case IPP_OP_PAUSE_ALL_PRINTERS_AFTER_CURRENT_JOB : ipp_pause_all_printers(client); break; case IPP_OP_RESUME_ALL_PRINTERS : ipp_resume_all_printers(client); break; case IPP_OP_SHUTDOWN_ALL_PRINTERS : ipp_shutdown_all_printers(client); break; case IPP_OP_CREATE_SYSTEM_SUBSCRIPTIONS : _papplSubscriptionIPPCreate(client); break; case IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES : _papplSubscriptionIPPGetAttributes(client); break; case IPP_OP_GET_SUBSCRIPTIONS : _papplSubscriptionIPPList(client); break; case IPP_OP_RENEW_SUBSCRIPTION : _papplSubscriptionIPPRenew(client); break; case IPP_OP_CANCEL_SUBSCRIPTION : _papplSubscriptionIPPCancel(client); break; case IPP_OP_GET_NOTIFICATIONS : _papplSubscriptionIPPGetNotifications(client); break; case IPP_OP_PAPPL_CREATE_PRINTERS : ipp_create_printers(client); break; case IPP_OP_PAPPL_FIND_DEVICES : ipp_find_devices(client); break; case IPP_OP_PAPPL_FIND_DRIVERS : ipp_find_drivers(client); break; default : if (client->system->op_cb && (client->system->op_cb)(client, client->system->op_cbdata)) break; papplClientRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } } // // 'ipp_create_printer()' - Create a printer. // static void ipp_create_printer( pappl_client_t *client) // I - Client { const char *printer_name, // Printer name *device_id, // Device ID *device_uri, // Device URI *driver_name; // Name of driver ipp_attribute_t *attr; // Current attribute pappl_printer_t *printer; // Printer cups_array_t *ra; // Requested attributes http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Is the system configured to support multiple printers? if (!(client->system->options & PAPPL_SOPTIONS_MULTI_QUEUE)) { papplClientRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "This operation is not supported."); return; } // Get required attributes... if ((attr = ippFindAttribute(client->request, "printer-service-type", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'printer-service-type' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetCount(attr) != 1 || strcmp(ippGetString(attr, 0, NULL), "print")) { papplClientRespondIPPUnsupported(client, attr); return; } if ((attr = ippFindAttribute(client->request, "printer-name", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'printer-name' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG) || ippGetCount(attr) != 1 || strlen(ippGetString(attr, 0, NULL)) > 127) { papplClientRespondIPPUnsupported(client, attr); return; } else printer_name = ippGetString(attr, 0, NULL); if ((attr = ippFindAttribute(client->request, "printer-device-id", IPP_TAG_ZERO)) != NULL && (ippGetGroupTag(attr) != IPP_TAG_PRINTER || ippGetValueTag(attr) != IPP_TAG_TEXT || ippGetCount(attr) != 1)) { papplClientRespondIPPUnsupported(client, attr); return; } else device_id = ippGetString(attr, 0, NULL); if ((attr = ippFindAttribute(client->request, "smi55357-device-uri", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'smi55357-device-uri' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_URI || ippGetCount(attr) != 1) { papplClientRespondIPPUnsupported(client, attr); return; } else { device_uri = ippGetString(attr, 0, NULL); if (!papplDeviceIsSupported(device_uri)) { papplClientRespondIPPUnsupported(client, attr); return; } } if ((attr = ippFindAttribute(client->request, "smi55357-driver", IPP_TAG_ZERO)) == NULL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'smi55357-driver' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetCount(attr) != 1) { papplClientRespondIPPUnsupported(client, attr); return; } else if (client->system->driver_cb) { driver_name = ippGetString(attr, 0, NULL); } else { papplLog(client->system, PAPPL_LOGLEVEL_ERROR, "No driver callback set, unable to add printer."); papplClientRespondIPPUnsupported(client, attr); return; } // Create the printer... if ((printer = papplPrinterCreate(client->system, 0, printer_name, driver_name, device_id, device_uri)) == NULL) { if (errno == EEXIST) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Printer name '%s' already exists.", printer_name); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_NAME, "printer-name", NULL, printer_name); } else if (errno == EIO) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Driver '%s' cannot be used with this printer.", driver_name); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, "smi55357-driver", NULL, driver_name); } else if (errno == EINVAL) { papplClientRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Printer names must start with a letter or underscore and cannot contain special characters."); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_NAME, "printer-name", NULL, printer_name); } else { papplClientRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "An error occurred when adding the printer: %s.", strerror(errno)); } return; } if (!_papplPrinterSetAttributes(client, printer)) return; // Return the printer papplClientRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL); cupsArrayAdd(ra, "printer-id"); cupsArrayAdd(ra, "printer-is-accepting-jobs"); cupsArrayAdd(ra, "printer-state"); cupsArrayAdd(ra, "printer-state-reasons"); cupsArrayAdd(ra, "printer-uuid"); cupsArrayAdd(ra, "printer-xri-supported"); _papplRWLockRead(printer->system); _papplRWLockRead(printer); _papplPrinterCopyAttributesNoLock(printer, client, ra, NULL); _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); _papplRWUnlock(printer->system); cupsArrayDelete(ra); } // // 'ipp_create_printers()' - Auto-add newly discovered printers. // static void ipp_create_printers( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status ipp_attribute_t *type_attr; // "smi55357-device-type" attribute cups_len_t i, // Looping var count; // Number of values pappl_devtype_t types; // Device types _pappl_create_t data; // Callback data // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Get the device type bits... if ((type_attr = ippFindAttribute(client->request, "smi55357-device-type", IPP_TAG_KEYWORD)) != NULL) { for (types = (pappl_devtype_t)0, i = 0, count = ippGetCount(type_attr); i < count; i ++) { const char *type = ippGetString(type_attr, i, NULL); // Current type keyword if (!strcmp(type, "all")) { types = PAPPL_DEVTYPE_ALL; break; } else if (!strcmp(type, "dns-sd")) { types |= PAPPL_DEVTYPE_DNS_SD; } else if (!strcmp(type, "local")) { types |= PAPPL_DEVTYPE_LOCAL; } else if (!strcmp(type, "network")) { types |= PAPPL_DEVTYPE_NETWORK; } else if (!strcmp(type, "other-local")) { types |= PAPPL_DEVTYPE_CUSTOM_LOCAL; } else if (!strcmp(type, "other-network")) { types |= PAPPL_DEVTYPE_CUSTOM_NETWORK; } else if (!strcmp(type, "snmp")) { types |= PAPPL_DEVTYPE_SNMP; } else if (!strcmp(type, "usb")) { types |= PAPPL_DEVTYPE_USB; } else { papplClientRespondIPPUnsupported(client, type_attr); return; } } } else { // Report all devices... types = PAPPL_DEVTYPE_ALL; } // List all devices data.client = client; data.ra = NULL; if (!papplSystemCreatePrinters(client->system, types, (pappl_pr_create_cb_t)printer_create_cb, &data)) papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No devices found."); cupsArrayDelete(data.ra); } // // 'ipp_delete_printer()' - Delete a printer. // static void ipp_delete_printer( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } if (!client->printer) { papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Printer not found."); return; } _papplRWLockWrite(client->printer); if (!client->printer->processing_job) { // Not busy, delete immediately... _papplRWUnlock(client->printer); papplPrinterDelete(client->printer); } else { // Busy, delete when current job is completed... client->printer->is_deleted = true; _papplRWUnlock(client->printer); } papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_disable_all_printers()' - Disable all printers. // static void ipp_disable_all_printers( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System pappl_printer_t *printer; // Current printer http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Loop through the printers... _papplRWLockRead(system); for (printer = (pappl_printer_t *)cupsArrayGetFirst(system->printers); printer; printer = (pappl_printer_t *)cupsArrayGetNext(system->printers)) { papplPrinterDisable(printer); } _papplRWUnlock(system); } // // 'ipp_enable_all_printers()' - Enable all printers. // static void ipp_enable_all_printers( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System pappl_printer_t *printer; // Current printer http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Loop through the printers... _papplRWLockRead(system); for (printer = (pappl_printer_t *)cupsArrayGetFirst(system->printers); printer; printer = (pappl_printer_t *)cupsArrayGetNext(system->printers)) { papplPrinterEnable(printer); } _papplRWUnlock(system); } // // 'ipp_find_devices()' - Find devices. // static void ipp_find_devices( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status ipp_attribute_t *type_attr; // "smi55357-device-type" attribute cups_len_t i, // Looping var count; // Number of values pappl_devtype_t types; // Device types cups_array_t *devices; // Device array _pappl_dinfo_t *d; // Current device information // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Get the device type bits... if ((type_attr = ippFindAttribute(client->request, "smi55357-device-type", IPP_TAG_KEYWORD)) != NULL) { for (types = (pappl_devtype_t)0, i = 0, count = ippGetCount(type_attr); i < count; i ++) { const char *type = ippGetString(type_attr, i, NULL); // Current type keyword if (!strcmp(type, "all")) { types = PAPPL_DEVTYPE_ALL; break; } else if (!strcmp(type, "dns-sd")) { types |= PAPPL_DEVTYPE_DNS_SD; } else if (!strcmp(type, "local")) { types |= PAPPL_DEVTYPE_LOCAL; } else if (!strcmp(type, "network")) { types |= PAPPL_DEVTYPE_NETWORK; } else if (!strcmp(type, "other-local")) { types |= PAPPL_DEVTYPE_CUSTOM_LOCAL; } else if (!strcmp(type, "other-network")) { types |= PAPPL_DEVTYPE_CUSTOM_NETWORK; } else if (!strcmp(type, "snmp")) { types |= PAPPL_DEVTYPE_SNMP; } else if (!strcmp(type, "usb")) { types |= PAPPL_DEVTYPE_USB; } else { papplClientRespondIPPUnsupported(client, type_attr); return; } } } else { // Report all devices... types = PAPPL_DEVTYPE_ALL; } // List all devices papplClientRespondIPP(client, IPP_STATUS_OK, NULL); devices = _papplDeviceInfoCreateArray(); papplDeviceList(types, (pappl_device_cb_t)_papplDeviceInfoCallback, devices, papplLogDevice, client->system); if (cupsArrayGetCount(devices) == 0) { // No devices... papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No devices found."); } else { // Respond with collection attribute... ipp_attribute_t *device_col = NULL; // smi55357-device-col attribute papplClientRespondIPP(client, IPP_STATUS_OK, NULL); for (d = (_pappl_dinfo_t *)cupsArrayGetFirst(devices); d; d = (_pappl_dinfo_t *)cupsArrayGetNext(devices)) { ipp_t *col; // Collection value // Create a new collection value for "smi55357-device-col"... col = ippNew(); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_TEXT, "smi55357-device-id", NULL, d->device_id); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_TEXT, "smi55357-device-info", NULL, d->device_info); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_URI, "smi55357-device-uri", NULL, d->device_uri); // Add or update the attribute... if (device_col) ippSetCollection(client->response, &device_col, ippGetCount(device_col), col); else device_col = ippAddCollection(client->response, IPP_TAG_SYSTEM, "smi55357-device-col", col); ippDelete(col); } } cupsArrayDelete(devices); } // // 'ipp_find_drivers()' - Find drivers. // static void ipp_find_drivers( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status const char *device_id; // Device ID cups_len_t num_dids = 0; // Number of key/value pairs cups_option_t *dids = NULL; // Device ID key/value pairs const char *driver_name = NULL, // Matching driver name, if any *cmd = NULL, // Command set from device ID *make = NULL, // Make from device ID *model = NULL; // Model from device ID cups_len_t i; // Looping var pappl_pr_driver_t *driver; // Current driver ipp_attribute_t *driver_col = NULL; // Collection for drivers ipp_t *col; // Collection value // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Assemble a list of drivers... papplClientRespondIPP(client, IPP_STATUS_OK, NULL); // See if the Client provided a device ID to match... if ((device_id = ippGetString(ippFindAttribute(client->request, "smi55357-device-id", IPP_TAG_TEXT), 0, NULL)) != NULL) { // Yes, filter based on device ID... if (client->system->autoadd_cb) { // Filter using the auto-add callback... if ((driver_name = (client->system->autoadd_cb)(NULL, NULL, device_id, client->system->driver_cbdata)) == NULL) { // No matching driver... papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No matching driver found."); return; } } else { // Filter using device ID matching... num_dids = papplDeviceParseID(device_id, &dids); if ((cmd = cupsGetOption("COMMAND SET", num_dids, dids)) == NULL) cmd = cupsGetOption("CMD", num_dids, dids); if ((make = cupsGetOption("MANUFACTURER", num_dids, dids)) == NULL) make = cupsGetOption("MFG", num_dids, dids); if ((model = cupsGetOption("MODEL", num_dids, dids)) == NULL) model = cupsGetOption("MDL", num_dids, dids); } } for (i = client->system->num_drivers, driver = client->system->drivers; i > 0; i --, driver ++) { if (driver_name) { // Compare driver name... if (strcmp(driver_name, driver->name)) continue; } else if (num_dids > 0) { // Compare device ID values... cups_len_t num_dids2; // Number of device ID key/value pairs cups_option_t *dids2; // Device ID key/value pairs const char *cmd2, // Command set from device ID *make2, // Make from device ID *model2; // Model from device ID bool match = true; // Do we have a match? num_dids2 = papplDeviceParseID(driver->device_id, &dids2); if ((cmd2 = cupsGetOption("COMMAND SET", num_dids2, dids2)) == NULL) cmd2 = cupsGetOption("CMD", num_dids2, dids2); if (cmd && cmd2 && !strstr(cmd, cmd2)) match = false; if ((make2 = cupsGetOption("MANUFACTURER", num_dids2, dids2)) == NULL) make2 = cupsGetOption("MFG", num_dids2, dids2); if (make && make2 && strcmp(make, make2)) match = false; if ((model2 = cupsGetOption("MODEL", num_dids2, dids2)) == NULL) model2 = cupsGetOption("MDL", num_dids2, dids2); if (model && model2 && strcmp(model, model2)) match = false; cupsFreeOptions(num_dids2, dids2); if (!match) continue; } // Create a collection for the driver values... col = ippNew(); if (driver->device_id) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_TEXT, "smi55357-device-id", NULL, driver->device_id); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "smi55357-driver", NULL, driver->name); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_TEXT, "smi55357-driver-info", NULL, driver->description); if (driver_col) ippSetCollection(client->response, &driver_col, ippGetCount(driver_col), col); else driver_col = ippAddCollection(client->response, IPP_TAG_SYSTEM, "smi55357-driver-col", col); ippDelete(col); } cupsFreeOptions(num_dids, dids); if (!driver_col) papplClientRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "No matching drivers found."); } // // 'ipp_get_printers()' - Get printers. // static void ipp_get_printers( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System cups_array_t *ra; // Requested attributes array cups_len_t i, // Looping var count, // Number of printers limit; // Maximum number to return pappl_printer_t *printer; // Current printer const char *format; // "document-format" value, if any // Get request attributes... limit = (cups_len_t)ippGetInteger(ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER), 0); ra = ippCreateRequestedArray(client->request); format = ippGetString(ippFindAttribute(client->request, "document-format", IPP_TAG_MIMETYPE), 0, NULL); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(system); // Enumerate the printers for the client... count = cupsArrayGetCount(system->printers); if (limit > 0 && limit < count) count = limit; for (i = 0; i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (limit && i >= limit) break; if (i) ippAddSeparator(client->response); _papplRWLockRead(printer); _papplPrinterCopyAttributesNoLock(printer, client, ra, format); _papplRWUnlock(printer); } _papplRWUnlock(system); cupsArrayDelete(ra); } // // 'ipp_get_system_attributes()' - Get system attributes. // static void ipp_get_system_attributes( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System cups_array_t *ra; // Requested attributes array cups_len_t i, // Looping var count; // Count of values pappl_printer_t *printer; // Current printer ipp_attribute_t *attr; // Current attribute ipp_t *col; // configured-printers value time_t config_time = system->config_time; // system-config-change-[date-]time value time_t state_time = 0; // system-state-change-[date-]time value ra = ippCreateRequestedArray(client->request); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); _papplRWLockRead(system); _papplCopyAttributes(client->response, system->attrs, ra, IPP_TAG_ZERO, true); if (!ra || cupsArrayFind(ra, "system-config-change-date-time") || cupsArrayFind(ra, "system-config-change-time")) { for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (config_time < printer->config_time) config_time = printer->config_time; } if (!ra || cupsArrayFind(ra, "system-config-change-date-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-config-change-date-time", ippTimeToDate(config_time)); if (!ra || cupsArrayFind(ra, "system-config-change-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-config-change-time", (int)(config_time - system->start_time)); } if (!ra || cupsArrayFind(ra, "system-configured-printers")) { attr = ippAddCollections(client->response, IPP_TAG_SYSTEM, "system-configured-printers", IPP_NUM_CAST cupsArrayGetCount(system->printers), NULL); for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); col = ippNew(); _papplRWLockRead(printer); ippAddInteger(col, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "printer-id", printer->printer_id); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "printer-info", NULL, printer->name); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "printer-name", NULL, printer->name); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_KEYWORD, "printer-service-type", NULL, "print"); _papplPrinterCopyStateNoLock(printer, IPP_TAG_PRINTER, col, client, NULL); _papplPrinterCopyXRINoLock(printer, col, client); _papplRWUnlock(printer); ippSetCollection(client->response, &attr, IPP_NUM_CAST i, col); ippDelete(col); } } if (!ra || cupsArrayFind(ra, "system-contact-col")) { col = _papplContactExport(&system->contact); ippAddCollection(client->response, IPP_TAG_SYSTEM, "system-contact-col", col); ippDelete(col); } if (!ra || cupsArrayFind(ra, "system-current-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-current-time", ippTimeToDate(time(NULL))); if (!ra || cupsArrayFind(ra, "system-default-printer-id")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-default-printer-id", system->default_printer_id); _papplSystemExportVersions(system, client->response, IPP_TAG_SYSTEM, ra); if (!ra || cupsArrayFind(ra, "system-geo-location")) { if (system->geo_location) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_URI, "system-geo-location", NULL, system->geo_location); else ippAddOutOfBand(client->response, IPP_TAG_SYSTEM, IPP_TAG_UNKNOWN, "system-geo-location"); } if (!ra || cupsArrayFind(ra, "system-location")) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "system-location", NULL, system->location ? system->location : ""); if (!ra || cupsArrayFind(ra, "system-name")) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_NAME, "system-name", NULL, system->name); if (!ra || cupsArrayFind(ra, "system-organization")) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "system-organization", NULL, system->organization ? system->organization : ""); if (!ra || cupsArrayFind(ra, "system-organizational-unit")) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "system-organizational-unit", NULL, system->org_unit ? system->org_unit : ""); if (!ra || cupsArrayFind(ra, "system-state")) { int state = IPP_PSTATE_IDLE; // System state for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (printer->state == IPP_PSTATE_PROCESSING) { state = IPP_PSTATE_PROCESSING; break; } } ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_ENUM, "system-state", state); } if (!ra || cupsArrayFind(ra, "system-state-change-date-time") || cupsArrayFind(ra, "system-state-change-time")) { for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (state_time < printer->state_time) state_time = printer->state_time; } if (!ra || cupsArrayFind(ra, "system-state-change-date-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-state-change-date-time", ippTimeToDate(state_time)); if (!ra || cupsArrayFind(ra, "system-state-change-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-state-change-time", (int)(state_time - system->start_time)); } if (!ra || cupsArrayFind(ra, "system-state-reasons")) { pappl_preason_t state_reasons = PAPPL_PREASON_NONE; for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); state_reasons |= printer->state_reasons; } if (state_reasons == PAPPL_PREASON_NONE) { ippAddString(client->response, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "system-state-reasons", NULL, "none"); } else { pappl_preason_t bit; // Reason bit for (attr = NULL, bit = PAPPL_PREASON_OTHER; bit <= PAPPL_PREASON_TONER_LOW; bit *= 2) { if (state_reasons & bit) { if (attr) ippSetString(client->response, &attr, ippGetCount(attr), _papplPrinterReasonString(bit)); else attr = ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_KEYWORD, "system-state-reasons", NULL, _papplPrinterReasonString(bit)); } } } } if (!ra || cupsArrayFind(ra, "system-up-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-up-time", (int)(time(NULL) - system->start_time)); if (system->uuid && (!ra || cupsArrayFind(ra, "system-uuid"))) ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_URI, "system-uuid", NULL, system->uuid); if (!ra || cupsArrayFind(ra, "system-xri-supported")) { char uri[1024]; // URI value httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), (system->options & PAPPL_SOPTIONS_NO_TLS) ? "ipp" : "ipps", NULL, client->host_field, client->host_port, "/ipp/system"); col = ippNew(); ippAddString(col, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-authentication", NULL, client->system->auth_service ? "basic" : "none"); ippAddString(col, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "xri-security", NULL, (system->options & PAPPL_SOPTIONS_NO_TLS) ? "none" : "tls"); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_URI, "xri-uri", NULL, uri); ippAddCollection(client->response, IPP_TAG_SYSTEM, "system-xri-supported", col); ippDelete(col); } _papplRWUnlock(system); cupsArrayDelete(ra); } // // 'ipp_pause_all_printers()' - all printers. // static void ipp_pause_all_printers( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System pappl_printer_t *printer; // Current printer http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Loop through the printers... _papplRWLockRead(system); for (printer = (pappl_printer_t *)cupsArrayGetFirst(system->printers); printer; printer = (pappl_printer_t *)cupsArrayGetNext(system->printers)) { papplPrinterPause(client->printer); } _papplRWUnlock(system); } // // 'ipp_resume_all_printers()' - all printers. // static void ipp_resume_all_printers( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System pappl_printer_t *printer; // Current printer http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Loop through the printers... _papplRWLockRead(system); for (printer = (pappl_printer_t *)cupsArrayGetFirst(system->printers); printer; printer = (pappl_printer_t *)cupsArrayGetNext(system->printers)) { papplPrinterResume(client->printer); } _papplRWUnlock(system); } // // 'ipp_set_system_attributes()' - Set system attributes. // static void ipp_set_system_attributes( pappl_client_t *client) // I - Client { pappl_system_t *system = client->system; // System ipp_attribute_t *rattr; // Current request attribute ipp_tag_t value_tag; // Value tag cups_len_t count; // Number of values const char *name; // Attribute name size_t i; // Looping var http_status_t auth_status; // Authorization status static _pappl_attr_t sattrs[] = // Settable system attributes { { "system-contact-col", IPP_TAG_BEGIN_COLLECTION, 1 }, { "system-default-printer-id", IPP_TAG_INTEGER, 1 }, { "system-geo-location", IPP_TAG_URI, 1 }, { "system-location", IPP_TAG_TEXT, 1 }, { "system-organization", IPP_TAG_TEXT, 1 }, { "system-organizational-unit", IPP_TAG_TEXT, 1 } }; // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } // Preflight request attributes... for (rattr = ippGetFirstAttribute(client->request); rattr; rattr = ippGetNextAttribute(client->request)) { papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "%s %s %s%s ...", ippTagString(ippGetGroupTag(rattr)), ippGetName(rattr), ippGetCount(rattr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(rattr))); if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) { continue; } else if (ippGetGroupTag(rattr) != IPP_TAG_SYSTEM) { papplClientRespondIPPUnsupported(client, rattr); continue; } name = ippGetName(rattr); value_tag = ippGetValueTag(rattr); count = ippGetCount(rattr); for (i = 0; i < (sizeof(sattrs) / sizeof(sattrs[0])); i ++) { if (!strcmp(name, sattrs[i].name) && value_tag == sattrs[i].value_tag && count <= sattrs[i].max_count) break; } if (i >= (sizeof(sattrs) / sizeof(sattrs[0]))) papplClientRespondIPPUnsupported(client, rattr); if (!strcmp(name, "system-default-printer-id")) { if (!papplSystemFindPrinter(system, NULL, ippGetInteger(rattr, 0), NULL)) { papplClientRespondIPPUnsupported(client, rattr); break; } } } if (ippGetStatusCode(client->response) != IPP_STATUS_OK) return; // Now apply changes... _papplRWLockWrite(system); for (rattr = ippGetFirstAttribute(client->request); rattr; rattr = ippGetNextAttribute(client->request)) { if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) continue; name = ippGetName(rattr); if (!strcmp(name, "system-contact-col")) { _papplContactImport(ippGetCollection(rattr, 0), &system->contact); } else if (!strcmp(name, "system-default-printer-id")) { // Value was checked previously... system->default_printer_id = ippGetInteger(rattr, 0); } else if (!strcmp(name, "system-geo-location")) { free(system->geo_location); system->geo_location = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "system-location")) { free(system->location); system->location = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "system-organization")) { free(system->organization); system->organization = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "system-organization-unit")) { free(system->org_unit); system->org_unit = strdup(ippGetString(rattr, 0, NULL)); } } system->config_changes ++; _papplRWUnlock(system); papplSystemAddEvent(system, NULL, NULL, PAPPL_EVENT_SYSTEM_CONFIG_CHANGED, NULL); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_shutdown_all_printers()' - Shutdown the system. // static void ipp_shutdown_all_printers( pappl_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = papplClientIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { papplClientRespond(client, auth_status, NULL, NULL, 0, 0); return; } client->system->shutdown_time = time(NULL); papplClientRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'printer_create_cb()' - Add a printer to the PAPPL-Create-Printers response. // static void printer_create_cb( pappl_printer_t *printer, // I - Printer _pappl_create_t *data) // I - Callback data { // Return printer information... if (data->ra) { // Nth printer (N > 1), need a separator... ippAddSeparator(data->client->response); } else { // First printer, set the response status and create the "requested" array... papplClientRespondIPP(data->client, IPP_STATUS_OK, NULL); data->ra = cupsArrayNew((cups_array_cb_t)strcmp, /*cb_data*/NULL, /*hash_cb*/NULL, /*hash_size*/0, /*copy_cb*/NULL, /*free_cb*/NULL); cupsArrayAdd(data->ra, "printer-id"); cupsArrayAdd(data->ra, "printer-is-accepting-jobs"); cupsArrayAdd(data->ra, "printer-state"); cupsArrayAdd(data->ra, "printer-state-reasons"); cupsArrayAdd(data->ra, "printer-uuid"); cupsArrayAdd(data->ra, "printer-xri-supported"); } // Add the printer attributes to the response... _papplRWLockRead(printer->system); _papplRWLockRead(printer); _papplPrinterCopyAttributesNoLock(printer, data->client, data->ra, NULL); _papplRWUnlock(printer); _papplRWUnlock(printer->system); } pappl-1.4.9/pappl/system-loadsave.c000066400000000000000000001032411476704353100172540ustar00rootroot00000000000000// // System load/save functions for the Printer Application Framework // // Copyright © 2020-2024 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static cups_len_t add_time(const char *name, time_t value, cups_len_t num_options, cups_option_t **options); static void parse_contact(char *value, pappl_contact_t *contact); static void parse_media_col(char *value, pappl_media_col_t *media); static char *read_line(cups_file_t *fp, char *line, size_t linesize, char **value, int *linenum); static void write_contact(cups_file_t *fp, pappl_contact_t *contact); static void write_media_col(cups_file_t *fp, const char *name, pappl_media_col_t *media); static void write_options(cups_file_t *fp, const char *name, cups_len_t num_options, cups_option_t *options); // // 'papplSystemLoadState()' - Load the previous system state. // // This function loads the previous system state from a file created by the // @link papplSystemSaveState@ function. The system state contains all of the // system object values, the list of printers, and the jobs for each printer. // // When loading a printer definition, if the printer cannot be created (e.g., // because the driver name is no longer valid) then that printer and all of its // job history will be lost. In the case of a bad driver name, a printer // application's driver callback can perform any necessary mapping of the driver // name, including the use its auto-add callback to find a compatible new // driver. // // > Note: This function must be called prior to @link papplSystemRun@. // bool // O - `true` on success, `false` on failure papplSystemLoadState( pappl_system_t *system, // I - System const char *filename) // I - File to load { int i; // Looping var cups_file_t *fp; // Output file int linenum; // Line number char line[2048], // Line from file *ptr, // Pointer into line/value *value; // Value from line // Range check input... if (!system || !filename) { return (false); } else if (system->is_running) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Cannot load system state while running."); return (false); } // Open the state file... if ((fp = cupsFileOpen(filename, "r")) == NULL) { if (errno != ENOENT) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to open system state file '%s': %s", filename, cupsGetErrorString()); return (false); } // Read lines from the state file... papplLog(system, PAPPL_LOGLEVEL_INFO, "Loading system state from '%s'.", filename); linenum = 0; while (read_line(fp, line, sizeof(line), &value, &linenum)) { if (!strcasecmp(line, "DNSSDName")) papplSystemSetDNSSDName(system, value); else if (!strcasecmp(line, "Location")) papplSystemSetLocation(system, value); else if (!strcasecmp(line, "GeoLocation")) papplSystemSetGeoLocation(system, value); else if (!strcasecmp(line, "Organization")) papplSystemSetOrganization(system, value); else if (!strcasecmp(line, "OrganizationalUnit")) papplSystemSetOrganizationalUnit(system, value); else if (!strcasecmp(line, "Contact")) { pappl_contact_t contact; // "system-contact" value parse_contact(value, &contact); papplSystemSetContact(system, &contact); } else if (!strcasecmp(line, "AdminGroup")) papplSystemSetAdminGroup(system, value); else if (!strcasecmp(line, "DefaultPrintGroup")) papplSystemSetDefaultPrintGroup(system, value); else if (!strcasecmp(line, "Password")) papplSystemSetPassword(system, value); else if (!strcasecmp(line, "DefaultPrinterID") && value) papplSystemSetDefaultPrinterID(system, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "MaxImageSize") && value) { long max_size; // Maximum (uncompressed) size int max_width, // Maximum width in columns max_height; // Maximum height in lines if (sscanf(value, "%ld%d%d", &max_size, &max_width, &max_height) == 3) papplSystemSetMaxImageSize(system, (size_t)max_size, max_width, max_height); } else if (!strcasecmp(line, "NextPrinterID") && value) papplSystemSetNextPrinterID(system, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "UUID") && value) { if ((system->uuid = strdup(value)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to allocate memory for system UUID."); return (false); } } else if (!strcasecmp(line, "options & PAPPL_SOPTIONS_MULTI_QUEUE) && (printer_state = cupsGetOption("state", num_options, options)) != NULL && (ipp_pstate_t)atoi(printer_state) == IPP_PSTATE_STOPPED) papplPrinterPause(printer); while (read_line(fp, line, sizeof(line), &value, &linenum)) { if (!strcasecmp(line, "")) break; else if (!printer) continue; else if (!strcasecmp(line, "DNSSDName")) papplPrinterSetDNSSDName(printer, value); else if (!strcasecmp(line, "Location")) papplPrinterSetLocation(printer, value); else if (!strcasecmp(line, "GeoLocation")) papplPrinterSetGeoLocation(printer, value); else if (!strcasecmp(line, "Organization")) papplPrinterSetOrganization(printer, value); else if (!strcasecmp(line, "OrganizationalUnit")) papplPrinterSetOrganizationalUnit(printer, value); else if (!strcasecmp(line, "Contact")) { pappl_contact_t contact;// "printer-contact" value parse_contact(value, &contact); papplPrinterSetContact(printer, &contact); } else if (!strcasecmp(line, "HoldNewJobs")) printer->hold_new_jobs = true; else if (!strcasecmp(line, "PrintGroup")) papplPrinterSetPrintGroup(printer, value); else if (!strcasecmp(line, "MaxActiveJobs") && value) papplPrinterSetMaxActiveJobs(printer, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "MaxCompletedJobs") && value) papplPrinterSetMaxCompletedJobs(printer, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "NextJobId") && value) papplPrinterSetNextJobID(printer, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "ImpressionsCompleted") && value) papplPrinterSetImpressionsCompleted(printer, (int)strtol(value, NULL, 10)); else if (!strcasecmp(line, "identify-actions-default")) printer->driver_data.identify_default = _papplIdentifyActionsValue(value); else if (!strcasecmp(line, "label-mode-configured")) printer->driver_data.mode_configured = _papplLabelModeValue(value); else if (!strcasecmp(line, "label-tear-offset-configured") && value) printer->driver_data.tear_offset_configured = (int)strtol(value, NULL, 10); else if (!strcasecmp(line, "media-col-default")) parse_media_col(value, &printer->driver_data.media_default); else if (!strncasecmp(line, "media-col-ready", 15)) { if ((i = (int)strtol(line + 15, NULL, 10)) >= 0 && i < PAPPL_MAX_SOURCE) parse_media_col(value, printer->driver_data.media_ready + i); } else if (!strcasecmp(line, "orientation-requested-default")) printer->driver_data.orient_default = (ipp_orient_t)ippEnumValue("orientation-requested", value); else if (!strcasecmp(line, "output-bin-default") && value) { for (i = 0; i < printer->driver_data.num_bin; i ++) { if (!strcmp(value, printer->driver_data.bin[i])) { printer->driver_data.bin_default = i; break; } } } else if (!strcasecmp(line, "print-color-mode-default")) printer->driver_data.color_default = _papplColorModeValue(value); else if (!strcasecmp(line, "print-content-optimize-default")) printer->driver_data.content_default = _papplContentValue(value); else if (!strcasecmp(line, "print-darkness-default") && value) printer->driver_data.darkness_default = (int)strtol(value, NULL, 10); else if (!strcasecmp(line, "print-quality-default")) printer->driver_data.quality_default = (ipp_quality_t)ippEnumValue("print-quality", value); else if (!strcasecmp(line, "print-scaling-default")) printer->driver_data.scaling_default = _papplScalingValue(value); else if (!strcasecmp(line, "print-speed-default") && value) printer->driver_data.speed_default = (int)strtol(value, NULL, 10); else if (!strcasecmp(line, "printer-darkness-configured") && value) printer->driver_data.darkness_configured = (int)strtol(value, NULL, 10); else if (!strcasecmp(line, "printer-resolution-default") && value) sscanf(value, "%dx%ddpi", &printer->driver_data.x_default, &printer->driver_data.y_default); else if (!strcasecmp(line, "sides-default")) printer->driver_data.sides_default = _papplSidesValue(value); else if ((ptr = strstr(line, "-default")) != NULL) { char defname[128], // xxx-default name supname[128]; // xxx-supported name ipp_attribute_t *attr; // Attribute *ptr = '\0'; snprintf(defname, sizeof(defname), "%s-default", line); snprintf(supname, sizeof(supname), "%s-supported", line); if (!value) value = ptr; ippDeleteAttribute(printer->driver_attrs, ippFindAttribute(printer->driver_attrs, defname, IPP_TAG_ZERO)); if ((attr = ippFindAttribute(printer->driver_attrs, supname, IPP_TAG_ZERO)) != NULL) { switch (ippGetValueTag(attr)) { case IPP_TAG_BOOLEAN : ippAddBoolean(printer->driver_attrs, IPP_TAG_PRINTER, defname, !strcmp(value, "true")); break; case IPP_TAG_INTEGER : case IPP_TAG_RANGE : ippAddInteger(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, defname, (int)strtol(value, NULL, 10)); break; case IPP_TAG_KEYWORD : ippAddString(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, defname, NULL, value); break; default : break; } } else { ippAddString(printer->driver_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, defname, NULL, value); } } else if (!strcasecmp(line, "Job") && value) { // Read printer job pappl_job_t *job; // Current Job struct stat jobbuf; // Job file buffer const char *job_name, // Job name *job_id, // Job ID *job_username, // Job username *job_format, // Job format *job_value; // Job option value num_options = cupsParseOptions(value, /*end*/NULL, 0, &options); if ((job_id = cupsGetOption("id", num_options, options)) == NULL || strtol(job_id, NULL, 10) <= 0 || (job_name = cupsGetOption("name", num_options, options)) == NULL || (job_username = cupsGetOption("username", num_options, options)) == NULL || (job_format = cupsGetOption("format", num_options, options)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Bad Job definition on line %d of '%s'.", linenum, filename); break; } if ((job = _papplJobCreate(printer, (int)strtol(job_id, NULL, 10), job_username, job_format, job_name, NULL)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Error creating job %s for printer %s", job_name, printer->name); break; } if ((job_value = cupsGetOption("filename", num_options, options)) != NULL) { if ((job->filename = strdup(job_value)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Error creating job %s for printer %s", job_name, printer->name); break; } } if ((job_value = cupsGetOption("state", num_options, options)) != NULL) job->state = (ipp_jstate_t)strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("state_reasons", num_options, options)) != NULL) job->state_reasons = (ipp_jstate_t)strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("created", num_options, options)) != NULL) job->created = strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("processing", num_options, options)) != NULL) job->processing = strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("completed", num_options, options)) != NULL) job->completed = strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("impressions", num_options, options)) != NULL) job->impressions = (int)strtol(job_value, NULL, 10); if ((job_value = cupsGetOption("imcompleted", num_options, options)) != NULL) job->impcompleted = (int)strtol(job_value, NULL, 10); // Add the job to printer completed jobs array... if (job->state < IPP_JSTATE_STOPPED) { // Load the file attributes from the spool directory... int attr_fd; // Attribute file descriptor char job_attr_filename[256]; // Attribute filename if ((attr_fd = papplJobOpenFile(job, job_attr_filename, sizeof(job_attr_filename), system->directory, "ipp", "r")) < 0) { if (errno != ENOENT) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to open file for job attributes: '%s'.", job_attr_filename); continue; } ippReadFile(attr_fd, job->attrs); close(attr_fd); if (!job->filename || stat(job->filename, &jobbuf)) { // If file removed, then set job state to aborted... job->state = IPP_JSTATE_ABORTED; } else { // Add the job to printer active jobs array... cupsArrayAdd(printer->active_jobs, job); } } else { // Add job to printer completed jobs... cupsArrayAdd(printer->completed_jobs, job); } } else papplLog(system, PAPPL_LOGLEVEL_WARN, "Unknown printer directive '%s' on line %d of '%s'.", line, linenum, filename); } // Loaded all printer attributes, call the status callback (if any) to // update the current printer state... if (printer && printer->driver_data.status_cb) (printer->driver_data.status_cb)(printer); } else { papplLog(system, PAPPL_LOGLEVEL_WARN, "Unknown directive '%s' on line %d of '%s'.", line, linenum, filename); } } cupsFileClose(fp); return (true); } // // 'papplSystemSaveState()' - Save the current system state. // // This function saves the current system state to a file. It is typically // used with the @link papplSystemSetSaveCallback@ function to periodically // save the state: // // ``` // |papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, // | (void *)filename); // ``` // bool // O - `true` on success, `false` on failure papplSystemSaveState( pappl_system_t *system, // I - System const char *filename) // I - File to save { cups_len_t i, j, // Looping vars count; // Number of printers cups_file_t *fp; // Output file pappl_printer_t *printer; // Current printer pappl_job_t *job; // Current Job if ((fp = cupsFileOpen(filename, "w")) == NULL) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create system state file '%s': %s", filename, cupsGetErrorString()); return (false); } papplLog(system, PAPPL_LOGLEVEL_INFO, "Saving system state to '%s'.", filename); _papplRWLockRead(system); if (system->dns_sd_name) cupsFilePutConf(fp, "DNSSDName", system->dns_sd_name); if (system->location) cupsFilePutConf(fp, "Location", system->location); if (system->geo_location) cupsFilePutConf(fp, "Geolocation", system->geo_location); if (system->organization) cupsFilePutConf(fp, "Organization", system->organization); if (system->org_unit) cupsFilePutConf(fp, "OrganizationalUnit", system->org_unit); write_contact(fp, &system->contact); if (system->admin_group) cupsFilePutConf(fp, "AdminGroup", system->admin_group); if (system->default_print_group) cupsFilePutConf(fp, "DefaultPrintGroup", system->default_print_group); if (system->password_hash[0]) cupsFilePutConf(fp, "Password", system->password_hash); cupsFilePrintf(fp, "DefaultPrinterID %d\n", system->default_printer_id); cupsFilePrintf(fp, "MaxImageSize %ld %d %d\n", (long)system->max_image_size, system->max_image_width, system->max_image_height); cupsFilePrintf(fp, "NextPrinterID %d\n", system->next_printer_id); cupsFilePutConf(fp, "UUID", system->uuid); // Loop through the printers. // // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the printers array. for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { cups_len_t jcount; // Number of jobs cups_len_t num_options = 0;// Number of options cups_option_t *options = NULL;// Options printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); _papplRWLockRead(printer); if (printer->is_deleted) { _papplRWUnlock(printer); continue; } num_options = cupsAddIntegerOption("id", printer->printer_id, num_options, &options); num_options = cupsAddOption("name", printer->name, num_options, &options); num_options = cupsAddOption("did", printer->device_id ? printer->device_id : "", num_options, &options); num_options = cupsAddOption("uri", printer->device_uri, num_options, &options); num_options = cupsAddOption("driver", printer->driver_name, num_options, &options); if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) num_options = cupsAddIntegerOption("state", (int)printer->state, num_options, &options); write_options(fp, "dns_sd_name) cupsFilePutConf(fp, "DNSSDName", printer->dns_sd_name); if (printer->location) cupsFilePutConf(fp, "Location", printer->location); if (printer->geo_location) cupsFilePutConf(fp, "Geolocation", printer->geo_location); if (printer->organization) cupsFilePutConf(fp, "Organization", printer->organization); if (printer->org_unit) cupsFilePutConf(fp, "OrganizationalUnit", printer->org_unit); write_contact(fp, &printer->contact); if (printer->hold_new_jobs) cupsFilePuts(fp, "HoldNewJobs\n"); if (printer->print_group) cupsFilePutConf(fp, "PrintGroup", printer->print_group); cupsFilePrintf(fp, "MaxActiveJobs %d\n", printer->max_active_jobs); cupsFilePrintf(fp, "MaxCompletedJobs %d\n", printer->max_completed_jobs); cupsFilePrintf(fp, "NextJobId %d\n", printer->next_job_id); cupsFilePrintf(fp, "ImpressionsCompleted %d\n", printer->impcompleted); if (printer->driver_data.identify_default) cupsFilePutConf(fp, "identify-actions-default", _papplIdentifyActionsString(printer->driver_data.identify_default)); if (printer->driver_data.mode_configured) cupsFilePutConf(fp, "label-mode-configured", _papplLabelModeString(printer->driver_data.mode_configured)); if (printer->driver_data.tear_offset_configured) cupsFilePrintf(fp, "label-tear-offset-configured %d\n", printer->driver_data.tear_offset_configured); write_media_col(fp, "media-col-default", &printer->driver_data.media_default); for (j = 0; j < (cups_len_t)printer->driver_data.num_source; j ++) { if (printer->driver_data.media_ready[j].size_name[0]) { char name[128]; // Attribute name snprintf(name, sizeof(name), "media-col-ready%u", (unsigned)j); write_media_col(fp, name, printer->driver_data.media_ready + j); } } if (printer->driver_data.orient_default) cupsFilePutConf(fp, "orientation-requested-default", ippEnumString("orientation-requested", (int)printer->driver_data.orient_default)); if (printer->driver_data.bin_default && printer->driver_data.num_bin > 0) cupsFilePutConf(fp, "output-bin-default", printer->driver_data.bin[printer->driver_data.bin_default]); if (printer->driver_data.color_default) cupsFilePutConf(fp, "print-color-mode-default", _papplColorModeString(printer->driver_data.color_default)); if (printer->driver_data.content_default) cupsFilePutConf(fp, "print-content-optimize-default", _papplContentString(printer->driver_data.content_default)); if (printer->driver_data.darkness_default) cupsFilePrintf(fp, "print-darkness-default %d\n", printer->driver_data.darkness_default); if (printer->driver_data.quality_default) cupsFilePutConf(fp, "print-quality-default", ippEnumString("print-quality", (int)printer->driver_data.quality_default)); if (printer->driver_data.scaling_default) cupsFilePutConf(fp, "print-scaling-default", _papplScalingString(printer->driver_data.scaling_default)); if (printer->driver_data.speed_supported[1] > 0) cupsFilePrintf(fp, "print-speed-default %d\n", printer->driver_data.speed_default); if (printer->driver_data.darkness_supported > 0) cupsFilePrintf(fp, "printer-darkness-configured %d\n", printer->driver_data.darkness_configured); if (printer->driver_data.x_default) cupsFilePrintf(fp, "printer-resolution-default %dx%ddpi\n", printer->driver_data.x_default, printer->driver_data.y_default); if (printer->driver_data.sides_default) cupsFilePutConf(fp, "sides-default", _papplSidesString(printer->driver_data.sides_default)); for (j = 0; j < (cups_len_t)printer->driver_data.num_vendor; j ++) { char defname[128], // xxx-default name defvalue[1024]; // xxx-default value snprintf(defname, sizeof(defname), "%s-default", printer->driver_data.vendor[j]); ippAttributeString(ippFindAttribute(printer->driver_attrs, defname, IPP_TAG_ZERO), defvalue, sizeof(defvalue)); cupsFilePutConf(fp, defname, defvalue); } // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the all_jobs array. for (j = 0, jcount = cupsArrayGetCount(printer->all_jobs); j < jcount; j ++) { job = (pappl_job_t *)cupsArrayGetElement(printer->all_jobs, j); _papplRWLockRead(job); // Add basic job attributes... num_options = 0; num_options = cupsAddIntegerOption("id", job->job_id, num_options, &options); num_options = cupsAddOption("name", job->name, num_options, &options); num_options = cupsAddOption("username", job->username, num_options, &options); num_options = cupsAddOption("format", job->format, num_options, &options); if (job->filename) num_options = cupsAddOption("filename", job->filename, num_options, &options); if (job->is_canceled) num_options = cupsAddIntegerOption("state", (int)IPP_JSTATE_CANCELED, num_options, &options); else if (job->state) num_options = cupsAddIntegerOption("state", (int)job->state, num_options, &options); if (job->state_reasons) num_options = cupsAddIntegerOption("state_reasons", (int)job->state_reasons, num_options, &options); if (job->created) num_options = add_time("created", job->created, num_options, &options); if (job->processing) num_options = add_time("processing", job->processing, num_options, &options); if (job->completed) num_options = add_time("completed", job->completed, num_options, &options); else if (job->is_canceled) num_options = add_time("completed", time(NULL), num_options, &options); if (job->impressions) num_options = cupsAddIntegerOption("impressions", job->impressions, num_options, &options); if (job->impcompleted) num_options = cupsAddIntegerOption("imcompleted", job->impcompleted, num_options, &options); if (job->attrs) { int attr_fd; // Attribute file descriptor char job_attr_filename[1024];// Attribute filename // Save job attributes to file in spool directory... if (job->state < IPP_JSTATE_STOPPED) { if ((attr_fd = papplJobOpenFile(job, job_attr_filename, sizeof(job_attr_filename), system->directory, "ipp", "w")) < 0) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create file for job attributes: '%s'.", job_attr_filename); _papplRWUnlock(job); continue; } ippWriteFile(attr_fd, job->attrs); close(attr_fd); } else { // If job completed or aborted, remove job-attributes file... papplJobOpenFile(job, job_attr_filename, sizeof(job_attr_filename), system->directory, "ipp", "x"); } } write_options(fp, "Job", num_options, options); cupsFreeOptions(num_options, options); _papplRWUnlock(job); } cupsFilePuts(fp, "\n"); _papplRWUnlock(printer); } _papplRWUnlock(system); cupsFileClose(fp); return (true); } // // 'add_time()' - Add a time_t value as an option. // static cups_len_t // O - New number of options add_time(const char *name, // I - Name time_t value, // I - Value cups_len_t num_options, // I - Number of options cups_option_t **options) // IO - Options { char buffer[100]; // Value string buffer // Format the number as a long integer... snprintf(buffer, sizeof(buffer), "%ld", (long)value); // Add the option with the string... return (cupsAddOption(name, buffer, num_options, options)); } // // 'parse_contact()' - Parse a contact value. // static void parse_contact(char *value, // I - Value pappl_contact_t *contact) // O - Contact { cups_len_t i, // Looping var num_options; // Number of options cups_option_t *options = NULL, // Options *option; // Current option memset(contact, 0, sizeof(pappl_contact_t)); num_options = cupsParseOptions(value, /*end*/NULL, 0, &options); for (i = num_options, option = options; i > 0; i --, option ++) { if (!strcasecmp(option->name, "name")) papplCopyString(contact->name, option->value, sizeof(contact->name)); else if (!strcasecmp(option->name, "email")) papplCopyString(contact->email, option->value, sizeof(contact->email)); else if (!strcasecmp(option->name, "telephone")) papplCopyString(contact->telephone, option->value, sizeof(contact->telephone)); } cupsFreeOptions(num_options, options); } // // 'parse_media_col()' - Parse a media-col value. // static void parse_media_col( char *value, // I - Value pappl_media_col_t *media) // O - Media collection { cups_len_t i, // Looping var num_options; // Number of options cups_option_t *options = NULL, // Options *option; // Current option memset(media, 0, sizeof(pappl_media_col_t)); num_options = cupsParseOptions(value, /*end*/NULL, 0, &options); for (i = num_options, option = options; i > 0; i --, option ++) { if (!strcasecmp(option->name, "bottom")) media->bottom_margin = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "left")) media->left_margin = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "left-offset")) media->left_offset = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "right")) media->right_margin = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "name")) papplCopyString(media->size_name, option->value, sizeof(media->size_name)); else if (!strcasecmp(option->name, "width")) media->size_width = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "length")) media->size_length = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "source")) papplCopyString(media->source, option->value, sizeof(media->source)); else if (!strcasecmp(option->name, "top")) media->top_margin = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "offset") || !strcasecmp(option->name, "top-offset")) media->top_offset = (int)strtol(option->value, NULL, 10); else if (!strcasecmp(option->name, "tracking")) media->tracking = _papplMediaTrackingValue(option->value); else if (!strcasecmp(option->name, "type")) papplCopyString(media->type, option->value, sizeof(media->type)); } cupsFreeOptions(num_options, options); } // // 'read_line()' - Read a line from the state file. // // This function is like `cupsFileGetConf`, except that it doesn't support // comments since the state files are not meant to be edited or maintained by // humans. // static char * // O - Line or `NULL` on EOF read_line(cups_file_t *fp, // I - File char *line, // I - Line buffer size_t linesize, // I - Size of line buffer char **value, // O - Value portion of line int *linenum) // IO - Current line number { char *ptr; // Pointer into line // Try reading a line from the file... *value = NULL; if (!cupsFileGets(fp, line, linesize)) return (NULL); // Got it, bump the line number... (*linenum) ++; // If we have "something value" then split at the whitespace... if ((ptr = strchr(line, ' ')) != NULL) { *ptr++ = '\0'; *value = ptr; } // Strip the trailing ">" for "" if (line[0] == '<' && *value && (ptr = *value + strlen(*value) - 1) >= *value && *ptr == '>') *ptr = '\0'; return (line); } // // 'write_contact()' - Write an "xxx-contact" value. // static void write_contact(cups_file_t *fp, // I - File pappl_contact_t *contact) // I - Contact { cups_len_t num_options = 0; // Number of options cups_option_t *options = NULL; // Options if (contact->name[0]) num_options = cupsAddOption("name", contact->name, num_options, &options); if (contact->email[0]) num_options = cupsAddOption("email", contact->email, num_options, &options); if (contact->telephone[0]) num_options = cupsAddOption("telephone", contact->telephone, num_options, &options); write_options(fp, "Contact", num_options, options); cupsFreeOptions(num_options, options); } // // 'write_media_col()' - Write a media-col value... // static void write_media_col( cups_file_t *fp, // I - File const char *name, // I - Attribute name pappl_media_col_t *media) // I - Media value { cups_len_t num_options = 0; // Number of options cups_option_t *options = NULL; // Options if (media->bottom_margin) num_options = cupsAddIntegerOption("bottom", media->bottom_margin, num_options, &options); if (media->left_margin) num_options = cupsAddIntegerOption("left", media->left_margin, num_options, &options); if (media->left_offset) num_options = cupsAddIntegerOption("left-offset", media->left_offset, num_options, &options); if (media->right_margin) num_options = cupsAddIntegerOption("right", media->right_margin, num_options, &options); if (media->size_name[0]) num_options = cupsAddOption("name", media->size_name, num_options, &options); if (media->size_width) num_options = cupsAddIntegerOption("width", media->size_width, num_options, &options); if (media->size_length) num_options = cupsAddIntegerOption("length", media->size_length, num_options, &options); if (media->source[0]) num_options = cupsAddOption("source", media->source, num_options, &options); if (media->top_margin) num_options = cupsAddIntegerOption("top", media->top_margin, num_options, &options); if (media->top_offset) num_options = cupsAddIntegerOption("top-offset", media->top_offset, num_options, &options); if (media->tracking) num_options = cupsAddOption("tracking", _papplMediaTrackingString(media->tracking), num_options, &options); if (media->type[0]) num_options = cupsAddOption("type", media->type, num_options, &options); write_options(fp, name, num_options, options); cupsFreeOptions(num_options, options); } // // 'write_options()' - Write a CUPS options array value... // static void write_options(cups_file_t *fp, // I - File const char *name, // I - Attribute name cups_len_t num_options,// I - Number of options cups_option_t *options) // I - Options { const char *start, // Start of current subset *ptr; // Pointer into value cupsFilePuts(fp, name); while (num_options > 0) { cupsFilePrintf(fp, " %s=\"", options->name); for (start = options->value, ptr = start; *ptr; ptr ++) { if (*ptr == '\\' || *ptr == '\"') { if (ptr > start) cupsFileWrite(fp, start, (size_t)(ptr - start)); cupsFilePutChar(fp, '\\'); start = ptr; } } if (ptr > start) cupsFileWrite(fp, start, (size_t)(ptr - start)); cupsFilePutChar(fp, '\"'); num_options --; options ++; } if (*name == '<') cupsFilePuts(fp, ">\n"); else cupsFilePutChar(fp, '\n'); } pappl-1.4.9/pappl/system-loc.c000066400000000000000000000026271476704353100162410ustar00rootroot00000000000000// // System localization support for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "system-private.h" #include "loc-private.h" // // '_papplSystemAddLoc()' - Add localization data to a system. // void _papplSystemAddLoc( pappl_system_t *system, // I - System pappl_loc_t *loc) // I - Localization data { // Create an array to hold the localizations as needed, then add... _papplRWLockWrite(system); if (!system->localizations) system->localizations = cupsArrayNew((cups_array_cb_t)_papplLocCompare, NULL, NULL, 0, NULL, (cups_afree_cb_t)_papplLocDelete); cupsArrayAdd(system->localizations, loc); _papplRWUnlock(system); } // // 'papplSystemFindLoc()' - Find a localization for the given printer and language. // pappl_loc_t * // O - Localization or `NULL` if none papplSystemFindLoc( pappl_system_t *system, // I - System const char *language) // I - Language { pappl_loc_t key, // Search key *match; // Matching localization // Range check input... if (!system || !language) return (NULL); // Find any existing localization... _papplRWLockRead(system); key.system = system; key.name = (char *)language; match = cupsArrayFind(system->localizations, &key); _papplRWUnlock(system); return (match); } pappl-1.4.9/pappl/system-printer.c000066400000000000000000000123521476704353100171430ustar00rootroot00000000000000// // System functions on printers for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // Local functions... // static int compare_printers(pappl_printer_t *a, pappl_printer_t *b); // // '_papplSystemAddPrinter()' - Add a printer to the system object, creating the printers array as needed. // void _papplSystemAddPrinter( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer int printer_id) // I - Printer ID or `0` for new { // Add the printer to the system... _papplRWLockWrite(system); if (printer_id) printer->printer_id = printer_id; else printer->printer_id = system->next_printer_id ++; if (!system->printers) system->printers = cupsArrayNew((cups_array_cb_t)compare_printers, /*cb_data*/NULL, /*hash_cb*/NULL, /*hash_size*/0, /*copy_cb*/NULL, /*free_cb*/NULL); cupsArrayAdd(system->printers, printer); if (!system->default_printer_id) system->default_printer_id = printer->printer_id; _papplRWUnlock(system); _papplSystemConfigChanged(system); papplSystemAddEvent(system, printer, NULL, PAPPL_EVENT_PRINTER_CREATED, NULL); papplSystemAddEvent(system, printer, NULL, PAPPL_EVENT_SYSTEM_CONFIG_CHANGED, NULL); } // // 'papplSystemCreatePrinters()' - Create newly discovered printers. // // This function lists all devices specified by "types" and attempts to add any // new printers that are found. The callback function "cb" is invoked for each // printer that is added. // bool // O - `true` if printers were added, `false` otherwise papplSystemCreatePrinters( pappl_system_t *system, // I - System pappl_devtype_t types, // I - Device types pappl_pr_create_cb_t cb, // I - Callback function void *cb_data) // I - Callback data { bool ret = false; // Return value cups_array_t *devices; // Device array _pappl_dinfo_t *d; // Current device information // List the devices... devices = _papplDeviceInfoCreateArray(); papplDeviceList(types, (pappl_device_cb_t)_papplDeviceInfoCallback, devices, papplLogDevice, system); // Loop through the devices to find new stuff... for (d = (_pappl_dinfo_t *)cupsArrayGetFirst(devices); d; d = (_pappl_dinfo_t *)cupsArrayGetNext(devices)) { pappl_printer_t *printer = NULL;// New printer // See if there is already a printer for this device URI... if (papplSystemFindPrinter(system, NULL, 0, d->device_uri)) continue; // Printer with this device URI exists // Then try creating the printer... if ((printer = papplPrinterCreate(system, 0, d->device_info, "auto", d->device_id, d->device_uri)) == NULL) continue; // Printer with this name exists // Register the DNS-SD service... _papplRWLockRead(printer->system); _papplRWLockRead(printer); _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); _papplRWUnlock(printer->system); // Created, return true and invoke the callback if provided... ret = true; if (cb) (cb)(printer, cb_data); } cupsArrayDelete(devices); return (ret); } // // 'papplSystemFindPrinter()' - Find a printer by resource, ID, or device URI. // // This function finds a printer contained in the system using its resource // path, unique integer identifier, or device URI. If none of these is // specified, the current default printer is returned. // pappl_printer_t * // O - Printer or `NULL` if none papplSystemFindPrinter( pappl_system_t *system, // I - System const char *resource, // I - Resource path or `NULL` int printer_id, // I - Printer ID or `0` const char *device_uri) // I - Device URI or `NULL` { cups_len_t i, // Current printer index count; // Printer count pappl_printer_t *printer = NULL;// Matching printer // Range check input... if (!system) return (NULL); _papplRWLockRead(system); if (resource && (!strcmp(resource, "/") || !strcmp(resource, "/ipp/print") || (!strncmp(resource, "/ipp/print/", 11) && isdigit(resource[11] & 255)))) { printer_id = system->default_printer_id; resource = NULL; } // Loop through the printers to find the one we want... // // Note: Cannot use cupsArrayGetFirst/Last since other threads might be // enumerating the printers array. for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (resource && !strncasecmp(printer->resource, resource, printer->resourcelen) && (!resource[printer->resourcelen] || resource[printer->resourcelen] == '/')) break; else if (printer->printer_id == printer_id) break; else if (device_uri && !strcmp(printer->device_uri, device_uri)) break; } if (i >= count) printer = NULL; _papplRWUnlock(system); return (printer); } // // 'compare_printers()' - Compare two printers. // static int // O - Result of comparison compare_printers(pappl_printer_t *a, // I - First printer pappl_printer_t *b) // I - Second printer { return (strcmp(a->name, b->name)); } pappl-1.4.9/pappl/system-private.h000066400000000000000000000244061476704353100171420ustar00rootroot00000000000000// // Private system header file for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_SYSTEM_PRIVATE_H_ # define _PAPPL_SYSTEM_PRIVATE_H_ # include "dnssd-private.h" # include "subscription-private.h" # include "system.h" // // Constants... // # define _PAPPL_MAX_LISTENERS 32 // Maximum number of listener sockets // // Types and structures... // typedef struct _pappl_mime_filter_s // MIME filter { const char *src, // Source MIME media type *dst; // Destination MIME media type pappl_mime_filter_cb_t cb; // Filter callback function void *cbdata; // Filter callback data } _pappl_mime_filter_t; typedef struct _pappl_resource_s // Resource { char *path, // Path *format, // Content type (MIME media type) *filename, // Filename *language; // Language (for strings) time_t last_modified; // Last-Modified date/time const void *data; // Static data size_t length; // Length of file/data pappl_resource_cb_t cb; // Dynamic callback void *cbdata; // Callback data } _pappl_resource_t; struct _pappl_system_s // System data { pthread_rwlock_t rwlock; // Reader/writer lock pappl_soptions_t options; // Server options bool is_running; // Is the system running? time_t start_time, // Startup time config_time, // Time of last config change clean_time, // Next clean time shutdown_time; // Shutdown requested? pthread_mutex_t config_mutex; // Mutex for configuration changes size_t config_changes, // Number of configuration changes save_changes; // Number of saved changes char *uuid, // "system-uuid" value *name, // "system-name" value *dns_sd_name, // "system-dns-sd-name" value *location, // "system-location" value *geo_location, // "system-geo-location" value *organization, // "system-organization" value *org_unit; // "system-organizational-unit" value pappl_contact_t contact; // "system-contact-col" value char *hostname; // Published hostname int port; // Port number, if any bool is_listenhost; // Hostname is listen host char *domain_path; // Domain socket path, if any cups_len_t num_versions; // Number of "xxx-firmware-yyy" values pappl_version_t versions[10]; // "xxx-firmware-yyy" values char *footer_html; // Footer HTML for web interface char *server_header; // Server: header value char *directory; // Spool directory pthread_mutex_t log_mutex; // Log mutex char *log_file; // Log filename, if any int log_fd; // Log file descriptor, if any pappl_loglevel_t log_level; // Log level size_t log_max_size; // Maximum log file size or `0` for none bool log_is_syslog; // Log to system log? char *subtypes; // DNS-SD sub-types, if any bool tls_only; // Only support TLS? char *auth_service; // PAM authorization service, if any char *admin_group; // PAM administrative group, if any gid_t admin_gid; // PAM administrative group ID char *default_print_group; // Default PAM printing group, if any char session_key[65]; // Session key pthread_mutex_t session_mutex; // Mutex for the session key time_t session_time; // Session key time cups_len_t num_listeners; // Number of listener sockets struct pollfd listeners[_PAPPL_MAX_LISTENERS]; // Listener sockets int num_clients, // Current number of clients max_clients; // Maximum number of clients cups_array_t *links; // Web navigation links cups_array_t *resources; // Array of resources cups_array_t *localizations; // Array of localizations cups_array_t *filters; // Array of filters int next_client; // Next client number cups_array_t *printers; // Array of printers int default_printer_id, // Default printer-id next_printer_id; // Next printer-id char password_hash[100]; // Access password hash cups_len_t num_drivers; // Number of printer drivers pappl_pr_driver_t *drivers; // Printer drivers pappl_pr_autoadd_cb_t autoadd_cb; // Printer driver auto-add callback pappl_pr_create_cb_t create_cb; // Printer driver creation callback pappl_pr_driver_cb_t driver_cb; // Printer driver initialization callback void *driver_cbdata; // Printer driver callback data ipp_t *attrs; // Static attributes for system char *auth_scheme; // Authentication scheme pappl_auth_cb_t auth_cb; // Authentication callback void *auth_cbdata; // Authentication callback data pappl_mime_cb_t mime_cb; // MIME typing callback void *mime_cbdata; // MIME typing callback data pappl_ipp_op_cb_t op_cb; // IPP operation callback void *op_cbdata; // IPP operation callback data pappl_save_cb_t save_cb; // Save callback void *save_cbdata; // Save callback data # ifdef HAVE_MDNSRESPONDER _pappl_srv_t dns_sd_ipps_ref, // DNS-SD IPPS service dns_sd_http_ref; // DNS-SD HTTP service DNSRecordRef dns_sd_loc_ref; // DNS-SD LOC record # else _pappl_srv_t dns_sd_ref; // DNS-SD services # endif // HAVE_MDNSRESPONDER unsigned char dns_sd_loc[16]; // DNS-SD LOC record data bool dns_sd_any_collision; // Was there a name collision for any printer? bool dns_sd_collision; // Was there a name collision for this system? int dns_sd_serial; // DNS-SD serial number (for collisions) int dns_sd_host_changes; // Last count of DNS-SD host name changes pappl_network_get_cb_t network_get_cb; // Get networks callback pappl_network_set_cb_t network_set_cb; // Set networks callback void *network_cbdata; // Network callback data pappl_wifi_join_cb_t wifi_join_cb; // Wi-Fi join callback pappl_wifi_list_cb_t wifi_list_cb; // Wi-Fi list callback pappl_wifi_status_cb_t wifi_status_cb; // Wi-Fi status callback void *wifi_cbdata; // Wi-Fi callback data pappl_event_cb_t event_cb; // Event callback void *event_data; // Event callback data pappl_event_cb_t systemui_cb; // System UI event callback void *systemui_data; // System UI event callback data size_t max_subscriptions; // Maximum number of subscriptions cups_array_t *subscriptions; // Subscription array int next_subscription_id; // Next "notify-subscription-id" value pthread_cond_t subscription_cond; // Subscription condition variable pthread_mutex_t subscription_mutex; // Subscription mutex cups_array_t *timers; // Timers array size_t max_image_size; // Maximum image file size (uncompressed) int max_image_width, // Maximum image file width max_image_height; // Maximum image file height }; typedef struct _pappl_timer_s // Timer callback data { pappl_timer_cb_t cb; // Callback function void *cb_data; // Callback data time_t next; // Next time int interval; // Timer interval } _pappl_timer_t; // // Functions... // extern void _papplSystemAddEventNoLock(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, const char *message, ...) _PAPPL_FORMAT(5, 6) _PAPPL_PRIVATE; extern void _papplSystemAddEventNoLockv(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, const char *message, va_list ap) _PAPPL_PRIVATE; extern void _papplSystemAddLoc(pappl_system_t *system, pappl_loc_t *loc) _PAPPL_PRIVATE; extern void _papplSystemAddPrinter(pappl_system_t *system, pappl_printer_t *printer, int printer_id) _PAPPL_PRIVATE; extern void _papplSystemAddPrinterIcons(pappl_system_t *system, pappl_printer_t *printer) _PAPPL_PRIVATE; extern bool _papplSystemAddSubscription(pappl_system_t *system, pappl_subscription_t *sub, int sub_id) _PAPPL_PRIVATE; extern void _papplSystemCleanSubscriptions(pappl_system_t *system, bool clean_all) _PAPPL_PRIVATE; extern void _papplSystemConfigChanged(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemExportVersions(pappl_system_t *system, ipp_t *ipp, ipp_tag_t group_tag, cups_array_t *ra); extern _pappl_mime_filter_t *_papplSystemFindMIMEFilter(pappl_system_t *system, const char *srctype, const char *dsttype) _PAPPL_PRIVATE; extern _pappl_resource_t *_papplSystemFindResourceForLanguage(pappl_system_t *system, const char *language) _PAPPL_PRIVATE; extern _pappl_resource_t *_papplSystemFindResourceForPath(pappl_system_t *system, const char *path) _PAPPL_PRIVATE; extern bool _papplSystemIsShutdownNoLock(pappl_system_t *system) _PAPPL_PRIVATE; extern char *_papplSystemMakeUUID(pappl_system_t *system, const char *printer_name, int job_id, char *buffer, size_t bufsize) _PAPPL_PRIVATE; extern void _papplSystemNeedClean(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemProcessIPP(pappl_client_t *client) _PAPPL_PRIVATE; extern bool _papplSystemRegisterDNSSDNoLock(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemSetHostNameNoLock(pappl_system_t *system, const char *value) _PAPPL_PRIVATE; extern void _papplSystemStatusUI(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemUnregisterDNSSDNoLock(pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebAddPrinter(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebConfig(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebConfigFinalize(pappl_system_t *system, cups_len_t num_form, cups_option_t *form) _PAPPL_PRIVATE; extern void _papplSystemWebHome(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebLogFile(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebLogs(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebNetwork(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebSecurity(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebSettings(pappl_client_t *client) _PAPPL_PRIVATE; # if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) extern void _papplSystemWebTLSInstall(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; extern void _papplSystemWebTLSNew(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; # endif // HAVE_OPENSSL || HAVE_GNUTLS extern void _papplSystemWebWiFi(pappl_client_t *client, pappl_system_t *system) _PAPPL_PRIVATE; #endif // !_PAPPL_SYSTEM_PRIVATE_H_ pappl-1.4.9/pappl/system-status-dummy.c000066400000000000000000000015211476704353100201300ustar00rootroot00000000000000// // Dummy system status UI for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // '_papplSystemStatusCallback()' - Handle system events... // void _papplSystemStatusCallback( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any pappl_event_t event, // I - Event void *data) // I - System UI data { (void)system; (void)printer; (void)job; (void)event; (void)data; } // // '_papplSystemStatusUI()' - Show/run the system status UI. // void _papplSystemStatusUI( pappl_system_t *system) // I - System { (void)system; } pappl-1.4.9/pappl/system-status-gnome.c000066400000000000000000000013661476704353100201110ustar00rootroot00000000000000// // GNOME system status UI for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // '_papplSystemStatusCallback()' - Handle system events... // void _papplSystemStatusCallback( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any pappl_event_t event, // I - Event void *data) // I - System UI data { } // // '_papplSystemStatusUI()' - Show/run the system status UI. // void _papplSystemStatusUI( pappl_system_t *system) // I - System { } pappl-1.4.9/pappl/system-status-macos.m000066400000000000000000000215631476704353100201210ustar00rootroot00000000000000// // macOS system status UI for the Printer Application Framework // // Copyright © 2022-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" #import // // Local class to hold system status data... // @interface PAPPLSystemStatusUI : NSObject { @public pappl_system_t *system; // System object pthread_rwlock_t rwlock; // Reader/writer lock size_t event_count; // Event counter NSString *name; // Application name NSMenu *mainMenu; // Application menu NSStatusItem *statusItem; // Status item in menubar NSMenu *statusMenu; // Menu associated with status item } + (id)newStatusUI:(pappl_system_t *)system; - (IBAction)showPrinter:(id)sender; - (IBAction)showWebPage:(id)sender; - (IBAction)terminate:(id)sender; - (void)updateMenu; @end // // Local function... // static void printer_cb(pappl_printer_t *printer, PAPPLSystemStatusUI *ui); static void status_cb(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, void *data); // // '_papplSystemStatusUI()' - Show/run the system status UI. // void _papplSystemStatusUI( pappl_system_t *system) // I - System { NSApplication *app; // Application object size_t last_count = 0; // Last count // Create a menu bar status item... app = [NSApplication sharedApplication]; PAPPLSystemStatusUI *ui = [PAPPLSystemStatusUI newStatusUI:system]; if (ui == nil) { NSLog(@"Unable to create system status UI."); return; } app.delegate = ui; app.mainMenu = ui->mainMenu; // Do a run loop that exits once the system is no longer running... while (!_papplSystemIsShutdownNoLock(system)) { NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5] inMode:NSDefaultRunLoopMode dequeue:YES]; if (event) [NSApp sendEvent:event]; pthread_rwlock_rdlock(&ui->rwlock); if (ui->event_count > last_count) { // NSLog(@"******** last_count=%u, event_count=%u", (unsigned)last_count, (unsigned)ui->event_count); last_count = ui->event_count; [ui updateMenu]; } pthread_rwlock_unlock(&ui->rwlock); } } @implementation PAPPLSystemStatusUI // // 'newStatusUI:' - Create a new system status user interface. // + (id)newStatusUI:(pappl_system_t *)system { // Allocate a new UI class instance... PAPPLSystemStatusUI *ui = [PAPPLSystemStatusUI alloc]; // New system status UI if (ui != nil) { // Assign pointers... ui->system = system; system->systemui_data = (void *)CFBridgingRetain(ui); system->systemui_cb = status_cb; pthread_rwlock_init(&ui->rwlock, NULL); // Create the menu bar icon... ui->statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength]; // Create the menu bar menus... ui->name = [NSString stringWithUTF8String:system->versions[0].name]; ui->mainMenu = [[NSMenu alloc] initWithTitle:ui->name]; [ui->mainMenu addItemWithTitle:[NSString stringWithFormat:@"About %@",ui->name] action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; // Set the image for the item... NSImage *image = [NSApp.applicationIconImage copy]; image.size = ui->statusItem.button.frame.size; ui->statusItem.button.image = image; // Build the menu... [ui updateMenu]; } return (ui); } // // 'showPrinter:' - Show the selected printer's web page. // - (IBAction)showPrinter:(id)sender { pappl_printer_t *printer; // Printer char uri[1024]; // Web page if ((printer = papplSystemFindPrinter(system, NULL, (int)((NSMenuItem *)sender).tag, NULL)) != NULL) { httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "http", NULL, "localhost", papplSystemGetHostPort(system), printer->uriname); NSLog(@"showWebPage: Opening '%s'.", uri); [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithUTF8String:uri]]]; } } // // 'showWebPage:' - Show the system web page. // - (IBAction)showWebPage:(id)sender { char uri[1024]; // Web page httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "http", NULL, "localhost", papplSystemGetHostPort(system), "/"); NSLog(@"showWebPage: Opening '%s'.", uri); [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithUTF8String:uri]]]; } // // 'terminate:' - Quit the printer application. // - (IBAction)terminate:(id)sender { papplSystemShutdown(system); } // // 'updateMenu' - Update the status icon menu. // - (void)updateMenu { char sysname[256]; // System name // NSLog(@"******** updateMenu"); // Start with the system name... statusMenu = [[NSMenu alloc] initWithTitle:name]; NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:papplSystemGetName(system, sysname, sizeof(sysname))] action:@selector(showWebPage:) keyEquivalent:@""]; item.target = self; [statusMenu addItem:item]; // Version number... [statusMenu addItemWithTitle:[NSString stringWithFormat:@" %s %s",system->versions[0].name,system->versions[0].sversion] action:nil keyEquivalent:@""]; // Separator... [statusMenu addItem:[NSMenuItem separatorItem]]; // Then show all of the printers... papplSystemIteratePrinters(system, (pappl_printer_cb_t)printer_cb, (__bridge void *)self); // Another separator... [statusMenu addItem:[NSMenuItem separatorItem]]; // Quit... item = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@""]; item.target = self; [statusMenu addItem:item]; // Replace the current menu... self->statusItem.menu = self->statusMenu; } @end // // 'printer_cb()' - Callback for adding a printer to the status menu. // static void printer_cb( pappl_printer_t *printer, // I - Printer PAPPLSystemStatusUI *ui) // I - Status UI { char name_status[256]; // Printer name pappl_preason_t reasons; // State reasons... snprintf(name_status, sizeof(name_status), "%s (%s)", printer->name, ippEnumString("printer-state", (int)printer->state)); reasons = printer->state_reasons; NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:name_status] action:@selector(showPrinter:) keyEquivalent:@""]; item.target = ui; item.tag = printer->printer_id; [ui->statusMenu addItem:item]; if (reasons & (PAPPL_PREASON_MEDIA_NEEDED | PAPPL_PREASON_MEDIA_EMPTY)) [ui->statusMenu addItemWithTitle:@" Out of paper." action:nil keyEquivalent:@""]; else if (reasons & PAPPL_PREASON_MEDIA_LOW) [ui->statusMenu addItemWithTitle:@" Low paper." action:nil keyEquivalent:@""]; if (reasons & PAPPL_PREASON_MARKER_SUPPLY_EMPTY) [ui->statusMenu addItemWithTitle:@" Out of ink." action:nil keyEquivalent:@""]; else if (reasons & PAPPL_PREASON_MARKER_SUPPLY_LOW) [ui->statusMenu addItemWithTitle:@" Low ink." action:nil keyEquivalent:@""]; if (reasons & PAPPL_PREASON_TONER_EMPTY) [ui->statusMenu addItemWithTitle:@" Out of toner." action:nil keyEquivalent:@""]; else if (reasons & PAPPL_PREASON_TONER_LOW) [ui->statusMenu addItemWithTitle:@" Low toner." action:nil keyEquivalent:@""]; } // // 'status_cb()' - Handle system events... // static void status_cb( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any pappl_event_t event, // I - Event void *data) // I - System UI data { (void)system; (void)printer; (void)job; (void)data; // NSLog(@"******** status_cb: event=%08x", event); if (event & (PAPPL_EVENT_PRINTER_ALL | PAPPL_EVENT_SYSTEM_CONFIG_CHANGED)) { // Printer or system change event, update the menu... PAPPLSystemStatusUI *ui = (__bridge PAPPLSystemStatusUI *)system->systemui_data; pthread_rwlock_wrlock(&ui->rwlock); ui->event_count ++; pthread_rwlock_unlock(&ui->rwlock); // NSLog(@"******* status_cb: event_count=%u", (unsigned)ui->event_count); } #if 0 // TODO: Migrate to new UNUserNotification API if (event & PAPPL_EVENT_PRINTER_STATE_CHANGED) { pappl_preason_t reasons; // State reasons... NSString *message = nil; // Message for notification reasons = printer->state_reasons; if (reasons & (PAPPL_PREASON_MEDIA_NEEDED | PAPPL_PREASON_MEDIA_EMPTY)) message = @"Out of paper."; else if (reasons & PAPPL_PREASON_MARKER_SUPPLY_EMPTY) message = @"Out of ink."; else if (reasons & PAPPL_PREASON_TONER_EMPTY) message = @"Out of toner."; if (message) { NSUserNotification *n = [[NSUserNotification alloc] init]; n.title = [NSString stringWithUTF8String:papplPrinterGetName(printer)]; n.informativeText = message; [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:n]; } } #endif // 0 } pappl-1.4.9/pappl/system-status-win32.c000066400000000000000000000014101476704353100177340ustar00rootroot00000000000000// // Windows system status UI for the Printer Application Framework // // Copyright © 2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "pappl-private.h" // // '_papplSystemStatusCallback()' - Handle system events... // void _papplSystemStatusCallback( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any pappl_event_t event, // I - Event void *data) // I - System UI data { } // // '_papplSystemStatusUI()' - Show/run the system status UI. // void _papplSystemStatusUI( pappl_system_t *system) // I - System { (void)system; } pappl-1.4.9/pappl/system-subscription.c000066400000000000000000000216611476704353100202070ustar00rootroot00000000000000// // System event functions for the Printer Application Framework // // Copyright © 2022-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" // // Local functions... // static int compare_subscriptions(pappl_subscription_t *a, pappl_subscription_t *b); // // 'papplSystemAddEvent()' - Add a notification event. // void papplSystemAddEvent( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Associated printer, if any pappl_job_t *job, // I - Associated job, if any pappl_event_t event, // I - IPP "notify-events" bit value const char *message, // I - printf-style message string ...) // I - Additional arguments as needed { va_list ap; // Argument pointer if (!system) return; if (printer) _papplRWLockRead(printer); if (job) _papplRWLockRead(job); va_start(ap, message); _papplSystemAddEventNoLockv(system, printer, job, event, message, ap); va_end(ap); if (job) _papplRWUnlock(job); if (printer) _papplRWUnlock(printer); } // // '_papplSystemAddEventNoLock()' - Add a notification event (no lock). // void _papplSystemAddEventNoLock( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Associated printer, if any pappl_job_t *job, // I - Associated job, if any pappl_event_t event, // I - IPP "notify-events" bit value const char *message, // I - printf-style message string ...) // I - Additional arguments as needed { va_list ap; // Argument pointer va_start(ap, message); _papplSystemAddEventNoLockv(system, printer, job, event, message, ap); va_end(ap); } // // '_papplSystemAddEventNoLockv()' - Add a notification event (no lock). // void _papplSystemAddEventNoLockv( pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Associated printer, if any pappl_job_t *job, // I - Associated job, if any pappl_event_t event, // I - IPP "notify-events" bit value const char *message, // I - printf-style message string va_list ap) // I - Pointer to additional arguments { pappl_subscription_t *sub; // Current subscription ipp_t *n; // Notify event attributes char uri[1024] = "", // "notify-printer/system-uri" value text[1024]; // "notify-text" value va_list cap; // Copy of additional arguments // Loop through all of the subscriptions and deliver any events... _papplRWLockRead(system); if (system->systemui_cb && system->systemui_data) (system->systemui_cb)(system, printer, job, event, system->systemui_data); if (system->event_cb) (system->event_cb)(system, printer, job, event, system->event_data); for (sub = (pappl_subscription_t *)cupsArrayGetFirst(system->subscriptions); sub; sub = (pappl_subscription_t *)cupsArrayGetNext(system->subscriptions)) { if ((sub->mask & event) && (!sub->job || job == sub->job) && (!sub->printer || printer == sub->printer)) { _papplRWLockWrite(sub); n = ippNew(); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_CONST_TAG(IPP_TAG_CHARSET), "notify-charset", NULL, "utf-8"); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "notify-natural-language", NULL, sub->language); if (printer) { if (!uri[0]) httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, system->hostname, system->port, printer->resource); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_URI, "notify-printer-uri", NULL, uri); } else { if (!uri[0]) httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, system->hostname, system->port, "/ipp/system"); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_URI, "notify-system-uri", NULL, uri); } if (job) ippAddInteger(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, sub->job ? "notify-job-id" : "job-id", job->job_id); ippAddInteger(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-subscription-id", sub->subscription_id); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_CONST_TAG(IPP_TAG_URI), "notify-subscription-uuid", NULL, sub->uuid); ippAddInteger(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "notify-sequence-number", ++ sub->last_sequence); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-subscribed-event", NULL, _papplSubscriptionEventString(event)); if (message) { va_copy(cap, ap); vsnprintf(text, sizeof(text), message, cap); va_end(cap); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_TEXT, "notify-text", NULL, text); } if (job && (event & PAPPL_EVENT_JOB_ALL)) { _papplJobCopyStateNoLock(job, IPP_TAG_EVENT_NOTIFICATION, n, NULL); if (event == PAPPL_EVENT_JOB_CREATED) { ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "job-name", NULL, job->name); ippAddString(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME, "job-originating-user-name", NULL, job->username); } } if (!sub->job && printer && (event & PAPPL_EVENT_PRINTER_ALL)) _papplPrinterCopyStateNoLock(printer, IPP_TAG_EVENT_NOTIFICATION, n, NULL, NULL); // TODO: add system event notifications if (printer) ippAddInteger(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "printer-up-time", (int)(time(NULL) - printer->start_time)); else ippAddInteger(n, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER, "system-up-time", (int)(time(NULL) - system->start_time)); cupsArrayAdd(sub->events, n); if (cupsArrayGetCount(sub->events) > PAPPL_MAX_EVENTS) { cupsArrayRemove(sub->events, cupsArrayGetFirst(sub->events)); sub->first_sequence ++; } _papplRWUnlock(sub); pthread_cond_broadcast(&system->subscription_cond); } } _papplRWUnlock(system); } // // '_papplSystemAddSubscription()' - Add a subscription to a system. // bool // O - `true` on success, `false` on error _papplSystemAddSubscription( pappl_system_t *system, // I - System pappl_subscription_t *sub, // I - Subscription int sub_id) // I - Subscription ID or `0` for new { if (!system || !sub || sub_id < 0) return (false); _papplRWLockWrite(system); if (!system->subscriptions) system->subscriptions = cupsArrayNew((cups_array_cb_t)compare_subscriptions, NULL, NULL, 0, NULL, NULL); if (!system->subscriptions || (system->max_subscriptions && (size_t)cupsArrayGetCount(system->subscriptions) >= system->max_subscriptions)) { _papplRWUnlock(system); return (false); } if (sub_id == 0) sub->subscription_id = ++ system->next_subscription_id; cupsArrayAdd(system->subscriptions, sub); _papplRWUnlock(system); return (true); } // // '_papplSystemCleanSubscriptions()' - Clean/expire subscriptions. // void _papplSystemCleanSubscriptions( pappl_system_t *system, // I - Subscription bool clean_all) // I - Clean all subscriptions? { pappl_subscription_t *sub; // Current subscription cups_array_t *expired = NULL;// Expired subscriptions time_t curtime; // Current time // Loop through all of the subscriptions and move all of the expired or // canceled subscriptions to a temporary array... _papplRWLockWrite(system); for (curtime = time(NULL), sub = (pappl_subscription_t *)cupsArrayGetFirst(system->subscriptions); sub; sub = (pappl_subscription_t *)cupsArrayGetNext(system->subscriptions)) { if (clean_all || sub->is_canceled || sub->expire <= curtime) { if (!expired) expired = cupsArrayNew(NULL, NULL, NULL, 0, NULL, NULL); cupsArrayAdd(expired, sub); cupsArrayRemove(system->subscriptions, sub); } } _papplRWUnlock(system); // Now clean up the expired subscriptions... for (sub = (pappl_subscription_t *)cupsArrayGetFirst(expired); sub; sub = (pappl_subscription_t *)cupsArrayGetNext(expired)) _papplSubscriptionDelete(sub); cupsArrayDelete(expired); } // // 'papplSystemFindSubscription()' - Find a subscription. // // This function finds the numbered event notification subscription on a system. // pappl_subscription_t * // O - Subscription or `NULL` if not found. papplSystemFindSubscription( pappl_system_t *system, // I - System int sub_id) // I - Subscription ID { pappl_subscription_t key, // Search key *match; // Match, if any if (!system || sub_id < 1) return (NULL); key.subscription_id = sub_id; _papplRWLockRead(system); match = (pappl_subscription_t *)cupsArrayFind(system->subscriptions, &key); _papplRWUnlock(system); return (match); } // // 'compare_subscriptions()' - Compare two subscriptions. // static int // O - Result of comparison compare_subscriptions( pappl_subscription_t *a, // I - First subscription pappl_subscription_t *b) // I - Second subscription { return (b->subscription_id - a->subscription_id); } pappl-1.4.9/pappl/system-webif.c000066400000000000000000003653101476704353100165610ustar00rootroot00000000000000// // System web interface functions for the Printer Application Framework // // Copyright © 2019-2024 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" #if !_WIN32 # include # include #endif // !_WIN32 #ifdef HAVE_OPENSSL # include # include # include # include # include #elif defined(HAVE_GNUTLS) # include # include #endif // HAVE_OPENSSL // // Local constants... // #define _PAPPL_MAX_NETWORKS 32 // Maximum number of networks that are supported // // Local types... // typedef enum _pappl_credtype_e // X.509 credential types { _PAPPL_CREDTYPE_RSA_2048_SHA256, // RSA with 2048-bit keys and SHA-256 hash _PAPPL_CREDTYPE_RSA_3072_SHA256, // RSA with 3072-bit keys and SHA-256 hash _PAPPL_CREDTYPE_RSA_4096_SHA256, // RSA with 4096-bit keys and SHA-256 hash _PAPPL_CREDTYPE_ECDSA_P256_SHA256, // ECDSA using the P-256 curve with SHA-256 hash _PAPPL_CREDTYPE_ECDSA_P384_SHA256, // ECDSA using the P-384 curve with SHA-256 hash _PAPPL_CREDTYPE_ECDSA_P521_SHA256 // ECDSA using the P-521 curve with SHA-256 hash } _pappl_credtype_t; typedef struct _pappl_system_dev_s // System device callback data { pappl_client_t *client; // Client connection const char *device_uri; // Current device URI } _pappl_system_dev_t; typedef struct _pappl_redirect_s // System redirection data { char ssid[128]; // SSID char psk[128]; // Passphrase size_t num_networks; // Number of networks pappl_network_t networks[_PAPPL_MAX_NETWORKS]; // Networks } _pappl_redirect_t; // // Local functions... // static size_t get_networks(size_t max_networks, pappl_network_t *networks); #ifdef HAVE_OPENSSL static bool openssl_add_ext(STACK_OF(X509_EXTENSION) *exts, int nid, const char *value); static X509_NAME *openssl_create_name(const char *organization, const char *org_unit, const char *locality, const char *state_province, const char *country, const char *common_name, const char *email); static EVP_PKEY *openssl_create_key(pappl_system_t *system, _pappl_credtype_t type); static X509_EXTENSION *openssl_create_san(const char *hostname, const char *localname); #endif // HAVE_OPENSSL static bool system_device_cb(const char *device_info, const char *device_uri, const char *device_id, void *data); static void system_footer(pappl_client_t *client); static void system_header(pappl_client_t *client, const char *title); static void system_redirect(pappl_client_t *client, const char *title, const char *resource, int seconds, pappl_timer_cb_t cb, _pappl_redirect_t *cb_data); static bool system_redirect_network_cb(pappl_system_t *system, _pappl_redirect_t *data); static bool system_redirect_wifi_cb(pappl_system_t *system, _pappl_redirect_t *data); #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) static bool tls_install_certificate(pappl_client_t *client, const char *crtfile, const char *keyfile); static bool tls_install_file(pappl_client_t *client, const char *dst, const char *src); static bool tls_make_certificate(pappl_client_t *client, cups_len_t num_form, cups_option_t *form); static bool tls_make_certsignreq(pappl_client_t *client, cups_len_t num_form, cups_option_t *form, char *crqpath, size_t crqsize); #endif // HAVE_OPENSSL || HAVE_GNUTLS // // Local globals... // #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) static const char * const countries[][2] = { // List of countries and their ISO 3166 2-letter codes { "AF", _PAPPL_LOC("Afghanistan") }, { "AX", _PAPPL_LOC("Åland Islands") }, { "AL", _PAPPL_LOC("Albania") }, { "DZ", _PAPPL_LOC("Algeria") }, { "AS", _PAPPL_LOC("American Samoa") }, { "AD", _PAPPL_LOC("Andorra") }, { "AO", _PAPPL_LOC("Angola") }, { "AI", _PAPPL_LOC("Anguilla") }, { "AQ", _PAPPL_LOC("Antarctica") }, { "AG", _PAPPL_LOC("Antigua and Barbuda") }, { "AR", _PAPPL_LOC("Argentina") }, { "AM", _PAPPL_LOC("Armenia") }, { "AW", _PAPPL_LOC("Aruba") }, { "AU", _PAPPL_LOC("Australia") }, { "AT", _PAPPL_LOC("Austria") }, { "AZ", _PAPPL_LOC("Azerbaijan") }, { "BS", _PAPPL_LOC("Bahamas") }, { "BH", _PAPPL_LOC("Bahrain") }, { "BD", _PAPPL_LOC("Bangladesh") }, { "BB", _PAPPL_LOC("Barbados") }, { "BY", _PAPPL_LOC("Belarus") }, { "BE", _PAPPL_LOC("Belgium") }, { "BZ", _PAPPL_LOC("Belize") }, { "BJ", _PAPPL_LOC("Benin") }, { "BM", _PAPPL_LOC("Bermuda") }, { "BT", _PAPPL_LOC("Bhutan") }, { "BO", _PAPPL_LOC("Bolivia (Plurinational State of)") }, { "BQ", _PAPPL_LOC("Bonaire, Sint Eustatius and Saba") }, { "BA", _PAPPL_LOC("Bosnia and Herzegovina") }, { "BW", _PAPPL_LOC("Botswana") }, { "BV", _PAPPL_LOC("Bouvet Island") }, { "BR", _PAPPL_LOC("Brazil") }, { "IO", _PAPPL_LOC("British Indian Ocean Territory") }, { "BN", _PAPPL_LOC("Brunei Darussalam") }, { "BG", _PAPPL_LOC("Bulgaria") }, { "BF", _PAPPL_LOC("Burkina Faso") }, { "BI", _PAPPL_LOC("Burundi") }, { "CV", _PAPPL_LOC("Cabo Verde") }, { "KH", _PAPPL_LOC("Cambodia") }, { "CM", _PAPPL_LOC("Cameroon") }, { "CA", _PAPPL_LOC("Canada") }, { "KY", _PAPPL_LOC("Cayman Islands") }, { "CF", _PAPPL_LOC("Central African Republic") }, { "TD", _PAPPL_LOC("Chad") }, { "CL", _PAPPL_LOC("Chile") }, { "CN", _PAPPL_LOC("China") }, { "CX", _PAPPL_LOC("Christmas Island") }, { "CC", _PAPPL_LOC("Cocos (Keeling) Islands") }, { "CO", _PAPPL_LOC("Colombia") }, { "KM", _PAPPL_LOC("Comoros") }, { "CD", _PAPPL_LOC("Congo, Democratic Republic of the") }, { "CG", _PAPPL_LOC("Congo") }, { "CK", _PAPPL_LOC("Cook Islands") }, { "CR", _PAPPL_LOC("Costa Rica") }, { "CI", _PAPPL_LOC("Côte d'Ivoire") }, { "HR", _PAPPL_LOC("Croatia") }, { "CU", _PAPPL_LOC("Cuba") }, { "CW", _PAPPL_LOC("Curaçao") }, { "CY", _PAPPL_LOC("Cyprus") }, { "CZ", _PAPPL_LOC("Czechia") }, { "DK", _PAPPL_LOC("Denmark") }, { "DJ", _PAPPL_LOC("Djibouti") }, { "DM", _PAPPL_LOC("Dominica") }, { "DO", _PAPPL_LOC("Dominican Republic") }, { "EC", _PAPPL_LOC("Ecuador") }, { "EG", _PAPPL_LOC("Egypt") }, { "SV", _PAPPL_LOC("El Salvador") }, { "GQ", _PAPPL_LOC("Equatorial Guinea") }, { "ER", _PAPPL_LOC("Eritrea") }, { "EE", _PAPPL_LOC("Estonia") }, { "SZ", _PAPPL_LOC("Eswatini") }, { "ET", _PAPPL_LOC("Ethiopia") }, { "FK", _PAPPL_LOC("Falkland Islands (Malvinas)") }, { "FO", _PAPPL_LOC("Faroe Islands") }, { "FJ", _PAPPL_LOC("Fiji") }, { "FI", _PAPPL_LOC("Finland") }, { "FR", _PAPPL_LOC("France") }, { "GF", _PAPPL_LOC("French Guiana") }, { "PF", _PAPPL_LOC("French Polynesia") }, { "TF", _PAPPL_LOC("French Southern Territories") }, { "GA", _PAPPL_LOC("Gabon") }, { "GM", _PAPPL_LOC("Gambia") }, { "GE", _PAPPL_LOC("Georgia") }, { "DE", _PAPPL_LOC("Germany") }, { "GH", _PAPPL_LOC("Ghana") }, { "GI", _PAPPL_LOC("Gibraltar") }, { "GR", _PAPPL_LOC("Greece") }, { "GL", _PAPPL_LOC("Greenland") }, { "GD", _PAPPL_LOC("Grenada") }, { "GP", _PAPPL_LOC("Guadeloupe") }, { "GU", _PAPPL_LOC("Guam") }, { "GT", _PAPPL_LOC("Guatemala") }, { "GG", _PAPPL_LOC("Guernsey") }, { "GW", _PAPPL_LOC("Guinea-Bissau") }, { "GN", _PAPPL_LOC("Guinea") }, { "GY", _PAPPL_LOC("Guyana") }, { "HT", _PAPPL_LOC("Haiti") }, { "HM", _PAPPL_LOC("Heard Island and McDonald Islands") }, { "VA", _PAPPL_LOC("Holy See") }, { "HN", _PAPPL_LOC("Honduras") }, { "HK", _PAPPL_LOC("Hong Kong") }, { "HU", _PAPPL_LOC("Hungary") }, { "IS", _PAPPL_LOC("Iceland") }, { "IN", _PAPPL_LOC("India") }, { "ID", _PAPPL_LOC("Indonesia") }, { "IR", _PAPPL_LOC("Iran (Islamic Republic of)") }, { "IQ", _PAPPL_LOC("Iraq") }, { "IE", _PAPPL_LOC("Ireland") }, { "IM", _PAPPL_LOC("Isle of Man") }, { "IL", _PAPPL_LOC("Israel") }, { "IT", _PAPPL_LOC("Italy") }, { "JM", _PAPPL_LOC("Jamaica") }, { "JP", _PAPPL_LOC("Japan") }, { "JE", _PAPPL_LOC("Jersey") }, { "JO", _PAPPL_LOC("Jordan") }, { "KZ", _PAPPL_LOC("Kazakhstan") }, { "KE", _PAPPL_LOC("Kenya") }, { "KI", _PAPPL_LOC("Kiribati") }, { "KP", _PAPPL_LOC("Korea (Democratic People's Republic of)") }, { "KR", _PAPPL_LOC("Korea, Republic of") }, { "KW", _PAPPL_LOC("Kuwait") }, { "KG", _PAPPL_LOC("Kyrgyzstan") }, { "LA", _PAPPL_LOC("Lao People's Democratic Republic") }, { "LV", _PAPPL_LOC("Latvia") }, { "LB", _PAPPL_LOC("Lebanon") }, { "LS", _PAPPL_LOC("Lesotho") }, { "LR", _PAPPL_LOC("Liberia") }, { "LY", _PAPPL_LOC("Libya") }, { "LI", _PAPPL_LOC("Liechtenstein") }, { "LT", _PAPPL_LOC("Lithuania") }, { "LU", _PAPPL_LOC("Luxembourg") }, { "MO", _PAPPL_LOC("Macao") }, { "MG", _PAPPL_LOC("Madagascar") }, { "MW", _PAPPL_LOC("Malawi") }, { "MY", _PAPPL_LOC("Malaysia") }, { "MV", _PAPPL_LOC("Maldives") }, { "ML", _PAPPL_LOC("Mali") }, { "MT", _PAPPL_LOC("Malta") }, { "MH", _PAPPL_LOC("Marshall Islands") }, { "MQ", _PAPPL_LOC("Martinique") }, { "MR", _PAPPL_LOC("Mauritania") }, { "MU", _PAPPL_LOC("Mauritius") }, { "YT", _PAPPL_LOC("Mayotte") }, { "MX", _PAPPL_LOC("Mexico") }, { "FM", _PAPPL_LOC("Micronesia (Federated States of)") }, { "MD", _PAPPL_LOC("Moldova, Republic of") }, { "MC", _PAPPL_LOC("Monaco") }, { "MN", _PAPPL_LOC("Mongolia") }, { "ME", _PAPPL_LOC("Montenegro") }, { "MS", _PAPPL_LOC("Montserrat") }, { "MA", _PAPPL_LOC("Morocco") }, { "MZ", _PAPPL_LOC("Mozambique") }, { "MM", _PAPPL_LOC("Myanmar") }, { "NA", _PAPPL_LOC("Namibia") }, { "NR", _PAPPL_LOC("Nauru") }, { "NP", _PAPPL_LOC("Nepal") }, { "NL", _PAPPL_LOC("Netherlands") }, { "NC", _PAPPL_LOC("New Caledonia") }, { "NZ", _PAPPL_LOC("New Zealand") }, { "NI", _PAPPL_LOC("Nicaragua") }, { "NE", _PAPPL_LOC("Niger") }, { "NG", _PAPPL_LOC("Nigeria") }, { "NU", _PAPPL_LOC("Niue") }, { "NF", _PAPPL_LOC("Norfolk Island") }, { "MK", _PAPPL_LOC("North Macedonia") }, { "MP", _PAPPL_LOC("Northern Mariana Islands") }, { "NO", _PAPPL_LOC("Norway") }, { "OM", _PAPPL_LOC("Oman") }, { "PK", _PAPPL_LOC("Pakistan") }, { "PW", _PAPPL_LOC("Palau") }, { "PS", _PAPPL_LOC("Palestine, State of") }, { "PA", _PAPPL_LOC("Panama") }, { "PG", _PAPPL_LOC("Papua New Guinea") }, { "PY", _PAPPL_LOC("Paraguay") }, { "PE", _PAPPL_LOC("Peru") }, { "PH", _PAPPL_LOC("Philippines") }, { "PN", _PAPPL_LOC("Pitcairn") }, { "PL", _PAPPL_LOC("Poland") }, { "PT", _PAPPL_LOC("Portugal") }, { "PR", _PAPPL_LOC("Puerto Rico") }, { "QA", _PAPPL_LOC("Qatar") }, { "RE", _PAPPL_LOC("Réunion") }, { "RO", _PAPPL_LOC("Romania") }, { "RU", _PAPPL_LOC("Russian Federation") }, { "RW", _PAPPL_LOC("Rwanda") }, { "BL", _PAPPL_LOC("Saint Barthélemy") }, { "SH", _PAPPL_LOC("Saint Helena, Ascension and Tristan da Cunha") }, { "KN", _PAPPL_LOC("Saint Kitts and Nevis") }, { "LC", _PAPPL_LOC("Saint Lucia") }, { "MF", _PAPPL_LOC("Saint Martin (French part)") }, { "PM", _PAPPL_LOC("Saint Pierre and Miquelon") }, { "VC", _PAPPL_LOC("Saint Vincent and the Grenadines") }, { "WS", _PAPPL_LOC("Samoa") }, { "SM", _PAPPL_LOC("San Marino") }, { "ST", _PAPPL_LOC("Sao Tome and Principe") }, { "SA", _PAPPL_LOC("Saudi Arabia") }, { "SN", _PAPPL_LOC("Senegal") }, { "RS", _PAPPL_LOC("Serbia") }, { "SC", _PAPPL_LOC("Seychelles") }, { "SL", _PAPPL_LOC("Sierra Leone") }, { "SG", _PAPPL_LOC("Singapore") }, { "SX", _PAPPL_LOC("Sint Maarten (Dutch part)") }, { "SK", _PAPPL_LOC("Slovakia") }, { "SI", _PAPPL_LOC("Slovenia") }, { "SB", _PAPPL_LOC("Solomon Islands") }, { "SO", _PAPPL_LOC("Somalia") }, { "ZA", _PAPPL_LOC("South Africa") }, { "GS", _PAPPL_LOC("South Georgia and the South Sandwich Islands") }, { "SS", _PAPPL_LOC("South Sudan") }, { "ES", _PAPPL_LOC("Spain") }, { "LK", _PAPPL_LOC("Sri Lanka") }, { "SD", _PAPPL_LOC("Sudan") }, { "SR", _PAPPL_LOC("Suriname") }, { "SJ", _PAPPL_LOC("Svalbard and Jan Mayen") }, { "SE", _PAPPL_LOC("Sweden") }, { "CH", _PAPPL_LOC("Switzerland") }, { "SY", _PAPPL_LOC("Syrian Arab Republic") }, { "TW", _PAPPL_LOC("Taiwan, Province of China") }, { "TJ", _PAPPL_LOC("Tajikistan") }, { "TZ", _PAPPL_LOC("Tanzania, United Republic of") }, { "TH", _PAPPL_LOC("Thailand") }, { "TL", _PAPPL_LOC("Timor-Leste") }, { "TG", _PAPPL_LOC("Togo") }, { "TK", _PAPPL_LOC("Tokelau") }, { "TO", _PAPPL_LOC("Tonga") }, { "TT", _PAPPL_LOC("Trinidad and Tobago") }, { "TN", _PAPPL_LOC("Tunisia") }, { "TR", _PAPPL_LOC("Turkey") }, { "TM", _PAPPL_LOC("Turkmenistan") }, { "TC", _PAPPL_LOC("Turks and Caicos Islands") }, { "TV", _PAPPL_LOC("Tuvalu") }, { "UG", _PAPPL_LOC("Uganda") }, { "UA", _PAPPL_LOC("Ukraine") }, { "AE", _PAPPL_LOC("United Arab Emirates") }, { "GB", _PAPPL_LOC("United Kingdom of Great Britain and Northern Ireland") }, { "UK", _PAPPL_LOC("United Kingdom") }, { "UM", _PAPPL_LOC("United States Minor Outlying Islands") }, { "US", _PAPPL_LOC("United States of America") }, { "UY", _PAPPL_LOC("Uruguay") }, { "UZ", _PAPPL_LOC("Uzbekistan") }, { "VU", _PAPPL_LOC("Vanuatu") }, { "VE", _PAPPL_LOC("Venezuela (Bolivarian Republic of)") }, { "VN", _PAPPL_LOC("Viet Nam") }, { "VG", _PAPPL_LOC("Virgin Islands (British)") }, { "VI", _PAPPL_LOC("Virgin Islands (U.S.)") }, { "WF", _PAPPL_LOC("Wallis and Futuna") }, { "EH", _PAPPL_LOC("Western Sahara") }, { "YE", _PAPPL_LOC("Yemen") }, { "ZM", _PAPPL_LOC("Zambia") }, { "ZW", _PAPPL_LOC("Zimbabwe") } }; #endif // HAVE_OPENSSL || HAVE_GNUTLS // // '_papplSystemAddPrinter()' - Add a printer // void _papplSystemWebAddPrinter( pappl_client_t *client, pappl_system_t *system) { cups_len_t i; // Looping var const char *status = NULL; // Status message, if any char printer_name[128] = "", // Printer Name driver_name[128] = "", // Driver Name device_uri[1024] = "", // Device URI *device_id = NULL, // Device ID hostname[256] = "", // Hostname hostvalue[256], // Hostname[:port] *ptr; // Pointer into string int port = 0; // Default port for Socket printing _pappl_system_dev_t devdata; // Device callback data static const char *hostname_pattern = // IP address or hostname pattern // Hostname per RFC 1123 "^((\\s*((?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\\b-){0,61}[0-9A-Za-z])?(?:\\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\\b-){0,61}[0-9A-Za-z])?)*\\.?)\\s*)" "|" // IPv4 address "(\\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\\s*)" "|" // IPv6 address "(\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*)" // Optional port number ")(|:[0-9]+)$"; if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { const char *value; // Form value cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { http_addrlist_t *list; // Address list if ((value = cupsGetOption("printer_name", num_form, form)) != NULL) papplCopyString(printer_name, value, sizeof(printer_name)); if ((value = cupsGetOption("driver_name", num_form, form)) != NULL) papplCopyString(driver_name, value, sizeof(driver_name)); if ((value = cupsGetOption("device_uri", num_form, form)) != NULL) { papplCopyString(device_uri, value, sizeof(device_uri)); if ((device_id = strchr(device_uri, '|')) != NULL) *device_id++ = '\0'; } if (!strcmp(device_uri, "socket")) { // Make URI using hostname if ((value = cupsGetOption("hostname", num_form, form)) == NULL) { status = _PAPPL_LOC("Please enter a hostname or IP address for the printer."); device_uri[0] = '\0'; } else { // Break out the port number, if present... papplCopyString(hostname, value, sizeof(hostname)); if ((ptr = strrchr(hostname, ':')) != NULL && !strchr(ptr, ']')) { char *end; // End of value *ptr++ = '\0'; port = (int)strtol(ptr, &end, 10); if (errno == ERANGE || *end || port <= 0 || port > 65535) { status = _PAPPL_LOC("Bad port number."); device_uri[0] = '\0'; } } if (!status) { // Then see if we can lookup the hostname or IP address (port number // isn't used here...) if ((list = httpAddrGetList(hostname, AF_UNSPEC, "9100")) == NULL) { status = _PAPPL_LOC("Unable to lookup address."); } else { httpAddrFreeList(list); httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "socket", NULL, hostname, port, "/"); } } } } if (!printer_name[0]) { status = _PAPPL_LOC("Please enter a printer name."); } else if (!device_uri[0]) { status = _PAPPL_LOC("Please select a device."); } else if (!driver_name[0]) { status = _PAPPL_LOC("Please select a driver."); } else if (!status) { pappl_printer_t *printer = papplPrinterCreate(system, 0, printer_name, driver_name, device_id, device_uri); // New printer if (printer) { // Advertise the printer... _papplRWLockWrite(printer); _papplPrinterRegisterDNSSDNoLock(printer); _papplRWUnlock(printer); // Redirect the client to the printer's status page... papplClientRespondRedirect(client, HTTP_STATUS_FOUND, printer->uriname); cupsFreeOptions(num_form, form); return; } switch (errno) { case EEXIST : status = _PAPPL_LOC("A printer with that name already exists."); break; case EIO : status = _PAPPL_LOC("Unable to use that driver."); break; case EINVAL : status = _PAPPL_LOC("Printer names must start with a letter or underscore and cannot contain special characters."); break; default : status = strerror(errno); break; } } } cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Add Printer")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" "
\n" "
\n", papplClientGetLocString(client, _PAPPL_LOC("Add Printer"))); system_footer(client); } // // '_papplSystemWebConfig()' - Show the system configuration page. // void _papplSystemWebConfig( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { char dns_sd_name[64], // DNS-SD name location[128], // Location geo_location[128], // Geo-location latitude organization[128], // Organization org_unit[128]; // Organizational unit pappl_contact_t contact; // Contact info const char *status = NULL; // Status message, if any if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) status = _PAPPL_LOC("Invalid form data."); else if (!papplClientIsValidForm(client, (int)num_form, form)) status = _PAPPL_LOC("Invalid form submission."); else { _papplSystemWebConfigFinalize(system, num_form, form); status = _PAPPL_LOC("Changes saved."); } cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Configuration")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); _papplClientHTMLInfo(client, true, papplSystemGetDNSSDName(system, dns_sd_name, sizeof(dns_sd_name)), papplSystemGetLocation(system, location, sizeof(location)), papplSystemGetGeoLocation(system, geo_location, sizeof(geo_location)), papplSystemGetOrganization(system, organization, sizeof(organization)), papplSystemGetOrganizationalUnit(system, org_unit, sizeof(org_unit)), papplSystemGetContact(system, &contact)); papplClientHTMLPuts(client, "
\n" "
\n"); system_footer(client); } // // '_papplSystemWebConfigFinalize()' - Save the changes to the system configuration. // void _papplSystemWebConfigFinalize( pappl_system_t *system, // I - System cups_len_t num_form, // I - Number of form variables cups_option_t *form) // I - Form variables { const char *value, // Form value *geo_lat, // Geo-location latitude *geo_lon, // Geo-location longitude *contact_name, // Contact name *contact_email, // Contact email *contact_tel; // Contact telephone number if ((value = cupsGetOption("dns_sd_name", num_form, form)) != NULL) papplSystemSetDNSSDName(system, *value ? value : NULL); if ((value = cupsGetOption("location", num_form, form)) != NULL) papplSystemSetLocation(system, *value ? value : NULL); geo_lat = cupsGetOption("geo_location_lat", num_form, form); geo_lon = cupsGetOption("geo_location_lon", num_form, form); if (geo_lat && geo_lon) { char uri[1024]; // "geo:" URI if (*geo_lat && *geo_lon) { snprintf(uri, sizeof(uri), "geo:%g,%g", strtod(geo_lat, NULL), strtod(geo_lon, NULL)); papplSystemSetGeoLocation(system, uri); } else papplSystemSetGeoLocation(system, NULL); } if ((value = cupsGetOption("organization", num_form, form)) != NULL) papplSystemSetOrganization(system, *value ? value : NULL); if ((value = cupsGetOption("organizational_unit", num_form, form)) != NULL) papplSystemSetOrganizationalUnit(system, *value ? value : NULL); contact_name = cupsGetOption("contact_name", num_form, form); contact_email = cupsGetOption("contact_email", num_form, form); contact_tel = cupsGetOption("contact_telephone", num_form, form); if (contact_name || contact_email || contact_tel) { pappl_contact_t contact; // Contact info memset(&contact, 0, sizeof(contact)); if (contact_name) papplCopyString(contact.name, contact_name, sizeof(contact.name)); if (contact_email) papplCopyString(contact.email, contact_email, sizeof(contact.email)); if (contact_tel) papplCopyString(contact.telephone, contact_tel, sizeof(contact.telephone)); papplSystemSetContact(system, &contact); } } // // '_papplSystemWebHome()' - Show the system home page. // void _papplSystemWebHome( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { char dns_sd_name[64], // System DNS-SD name location[128], // System location geo_location[128], // System geo-location organization[256], // System organization org_unit[256]; // System organizational unit pappl_contact_t contact; // System contact system_header(client, NULL); papplClientHTMLPrintf(client, "
\n" "
\n" "

%s %s

\n", papplClientGetLocString(client, _PAPPL_LOC("Configuration")), _papplClientGetAuthWebScheme(client), client->host_field, client->host_port, papplClientGetLocString(client, _PAPPL_LOC("Change"))); _papplClientHTMLPutLinks(client, system->links, PAPPL_LOPTIONS_CONFIGURATION); _papplClientHTMLInfo(client, false, papplSystemGetDNSSDName(system, dns_sd_name, sizeof(dns_sd_name)), papplSystemGetLocation(system, location, sizeof(location)), papplSystemGetGeoLocation(system, geo_location, sizeof(geo_location)), papplSystemGetOrganization(system, organization, sizeof(organization)), papplSystemGetOrganizationalUnit(system, org_unit, sizeof(org_unit)), papplSystemGetContact(system, &contact)); _papplSystemWebSettings(client); papplClientHTMLPrintf(client, "
\n" "
\n" "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("Printers"))); _papplClientHTMLPutLinks(client, system->links, PAPPL_LOPTIONS_PRINTER); papplSystemIteratePrinters(system, (pappl_printer_cb_t)_papplPrinterWebIteratorCallback, client); papplClientHTMLPuts(client, "
\n" "
\n"); system_footer(client); } // // '_papplSystemWebLogFile()' - Return the log file as requested // void _papplSystemWebLogFile( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_GET) { http_status_t code; // HTTP status of response struct stat loginfo; // Log information ssize_t bytes; // Bytes read/written size_t length = 0; // Log length const char *value; // Range Field value char *rangeptr; // Pointer into range... char buffer[8192]; // Copy buffer int fd; // Resource file descriptor long low = 0, // Log lower range high = -1; // Log upper range value = httpGetField(client->http, HTTP_FIELD_RANGE); // If range exists, send log content from low to high if (value && *value && (rangeptr = strstr(value, "bytes=")) != NULL) { if ((low = strtol(rangeptr + 6, &rangeptr, 10)) < 0) low = 0; else if (rangeptr && *rangeptr == '-' && isdigit(rangeptr[1] & 255)) high = strtol(rangeptr + 1, NULL, 10); } if ((fd = open(system->log_file, O_RDONLY)) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to open log file '%s': %s", system->log_file, strerror(errno)); papplClientRespond(client, HTTP_STATUS_SERVER_ERROR, NULL, NULL, 0, 0); return; } // Get log file info if (fstat(fd, &loginfo)) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to access log file '%s': %s", system->log_file, strerror(errno)); papplClientRespond(client, HTTP_STATUS_SERVER_ERROR, NULL, NULL, 0, 0); close(fd); return; } // Write the log in the range if (low > loginfo.st_size) { length = (size_t)loginfo.st_size; code = HTTP_STATUS_OK; low = 0; } else if (high < 0) { length = (size_t)loginfo.st_size - (size_t)low; code = HTTP_STATUS_PARTIAL_CONTENT; } else { length = (size_t)(high - low); code = HTTP_STATUS_PARTIAL_CONTENT; } httpSetLength(client->http, length); httpSetField(client->http, HTTP_FIELD_SERVER, papplSystemGetServerHeader(system)); httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, "text/plain"); // Seek to position low in log if (lseek(fd, (off_t)low, SEEK_CUR) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to seek to offset %ld in log file '%s': %s", low, system->log_file, strerror(errno)); papplClientRespond(client, HTTP_STATUS_SERVER_ERROR, NULL, NULL, 0, 0); close(fd); return; } if (!httpWriteResponse(client->http, code)) { close(fd); return; } papplLogClient(client, PAPPL_LOGLEVEL_INFO, "%s %s %d", code == HTTP_STATUS_OK ? "OK" : "Partial Content", "text/plain", (int)length); // Read buffer and write to client while (length > 0 && (bytes = read(fd, buffer, sizeof(buffer))) > 0) { if ((size_t)bytes > length) bytes = (ssize_t)length; length -= (size_t)bytes; httpWrite(client->http, buffer, (size_t)bytes); } httpWrite(client->http, "", 0); close(fd); } else papplClientRespond(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0, 0); } // // '_papplSystemWebLogs()' - Show the system logs // void _papplSystemWebLogs( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { pappl_loglevel_t i, // Looping var loglevel; // Current log level const char *status = NULL; // Status message, if any static const char * const levels[] = // Log level strings { _PAPPL_LOC("Debugging"), _PAPPL_LOC("Informational"), _PAPPL_LOC("Warning"), _PAPPL_LOC("Errors"), _PAPPL_LOC("Fatal Errors/Conditions"), }; if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { const char *value; // Form value cups_len_t num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { if ((value = cupsGetOption("log_level", num_form, form)) != NULL) { // Get log level and save it... for (loglevel = PAPPL_LOGLEVEL_DEBUG; loglevel <= PAPPL_LOGLEVEL_FATAL; loglevel ++) { if (!strcmp(value, levels[loglevel])) break; } if (loglevel <= PAPPL_LOGLEVEL_FATAL) { papplSystemSetLogLevel(system, loglevel); status = _PAPPL_LOC("Changes Saved."); } else status = _PAPPL_LOC("Please select a valid log level."); } else { status = _PAPPL_LOC("Please select a valid log level."); } } cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Logs")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" "
%s:%s
\n" " \n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Change Log Level")), papplClientGetLocString(client, _PAPPL_LOC("Log File")), papplClientGetLocString(client, _PAPPL_LOC("Download Log File"))); system_footer(client); } // // '_papplSystemWebNetwork()' - Show the system network configuration page. // void _papplSystemWebNetwork( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { const char *status = NULL; // Status message, if any pappl_loc_t *loc; // Localization char hostname[256]; // Hostname size_t i, // Looping var num_networks; // Number of network interfaces pappl_network_t networks[_PAPPL_MAX_NETWORKS], // Network interfaces *network; // Current network if (!papplClientHTMLAuthorize(client)) return; if (client->system->network_get_cb) num_networks = (client->system->network_get_cb)(client->system, client->system->network_cbdata, sizeof(networks) / sizeof(networks[0]), networks); else num_networks = get_networks(sizeof(networks) / sizeof(networks[0]), networks); if (client->operation == HTTP_STATE_POST) { int j; // Looping var cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables char name[128]; // Variable name const char *value; // Form variable value _pappl_redirect_t data; // Redirection data if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if ((value = cupsGetOption("hostname", num_form, form)) != NULL) { // Set hostname and save it... papplSystemSetHostName(client->system, value); // Then look for network changes if (client->system->network_set_cb && num_networks > 0) { for (i = num_networks, network = networks; i > 0; i --, network ++) { snprintf(name, sizeof(name), "%s.domain", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) papplCopyString(network->domain, value, sizeof(network->domain)); snprintf(name, sizeof(name), "%s.config4", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { pappl_netconf_t config = (pappl_netconf_t)atoi(value); // Configuration value if (config < PAPPL_NETCONF_OFF || config > PAPPL_NETCONF_MANUAL) { status = _PAPPL_LOC("Invalid network configuration."); goto post_done; } network->config4 = config; } snprintf(name, sizeof(name), "%s.addr4", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { if (inet_pton(AF_INET, value, &network->addr4.ipv4.sin_addr) <= 0) { status = _PAPPL_LOC("Invalid IPv4 address."); goto post_done; } } snprintf(name, sizeof(name), "%s.mask4", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { if (inet_pton(AF_INET, value, &network->mask4.ipv4.sin_addr) <= 0) { status = _PAPPL_LOC("Invalid IPv4 netmask."); goto post_done; } } snprintf(name, sizeof(name), "%s.gateway4", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { if (*value) inet_pton(AF_INET, value, &network->gateway4.ipv4.sin_addr); else network->gateway4.ipv4.sin_addr.s_addr = 0; } for (j = 0; j < 2; j ++) { network->dns[j].ipv4.sin_family = AF_INET; network->dns[j].ipv4.sin_addr.s_addr = 0; snprintf(name, sizeof(name), "%s.dns_%d", network->ident, j + 1); if ((value = cupsGetOption(name, num_form, form)) != NULL) { if (*value) { if (strchr(value, ':') != NULL) { network->dns[j].ipv6.sin6_family = AF_INET6; inet_pton(AF_INET6, value, &network->dns[j].ipv6.sin6_addr); } else { network->dns[j].ipv4.sin_family = AF_INET; inet_pton(AF_INET, value, &network->dns[j].ipv4.sin_addr); } } } } snprintf(name, sizeof(name), "%s.config6", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { pappl_netconf_t config = (pappl_netconf_t)atoi(value); // Configuration value if (config < PAPPL_NETCONF_OFF || config > PAPPL_NETCONF_MANUAL) { status = _PAPPL_LOC("Invalid network configuration."); goto post_done; } network->config6 = config; } snprintf(name, sizeof(name), "%s.addr6", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { network->addr6.ipv6.sin6_family = AF_INET6; if (*value) { // Parse IPv6 address if (inet_pton(AF_INET6, value, &network->addr6.ipv6.sin6_addr) <= 0) { status = _PAPPL_LOC("Invalid IPv6 address."); goto post_done; } } else { // Clear IPv6 address... memset(&network->addr6.ipv6.sin6_addr, 0, sizeof(network->addr6.ipv6.sin6_addr)); } } snprintf(name, sizeof(name), "%s.prefix6", network->ident); if ((value = cupsGetOption(name, num_form, form)) != NULL) { int intvalue = atoi(value); if (intvalue > 0 && intvalue <= 128) { network->prefix6 = (unsigned)intvalue; } else { status = _PAPPL_LOC("Invalid IPv6 prefix length."); goto post_done; } } } data.num_networks = num_networks; memcpy(data.networks, networks, num_networks * sizeof(pappl_network_t)); system_redirect(client, _PAPPL_LOC("Updating Network Configuration"), "/network", 10, (pappl_timer_cb_t)system_redirect_network_cb, &data); cupsFreeOptions(num_form, form); return; } if (!status) status = _PAPPL_LOC("Changes saved."); } else { status = _PAPPL_LOC("Unknown form request."); } post_done: cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Networking")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPuts(client, " \n" " \n"); if (system->wifi_status_cb) { pappl_wifi_t wifi_info; // Wi-Fi info static const char * const wifi_statuses[] = { // Wi-Fi state values _PAPPL_LOC("off"), _PAPPL_LOC("not configured"), _PAPPL_LOC("not visible"), _PAPPL_LOC("unable to join"), _PAPPL_LOC("joining"), _PAPPL_LOC("on") }; if ((system->wifi_status_cb)(system, system->wifi_cbdata, &wifi_info)) { papplClientHTMLPrintf(client, " \n", papplClientGetLocString(client, _PAPPL_LOC("Change Wi-Fi Network"))); else papplClientHTMLPuts(client, "\n"); } } papplSystemGetHostName(system, hostname, sizeof(hostname)); papplClientHTMLPrintf(client, " \n", hostname, hostname); else papplClientHTMLPrintf(client, "\n", hostname, papplClientGetLocString(client, _PAPPL_LOC("Change Hostname"))); loc = papplClientGetLoc(client); if (num_networks > 0) { size_t j; // Looping var char temp[256]; // Address string static const char * const configs[] = { _PAPPL_LOC("Off"), _PAPPL_LOC("DHCP"), _PAPPL_LOC("DHCP w/Manual Address"), _PAPPL_LOC("Manual Configuration") }; papplClientHTMLPuts(client, " \n"); for (i = num_networks, network = networks; i > 0; i --, network ++) { papplClientHTMLPrintf(client, " \n"); } } papplClientHTMLPuts(client, " \n" "
%s:%s (%s)", papplClientGetLocString(client, _PAPPL_LOC("Wi-Fi Network")), wifi_info.ssid, papplClientGetLocString(client, wifi_statuses[wifi_info.state - PAPPL_WIFI_STATE_OFF])); if (system->wifi_list_cb) papplClientHTMLPrintf(client, " %s
", papplClientGetLocString(client, _PAPPL_LOC("Hostname"))); if (system->is_listenhost) papplClientHTMLPrintf(client, "%s
%s:", papplLocGetString(loc, network->name)); if (client->system->network_set_cb) { papplClientHTMLPrintf(client, "%s:
"); } papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("IPv4 Address"))); inet_ntop(AF_INET, &network->addr4.ipv4.sin_addr, temp, sizeof(temp)); if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, temp, network->config4 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); else papplClientHTMLPrintf(client, "%s
", temp); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("IPv4 Netmask"))); inet_ntop(AF_INET, &network->mask4.ipv4.sin_addr, temp, sizeof(temp)); if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, temp, network->config4 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); else papplClientHTMLPrintf(client, "%s
", temp); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("IPv4 Gateway"))); inet_ntop(AF_INET, &network->gateway4.ipv4.sin_addr, temp, sizeof(temp)); if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, temp, network->config4 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); else papplClientHTMLPrintf(client, "%s
", temp); papplClientHTMLPuts(client, " 
"); if (client->system->network_set_cb) { // IPv6 configuration mode... papplClientHTMLPrintf(client, "%s:
"); } inet_ntop(AF_INET6, &network->linkaddr6.ipv6.sin6_addr, temp, sizeof(temp)); papplClientHTMLPrintf(client, "%s: %s
", papplLocGetString(loc, _PAPPL_LOC("IPv6 Link-Local")), temp); if (client->system->network_set_cb) { // IPv6 routable address... inet_ntop(AF_INET6, &network->addr6.ipv6.sin6_addr, temp, sizeof(temp)); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("IPv6 Address"))); papplClientHTMLPrintf(client, "
", network->ident, temp, network->config6 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("IPv6 Prefix Length"))); papplClientHTMLPrintf(client, "
", network->ident, network->prefix6 ? network->prefix6 : 64, network->config6 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); } papplClientHTMLPrintf(client, " 
%s: ", papplLocGetString(loc, _PAPPL_LOC("Domain Name"))); if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, network->domain); else if (network->domain[0]) papplClientHTMLPrintf(client, "%s
", network->domain); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("Primary DNS"))); if (network->dns[0].addr.sa_family == AF_INET6) inet_ntop(AF_INET6, &network->dns[0].ipv6.sin6_addr, temp, sizeof(temp)); else inet_ntop(AF_INET, &network->dns[0].ipv4.sin_addr, temp, sizeof(temp)); if (!strcmp(temp, "0.0.0.0")) temp[0] = '\0'; if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, temp, network->config4 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); else papplClientHTMLPrintf(client, "%s
", temp); papplClientHTMLPrintf(client, "%s: ", papplLocGetString(loc, _PAPPL_LOC("Secondary DNS"))); if (network->dns[1].addr.sa_family == AF_INET6) inet_ntop(AF_INET6, &network->dns[1].ipv6.sin6_addr, temp, sizeof(temp)); else inet_ntop(AF_INET, &network->dns[1].ipv4.sin_addr, temp, sizeof(temp)); if (!strcmp(temp, "0.0.0.0")) temp[0] = '\0'; if (client->system->network_set_cb) papplClientHTMLPrintf(client, "
", network->ident, temp, network->config4 < PAPPL_NETCONF_DHCP_MANUAL ? " disabled" : ""); else papplClientHTMLPrintf(client, "%s
", temp); if (client->system->network_set_cb) papplClientHTMLPrintf(client, "", _PAPPL_LOC("Change Network Settings")); papplClientHTMLPuts(client, "
\n" " \n"); _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_NETWORK); papplClientHTMLPuts(client, "
\n"); system_footer(client); } // // '_papplSystemWebSecurity()' - Show the system security (users/password) page. // void _papplSystemWebSecurity( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { const char *status = NULL; // Status message, if any #if !_WIN32 struct group *grp; // Current group #endif // !_WIN32 if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if (!client->system->auth_service) { const char *old_password, // Old password (if any) *new_password, // New password *new_password2; // New password again char hash[1024]; // Hash of password old_password = cupsGetOption("old_password", num_form, form); new_password = cupsGetOption("new_password", num_form, form); new_password2 = cupsGetOption("new_password2", num_form, form); if (system->password_hash[0] && (!old_password || !_papplIsEqual(system->password_hash, papplSystemHashPassword(system, system->password_hash, old_password, hash, sizeof(hash))))) { status = _PAPPL_LOC("Wrong old password."); } else if (!new_password || !new_password2 || !_papplIsEqual(new_password, new_password2)) { status = _PAPPL_LOC("Passwords do not match."); } else { const char *passptr; // Pointer into password bool have_lower, // Do we have a lowercase letter? have_upper, // Do we have an uppercase letter? have_digit; // Do we have a number? for (passptr = new_password, have_lower = false, have_upper = false, have_digit = false; *passptr; passptr ++) { if (isdigit(*passptr & 255)) have_digit = true; else if (islower(*passptr & 255)) have_lower = true; else if (isupper(*passptr & 255)) have_upper = true; } if (!have_digit || !have_lower || !have_upper || strlen(new_password) < 8) { status = _PAPPL_LOC("Password must be at least eight characters long and contain at least one uppercase letter, one lowercase letter, and one digit."); } else { papplSystemHashPassword(system, NULL, new_password, hash, sizeof(hash)); papplSystemSetPassword(system, hash); status = _PAPPL_LOC("Password changed."); } } } #if !_WIN32 else { const char *group; // Current group char buffer[8192]; // Buffer for strings struct group grpbuf; // Group buffer grp = NULL; if ((group = cupsGetOption("admin_group", num_form, form)) != NULL) { if (strcmp(group, "") && (getgrnam_r(group, &grpbuf, buffer, sizeof(buffer), &grp) || !grp)) status = _PAPPL_LOC("Bad administration group."); else papplSystemSetAdminGroup(system, group); } if ((group = cupsGetOption("print_group", num_form, form)) != NULL) { if (strcmp(group, "") && (getgrnam_r(group, &grpbuf, buffer, sizeof(buffer), &grp) || !grp)) { status = _PAPPL_LOC("Bad print group."); } else { papplSystemSetDefaultPrintGroup(system, group); papplSystemIteratePrinters(system, (pappl_printer_cb_t)papplPrinterSetPrintGroup, (void *)group); } } if (!status) status = _PAPPL_LOC("Group changes saved."); } #endif // !_WIN32 cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Security")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLPuts(client, " \n" " \n" "
\n"); #if !_WIN32 if (system->auth_service) { // Show Users pane for group controls papplClientHTMLPrintf(client, "
\n" "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("Users"))); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Save Changes"))); } else #endif // !_WIN32 if (system->password_hash[0]) { // Show simple access password update form... papplClientHTMLPrintf(client, "
\n" "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("Change Access Password"))); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Current Password")), papplClientGetLocString(client, _PAPPL_LOC("New Password")), papplClientGetLocString(client, _PAPPL_LOC(/*Password Requirements*/"8+, upper+lower+digit")), papplClientGetLocString(client, _PAPPL_LOC("New Password (again)")), papplClientGetLocString(client, _PAPPL_LOC(/*Password Requirements*/"8+, upper+lower+digit")), papplClientGetLocString(client, _PAPPL_LOC("Change Access Password"))); } else { // Show simple access password initial setting form... papplClientHTMLPrintf(client, "
\n" "

%s

\n", papplClientGetLocString(client, _PAPPL_LOC("Set Access Password"))); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Password")), papplClientGetLocString(client, _PAPPL_LOC(/*Password Requirements*/"8+, upper+lower+digit")), papplClientGetLocString(client, _PAPPL_LOC("Password (again)")), papplClientGetLocString(client, _PAPPL_LOC(/*Password Requirements*/"8+, upper+lower+digit")), papplClientGetLocString(client, _PAPPL_LOC("Set Access Password"))); } _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_SECURITY); // Finish up... papplClientHTMLPuts(client, "
\n"); system_footer(client); } // // '_papplSystemWebSettings()' - Show the system settings panel, as needed. // void _papplSystemWebSettings( pappl_client_t *client) // I - Client { cups_len_t i, // Looping var count; // Number of links _pappl_link_t *l; // Current link for (i = 0, count = cupsArrayGetCount(client->system->links); i < count; i ++) { l = (_pappl_link_t *)cupsArrayGetElement(client->system->links, i); if (!l) continue; if (l->options & PAPPL_LOPTIONS_OTHER) break; } if (i < count) { papplClientHTMLPrintf(client, "

%s

\n" "
", papplClientGetLocString(client, _PAPPL_LOC("Other Settings"))); _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_OTHER); papplClientHTMLPuts(client, "
\n"); } if ((client->system->options & PAPPL_SOPTIONS_WEB_LOG) && client->system->log_file && strcmp(client->system->log_file, "-") && strcmp(client->system->log_file, "syslog")) { papplClientHTMLPrintf(client, "

%s

\n" "
", papplClientGetLocString(client, _PAPPL_LOC("Logging"))); _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_LOGGING); papplClientHTMLPuts(client, "
\n"); } } #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) // // '_papplSystemWebTLSInstall()' - Show the system TLS certificate installation page. // void _papplSystemWebTLSInstall( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { const char *status = NULL; // Status message, if any (void)system; if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else { const char *crtfile, // Certificate file *keyfile; // Private key file char filename[1024]; // Filename crtfile = cupsGetOption("certificate", num_form, form); keyfile = cupsGetOption("privatekey", num_form, form); if (!keyfile) { char hostname[256], // Hostname *hostptr; // Pointer into hostname papplCopyString(hostname, client->system->hostname, sizeof(hostname)); if ((hostptr = strchr(hostname, '.')) != NULL) *hostptr = '\0'; snprintf(filename, sizeof(filename), "%s/%s.key", client->system->directory, hostname); if (!access(filename, R_OK)) keyfile = filename; else status = _PAPPL_LOC("Missing private key."); } if (!status) { if (tls_install_certificate(client, crtfile, keyfile)) status = _PAPPL_LOC("Certificate installed."); else status = _PAPPL_LOC("Invalid certificate or private key."); } } cupsFreeOptions(num_form, form); } system_header(client, _PAPPL_LOC("Install TLS Certificate")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLPuts(client, " \n" " \n" "
\n"); papplClientHTMLStartForm(client, client->uri, true); papplClientHTMLPrintf(client, "
\n" "

%s

\n" " \n" " \n" " \n" " \n" " \n" " \n" "
(PEM-encoded)
%s
\n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("This form will install a trusted TLS certificate you have obtained from a Certificate Authority ('CA'). Once installed, it will be used immediately.")), papplClientGetLocString(client, _PAPPL_LOC("Certificate")), papplClientGetLocString(client, _PAPPL_LOC("Private Key")), papplClientGetLocString(client, _PAPPL_LOC("(PEM-encoded, leave unselected to use the key from the last signing request)")), papplClientGetLocString(client, _PAPPL_LOC("Install Certificate"))); _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_TLS); papplClientHTMLPuts(client, "
\n"); system_footer(client); } // // '_papplSystemWebTLSNew()' - Show the system TLS certificate/request creation page. // void _papplSystemWebTLSNew( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { int i; // Looping var const char *status = NULL; // Status message, if any char crqpath[256] = ""; // Certificate request file, if any char organization[256], // Organization org_unit[256]; // Organizational unit pappl_contact_t contact; // Contact info bool success = false; // Were we successful? if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if (!strcmp(client->uri, "/tls-new-crt")) { if (tls_make_certificate(client, num_form, form)) { status = _PAPPL_LOC("Certificate created."); success = true; } else status = _PAPPL_LOC("Unable to create certificate."); } else { if (tls_make_certsignreq(client, num_form, form, crqpath, sizeof(crqpath))) { status = _PAPPL_LOC("Certificate request created."); success = true; } else status = _PAPPL_LOC("Unable to create certificate request."); } cupsFreeOptions(num_form, form); } if (!strcmp(client->uri, "/tls-new-crt")) system_header(client, _PAPPL_LOC("Create New TLS Certificate")); else system_header(client, _PAPPL_LOC("Create TLS Certificate Request")); if (status) { papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); if (crqpath[0]) papplClientHTMLPrintf(client, "

%s

\n", crqpath, papplClientGetLocString(client, _PAPPL_LOC("Download Certificate Request File"))); if (success) { papplClientHTMLPuts(client, " \n" " \n"); system_footer(client); return; } } papplClientHTMLPuts(client, " \n" " \n" "
\n"); papplClientHTMLStartForm(client, client->uri, false); if (!strcmp(client->uri, "/tls-new-crt")) papplClientHTMLPrintf(client, "
\n" "

%s

\n" " \n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("This form creates a new 'self-signed' TLS certificate for secure printing. Self-signed certificates are not automatically trusted by web browsers.")), papplClientGetLocString(client, _PAPPL_LOC("Duration (years)"))); else papplClientHTMLPrintf(client, "
\n" "

%s

\n" "
\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("This form creates a certificate signing request ('CSR') that you can send to a Certificate Authority ('CA') to obtain a trusted TLS certificate. The private key is saved separately for use with the certificate you get from the CA."))); papplSystemGetContact(system, &contact); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Create New Certificate"))); else papplClientHTMLPrintf(client, "\n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Create Certificate Signing Request"))); papplClientHTMLPuts(client, " \n" "
\n" "
\n" " \n" " \n"); _papplClientHTMLPutLinks(client, client->system->links, PAPPL_LOPTIONS_TLS); papplClientHTMLPuts(client, "
\n"); system_footer(client); } #endif // HAVE_OPENSSL || HAVE_GNUTLS // // '_papplSystemWebWiFi()' - Show the Wi-Fi network UI. // void _papplSystemWebWiFi( pappl_client_t *client, // I - Client pappl_system_t *system) // I - System { cups_len_t i, // Looping var num_ssids; // Number of Wi-Fi networks cups_dest_t *ssids; // Wi-Fi networks const char *status = NULL; // Status message, if any if (!papplClientHTMLAuthorize(client)) return; if (client->operation == HTTP_STATE_POST) { cups_len_t num_form = 0; // Number of form variable cups_option_t *form = NULL; // Form variables const char *ssid, // Wi-Fi network name *psk; // Wi-Fi password if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0) { status = _PAPPL_LOC("Invalid form data."); } else if (!papplClientIsValidForm(client, (int)num_form, form)) { status = _PAPPL_LOC("Invalid form submission."); } else if ((ssid = cupsGetOption("ssid", num_form, form)) != NULL && (psk = cupsGetOption("psk", num_form, form)) != NULL) { _pappl_redirect_t data; // Redirection data if (!strcmp(ssid, "__hidden__")) ssid = cupsGetOption("ssid_hidden", num_form, form); if (ssid && *ssid) { // Have a valid SSID, try joining... papplCopyString(data.ssid, ssid, sizeof(data.ssid)); papplCopyString(data.psk, psk, sizeof(data.psk)); system_redirect(client, _PAPPL_LOC("Joining Wi-Fi Network"), "/network", 30, (pappl_timer_cb_t)system_redirect_wifi_cb, &data); cupsFreeOptions(num_form, form); return; } status = _PAPPL_LOC("Missing network name."); } else { status = _PAPPL_LOC("Unknown form action."); } cupsFreeOptions(num_form, form); } // Show the Wi-Fi configuration system_header(client, _PAPPL_LOC("Wi-Fi Configuration")); if (status) papplClientHTMLPrintf(client, "
%s
\n", papplClientGetLocString(client, status)); papplClientHTMLStartForm(client, client->uri, false); papplClientHTMLPrintf(client, " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
%s
\n" " \n" " \n", papplClientGetLocString(client, _PAPPL_LOC("Hidden SSID")), papplClientGetLocString(client, _PAPPL_LOC("Rescan")), papplClientGetLocString(client, _PAPPL_LOC("Password")), papplClientGetLocString(client, _PAPPL_LOC("Join Wi-Fi Network"))); system_footer(client); } // // 'get_networks()' - Get the list of available networks. // // This is the default implementation of the @link pappl_network_get_cb_t@ // function that just gets the current network interface status without respect // to whatever network management software is in use. // static size_t // O - Actual networks get_networks( size_t max_networks, // I - Maximum number of networks pappl_network_t *networks) // I - Networks { #if _WIN32 // TODO: Implement network interface lookups for Windows... return (0); #else size_t i, // Looping var num_networks = 0; // Number of networks struct ifaddrs *addrs, // List of network addresses *addr; // Current network address pappl_network_t *network; // Current network memset(networks, 0, max_networks * sizeof(pappl_network_t)); if (getifaddrs(&addrs)) return (0); for (addr = addrs; addr; addr = addr->ifa_next) { // Skip loopback and point-to-point interfaces... if (addr->ifa_name == NULL || addr->ifa_addr == NULL || (addr->ifa_addr->sa_family != AF_INET && addr->ifa_addr->sa_family != AF_INET6) || (addr->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) || !strncmp(addr->ifa_name, "awdl", 4)) continue; // Find the interface in the list... for (i = num_networks, network = networks; i > 0; i --, network ++) { if (!strcmp(network->name, addr->ifa_name)) break; } if (i == 0) { // Not found, add it or skip it... if (num_networks < max_networks) { network = networks + num_networks; num_networks ++; papplCopyString(network->name, addr->ifa_name, sizeof(network->name)); papplCopyString(network->ident, addr->ifa_name, sizeof(network->ident)); network->up = (addr->ifa_flags & IFF_UP) != 0; } else { continue; } } // Now assign the address information... if (addr->ifa_addr->sa_family == AF_INET) { // IPv4 unsigned ipv4 = ntohl(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr); // IPv4 address network->addr4.ipv4 = *((struct sockaddr_in *)addr->ifa_addr); network->mask4.ipv4 = *((struct sockaddr_in *)addr->ifa_netmask); // Assume default router is first node in subnet... network->gateway4 = network->addr4; network->gateway4.ipv4.sin_addr.s_addr = (network->gateway4.ipv4.sin_addr.s_addr & network->mask4.ipv4.sin_addr.s_addr) | htonl(1); if ((ipv4 & 0xff000000) == 0x0a000000 || (ipv4 & 0xfff00000) == 0xac100000 || (ipv4 & 0xffff0000) == 0xc0a80000) { // Private use 10.*, 172.16.*, or 192.168.* so this is likely DHCP-assigned if ((ipv4 & 255) < 200) network->config4 = PAPPL_NETCONF_DHCP; else network->config4 = PAPPL_NETCONF_DHCP_MANUAL; } else { // Otherwise assume manual configuration... network->config4 = PAPPL_NETCONF_MANUAL; } } else { // IPv6 if (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)addr->ifa_addr)->sin6_addr)) { // Save link-local address... network->linkaddr6.ipv6 = *((struct sockaddr_in6 *)addr->ifa_addr); if (network->config6 == PAPPL_NETCONF_OFF) network->config6 = PAPPL_NETCONF_DHCP; } else { // Save routable address... struct sockaddr_in6 *netmask6 = (struct sockaddr_in6 *)addr->ifa_netmask; network->addr6.ipv6 = *((struct sockaddr_in6 *)addr->ifa_addr); for (network->prefix6 = 0, i = 0; i < 16; i ++) { switch (netmask6->sin6_addr.s6_addr[i]) { case 0xff : network->prefix6 += 8; break; case 0xfe : network->prefix6 += 7; break; case 0xfc : network->prefix6 += 6; break; case 0xf8 : network->prefix6 += 5; break; case 0xf0 : network->prefix6 += 4; break; case 0xe0 : network->prefix6 += 3; break; case 0xc0 : network->prefix6 += 2; break; case 0x80 : network->prefix6 += 1; break; default : break; } if (netmask6->sin6_addr.s6_addr[i] < 0xff) break; } if (network->config6 == PAPPL_NETCONF_OFF) network->config6 = PAPPL_NETCONF_MANUAL; } } } freeifaddrs(addrs); // Return the number of networks we found... return (num_networks); #endif // _WIN32 } #ifdef HAVE_OPENSSL // // 'openssl_add_ext()' - Add an extension. // static bool // O - `true` on success, `false` on error openssl_add_ext( STACK_OF(X509_EXTENSION) *exts, // I - Stack of extensions int nid, // I - Extension ID const char *value) // I - Value { X509_EXTENSION *ext = NULL; // Extension // Create and add the extension... if ((ext = X509V3_EXT_conf_nid(/*conf*/NULL, /*ctx*/NULL, nid, value)) == NULL) return (false); sk_X509_EXTENSION_push(exts, ext); return (true); } // // 'openssl_create_key()' - Create a suitable key pair for a certificate/signing request. // static EVP_PKEY * // O - Key pair openssl_create_key( pappl_system_t *system, // I - System _pappl_credtype_t type) // I - Type of key { EVP_PKEY *pkey; // Key pair EVP_PKEY_CTX *ctx; // Key generation context int algid; // Algorithm NID int bits = 0; // Bits int curveid = 0; // Curve NID switch (type) { case _PAPPL_CREDTYPE_ECDSA_P256_SHA256 : algid = EVP_PKEY_EC; curveid = NID_secp256k1; break; case _PAPPL_CREDTYPE_ECDSA_P384_SHA256 : algid = EVP_PKEY_EC; curveid = NID_secp384r1; break; case _PAPPL_CREDTYPE_ECDSA_P521_SHA256 : algid = EVP_PKEY_EC; curveid = NID_secp521r1; break; case _PAPPL_CREDTYPE_RSA_2048_SHA256 : algid = EVP_PKEY_RSA; bits = 2048; break; default : case _PAPPL_CREDTYPE_RSA_3072_SHA256 : algid = EVP_PKEY_RSA; bits = 3072; break; case _PAPPL_CREDTYPE_RSA_4096_SHA256 : algid = EVP_PKEY_RSA; bits = 4096; break; } pkey = NULL; if ((ctx = EVP_PKEY_CTX_new_id(algid, NULL)) == NULL) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create private key context."); else if (EVP_PKEY_keygen_init(ctx) <= 0) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to initialize private key context."); else if (bits && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to configure private key context."); else if (curveid && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curveid) <= 0) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to configure private key context."); else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create private key."); EVP_PKEY_CTX_free(ctx); return (pkey); } // // 'openssl_create_name()' - Create an X.509 name value for a certificate/signing request. // static X509_NAME * // O - X.509 name value openssl_create_name( const char *organization, // I - Organization or `NULL` to use common name const char *org_unit, // I - Organizational unit or `NULL` for none const char *locality, // I - City/town or `NULL` for "Unknown" const char *state_province, // I - State/province or `NULL` for "Unknown" const char *country, // I - Country or `NULL` for locale-based default const char *common_name, // I - Common name const char *email) // I - Email address or `NULL` for none { X509_NAME *name; // Subject/issuer name cups_lang_t *language; // Default language info const char *langname; // Language name language = cupsLangDefault(); langname = cupsLangGetName(language); name = X509_NAME_new(); if (country) X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)country, -1, -1, 0); else if (strlen(langname) == 5) X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)langname + 3, -1, -1, 0); else X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); X509_NAME_add_entry_by_txt(name, SN_commonName, MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); X509_NAME_add_entry_by_txt(name, SN_organizationName, MBSTRING_ASC, (unsigned char *)(organization ? organization : common_name), -1, -1, 0); X509_NAME_add_entry_by_txt(name, SN_organizationalUnitName, MBSTRING_ASC, (unsigned char *)(org_unit ? org_unit : ""), -1, -1, 0); X509_NAME_add_entry_by_txt(name, SN_stateOrProvinceName, MBSTRING_ASC, (unsigned char *)(state_province ? state_province : "Unknown"), -1, -1, 0); X509_NAME_add_entry_by_txt(name, SN_localityName, MBSTRING_ASC, (unsigned char *)(locality ? locality : "Unknown"), -1, -1, 0); if (email) X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_ASC, (unsigned char *)email, -1, -1, 0); return (name); } // // 'openssl_create_san()' - Create a list of subjectAltName values for a certificate/signing request. // static X509_EXTENSION * // O - Extension openssl_create_san( const char *hostname, // I - Hostname const char *localname) // I - Local hostname { char temp[2048]; // Temporary string // Add the hostname and (if set) local name... if (localname && *localname) snprintf(temp, sizeof(temp), "DNS:%s,DNS:%s", hostname, localname); else snprintf(temp, sizeof(temp), "DNS:%s", hostname); // Return the stack return (X509V3_EXT_conf_nid(/*conf*/NULL, /*ctx*/NULL, NID_subject_alt_name, temp)); } #endif // HAVE_OPENSSL // // 'system_device_cb()' - Device callback for the "add printer" chooser. // static bool // O - `true` to stop, `false` to continue system_device_cb( const char *device_info, // I - Device description const char *device_uri, // I - Device URI const char *device_id, // I - IEEE-1284 device ID void *data) // I - Callback data (client + device URI) { _pappl_system_dev_t *devdata = (_pappl_system_dev_t *)data; // Callback data papplClientHTMLPrintf(devdata->client, "", device_uri, device_id, !strcmp(devdata->device_uri, device_uri) ? " selected" : "", device_info); return (false); } // // 'system_footer()' - Show the system footer. // static void system_footer(pappl_client_t *client) // I - Client { papplClientHTMLPuts(client, " \n"); papplClientHTMLFooter(client); } // // 'system_header()' - Show the system header. // static void system_header(pappl_client_t *client, // I - Client const char *title) // I - Title { char text[1024]; // Localized version number const char *header; // Header text if (!papplClientRespond(client, HTTP_STATUS_OK, NULL, "text/html", 0, 0)) return; papplClientHTMLHeader(client, title, 0); if (client->system->versions[0].sversion[0]) { papplLocFormatString(papplClientGetLoc(client), text, sizeof(text), _PAPPL_LOC("Version %s"), client->system->versions[0].sversion); papplClientHTMLPrintf(client, "
\n" "
\n" "
\n" " %s\n" "
\n" "
\n" "
\n", text); } papplClientHTMLPuts(client, "
\n"); if ((header = papplClientGetLocString(client, client->uri)) != client->uri) { // Show header text papplClientHTMLPuts(client, "
\n" "
\n"); papplClientHTMLPuts(client, header); papplClientHTMLPuts(client, "\n" "
\n" "
\n"); } if (title) papplClientHTMLPrintf(client, "
\n" "
\n" "

%s

\n", papplClientGetLocString(client, title)); } // // 'system_redirect()' - Show a standard redirection page that reloads after N seconds. // static void system_redirect( pappl_client_t *client, // I - Client const char *title, // I - Web page title const char *resource, // I - Resource path int seconds, // I - Number of seconds to wait pappl_timer_cb_t cb, // I - Timer callback function _pappl_redirect_t *cb_data) // I - Data to send callback { _pappl_redirect_t *tdata; // Thread data // Display a temporary "spinner" page... papplClientRespond(client, HTTP_STATUS_OK, NULL, "text/html", 0, 0); papplClientHTMLPrintf(client, "\n" "\n" " \n" " %s\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "

%s

\n" "
\n" "
\n" "
\n" "
\n" "
\n" "
\n" "
\n" "
\n" " \n" "\n", papplClientGetLocString(client, title), seconds, papplClientIsEncrypted(client) ? "https" : "http", papplClientGetHostName(client), papplClientGetHostPort(client), resource, papplClientGetLocString(client, title)); httpWrite(papplClientGetHTTP(client), "", 0); // Make a copy of the redirection data... if ((tdata = malloc(sizeof(_pappl_redirect_t))) == NULL) return; memcpy(tdata, cb_data, sizeof(_pappl_redirect_t)); // Set a timer to do the configuration work... papplSystemAddTimerCallback(papplClientGetSystem(client), time(NULL) + 2, 0, cb, tdata); } // // 'system_redirect_network_cb()' - Configure network interfaces. // static bool // O - `false` to not repeat system_redirect_network_cb( pappl_system_t *system, // I - System _pappl_redirect_t *data) // I - Network data { if ((system->network_set_cb)(system, system->network_cbdata, data->num_networks, data->networks)) papplLog(system, PAPPL_LOGLEVEL_INFO, "Network configuration changed successfully."); else papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to change network configuration."); free(data); return (false); } // // 'system_redirect_wifi_cb()' - Configure the current Wi-Fi connection. // static bool // O - `false` to not repeat system_redirect_wifi_cb( pappl_system_t *system, // I - System _pappl_redirect_t *data) // I - Wi-Fi data { if ((system->wifi_join_cb)(system, system->wifi_cbdata, data->ssid, data->psk)) papplLog(system, PAPPL_LOGLEVEL_INFO, "Joined Wi-Fi network '%s'.", data->ssid); else papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to join Wi-Fi network '%s'.", data->ssid); free(data); return (false); } #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) // // 'tls_install_certificate()' - Install a certificate and private key. // static bool // O - `true` on success, `false` otherwise tls_install_certificate( pappl_client_t *client, // I - Client const char *crtfile, // I - PEM-encoded certificate filename const char *keyfile) // I - PEM-encoded private key filename { pappl_system_t *system = papplClientGetSystem(client); // System const char *home; // Home directory char hostname[256], // Hostname basedir[256], // CUPS directory ssldir[256], // CUPS "ssl" directory dstcrt[1024], // Destination certificate dstkey[1024]; // Destination private key # ifdef HAVE_OPENSSL # else gnutls_certificate_credentials_t *credentials; // TLS credentials int status; // Status for loading of credentials # endif // HAVE_OPENSSL # ifdef HAVE_OPENSSL # else // Try loading the credentials... if ((credentials = (gnutls_certificate_credentials_t *)malloc(sizeof(gnutls_certificate_credentials_t))) == NULL) return (false); gnutls_certificate_allocate_credentials(credentials); status = gnutls_certificate_set_x509_key_file(*credentials, crtfile, keyfile, GNUTLS_X509_FMT_PEM); gnutls_certificate_free_credentials(*credentials); free(credentials); if (status != 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to load TLS credentials: %s", gnutls_strerror(status)); return (false); } # endif // HAVE_OPENSSL // If everything checks out, copy the certificate and private key to the // CUPS "ssl" directory... home = getuid() ? getenv("HOME") : NULL; if (home) snprintf(basedir, sizeof(basedir), "%s/.cups", home); else papplCopyString(basedir, CUPS_SERVERROOT, sizeof(basedir)); // Make "~/.cups" or "CUPS_SERVERROOT" directory... if (mkdir(basedir, 0755) && errno != EEXIST) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create directory '%s': %s", basedir, strerror(errno)); return (false); } // Make "~/.cups/ssl" or "CUPS_SERVERROOT/ssl" directory... snprintf(ssldir, sizeof(ssldir), "%s/ssl", basedir); if (mkdir(ssldir, 0755) && errno != EEXIST) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create directory '%s': %s", ssldir, strerror(errno)); return (false); } snprintf(dstkey, sizeof(dstkey), "%s/%s.key", ssldir, papplSystemGetHostName(system, hostname, sizeof(hostname))); snprintf(dstcrt, sizeof(dstcrt), "%s/%s.crt", ssldir, hostname); if (!tls_install_file(client, dstkey, keyfile)) { unlink(dstcrt); return (false); } if (!tls_install_file(client, dstcrt, crtfile)) { unlink(dstkey); return (false); } // If we get this far we are done! return (true); } // // 'tls_install_file()' - Copy a TLS file. // static bool // O - `true` on success, `false` otherwise tls_install_file( pappl_client_t *client, // I - Client const char *dst, // I - Destination filename const char *src) // I - Source filename { cups_file_t *dstfile, // Destination file *srcfile; // Source file char buffer[32768]; // Copy buffer ssize_t bytes; // Bytes to copy if ((dstfile = cupsFileOpen(dst, "wb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create file '%s': %s", dst, strerror(errno)); return (false); } if ((srcfile = cupsFileOpen(src, "rb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to open file '%s': %s", src, strerror(errno)); cupsFileClose(dstfile); unlink(dst); return (false); } while ((bytes = cupsFileRead(srcfile, buffer, sizeof(buffer))) > 0) { #if CUPS_VERSION_MAJOR < 3 if (cupsFileWrite(dstfile, buffer, (size_t)bytes) < 0) #else if (!cupsFileWrite(dstfile, buffer, (size_t)bytes)) #endif // CUPS_VERSION_MAJOR < 3 { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write file '%s': %s", dst, strerror(errno)); cupsFileClose(dstfile); unlink(dst); cupsFileClose(srcfile); return (false); } } cupsFileClose(dstfile); cupsFileClose(srcfile); return (true); } // // 'tls_make_certificate()' - Make a self-signed certificate and private key. // static bool // O - `true` on success, `false` otherwise tls_make_certificate( pappl_client_t *client, // I - Client cups_len_t num_form, // I - Number of form variables cups_option_t *form) // I - Form variables { pappl_system_t *system = papplClientGetSystem(client); // System const char *home, // Home directory *value, // Value from form variables *level, // Level/algorithm+bits *email, // Email address *organization, // Organization name *org_unit, // Organizational unit, if any *city, // City/locality *state, // State/province *country; // Country int duration; // Duration in years char hostname[256], // Hostname localname[256], // Hostname.local basedir[256], // CUPS directory ssldir[256], // CUPS "ssl" directory crtfile[1024], // Certificate file keyfile[1024]; // Private key file _pappl_credtype_t credtype; // Type of credentials time_t curtime; // Current time # ifdef HAVE_OPENSSL bool result = false; // Result of operations EVP_PKEY *pkey; // Private key X509 *cert; // Certificate ASN1_INTEGER *serial; // Serial number ASN1_TIME *notBefore, // Initial date *notAfter; // Expiration date X509_NAME *name; // Subject/issuer name STACK_OF(X509_EXTENSION) *exts; // Extensions X509_EXTENSION *ext; // Current extension BIO *bio; // Output file # else // HAVE_GNUTLS gnutls_x509_crt_t crt; // Self-signed certificate gnutls_x509_privkey_t key; // Private/public key pair cups_file_t *fp; // Key/cert file unsigned char buffer[8192]; // Buffer for key/cert data size_t bytes; // Number of bytes of data unsigned char serial[8]; // Serial number buffer int status; // GNU TLS status # endif // HAVE_OPENSSL // Verify that we have all of the required form variables... if ((value = cupsGetOption("duration", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'duration' form field."); return (false); } else if ((duration = (int)strtol(value, NULL, 10)) < 1 || duration > 10) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Bad 'duration'='%s' form field.", value); return (false); } if ((level = cupsGetOption("level", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'level' form field."); return (false); } else if (!strcmp(level, "rsa-2048")) { credtype = _PAPPL_CREDTYPE_RSA_2048_SHA256; } else if (!strcmp(level, "rsa-3072")) { credtype = _PAPPL_CREDTYPE_RSA_3072_SHA256; } else if (!strcmp(level, "rsa-4096")) { credtype = _PAPPL_CREDTYPE_RSA_4096_SHA256; } else if (!strcmp(level, "ecdsa-p256")) { credtype = _PAPPL_CREDTYPE_ECDSA_P256_SHA256; } else if (!strcmp(level, "ecdsa-p384")) { credtype = _PAPPL_CREDTYPE_ECDSA_P384_SHA256; } else if (!strcmp(level, "ecdsa-p521")) { credtype = _PAPPL_CREDTYPE_ECDSA_P521_SHA256; } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unknown 'level' form field '%s'.", level); return (false); } if ((email = cupsGetOption("email", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'email' form field."); return (false); } if ((organization = cupsGetOption("organization", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'organization' form field."); return (false); } if ((org_unit = cupsGetOption("organizational_unit", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'organizational_unit' form field."); return (false); } if ((city = cupsGetOption("city", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'city' form field."); return (false); } if ((state = cupsGetOption("state", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'state' form field."); return (false); } if ((country = cupsGetOption("country", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'country' form field."); return (false); } curtime = time(NULL); // Get the name this system is known by... papplSystemGetHostName(system, hostname, sizeof(hostname)); if (strstr(hostname, ".local")) { // Hostname is of the form "HOSTNAME.local"... localname[0] = '\0'; } else { // Hostname is not of the form "HOSTNAME.local"... char *localptr; // Pointer into localname papplCopyString(localname, hostname, sizeof(localname)); if ((localptr = strchr(localname, '.')) != NULL) papplCopyString(localptr, ".local", sizeof(localname) - (size_t)(localptr - localname)); else papplCopyString(localname + strlen(localname), ".local", sizeof(localname) - strlen(localname)); } // Store the certificate and private key in the CUPS "ssl" directory... home = getuid() ? getenv("HOME") : NULL; if (home) snprintf(basedir, sizeof(basedir), "%s/.cups", home); else papplCopyString(basedir, CUPS_SERVERROOT, sizeof(basedir)); // Make "~/.cups" or "CUPS_SERVERROOT" directory... if (mkdir(basedir, 0755) && errno != EEXIST) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create directory '%s': %s", basedir, strerror(errno)); return (false); } // Make "~/.cups/ssl" or "CUPS_SERVERROOT/ssl" directory... snprintf(ssldir, sizeof(ssldir), "%s/ssl", basedir); if (mkdir(ssldir, 0755) && errno != EEXIST) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create directory '%s': %s", ssldir, strerror(errno)); return (false); } snprintf(keyfile, sizeof(keyfile), "%s/%s.key", ssldir, hostname); snprintf(crtfile, sizeof(crtfile), "%s/%s.crt", ssldir, hostname); papplLogClient(client, PAPPL_LOGLEVEL_DEBUG, "Creating crtfile='%s', keyfile='%s'.", crtfile, keyfile); # ifdef HAVE_OPENSSL // Create the paired encryption keys... if ((pkey = openssl_create_key(system, credtype)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create private key."); return (false); } // Create the self-signed certificate... if ((cert = X509_new()) == NULL) { EVP_PKEY_free(pkey); papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create X.509 certificate."); return (false); } notBefore = ASN1_TIME_new(); ASN1_TIME_set(notBefore, curtime); X509_set_notBefore(cert, notBefore); ASN1_TIME_free(notBefore); notAfter = ASN1_TIME_new(); ASN1_TIME_set(notAfter, curtime + duration * 365 * 86400); X509_set_notAfter(cert, notAfter); ASN1_TIME_free(notAfter); serial = ASN1_INTEGER_new(); ASN1_INTEGER_set(serial, (long)curtime); X509_set_serialNumber(cert, serial); ASN1_INTEGER_free(serial); X509_set_pubkey(cert, pkey); name = openssl_create_name(organization, org_unit, city, state, country, hostname, email); X509_set_subject_name(cert, name); X509_set_issuer_name(cert, name); X509_NAME_free(name); exts = sk_X509_EXTENSION_new_null(); // Add extension with DNS names and free buffer for GENERAL_NAME if ((ext = openssl_create_san(hostname, localname)) == NULL) goto done; sk_X509_EXTENSION_push(exts, ext); // Add other extensions required for TLS... openssl_add_ext(exts, NID_basic_constraints, "critical,CA:FALSE,pathlen:0"); openssl_add_ext(exts, NID_key_usage, "critical,digitalSignature,keyEncipherment"); openssl_add_ext(exts, NID_ext_key_usage, "1.3.6.1.5.5.7.3.1"); // serverAuth OID openssl_add_ext(exts, NID_subject_key_identifier, "hash"); openssl_add_ext(exts, NID_authority_key_identifier, "keyid,issuer"); while ((ext = sk_X509_EXTENSION_pop(exts)) != NULL) { if (!X509_add_ext(cert, ext, -1)) { sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); goto done; } } X509_set_version(cert, 2); // v3 // Sign with our private key... X509_sign(cert, pkey, EVP_sha256()); // Save them... if ((bio = BIO_new_file(keyfile, "wb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create key file '%s': %s", keyfile, strerror(errno)); goto done; } if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write key file '%s': %s", keyfile, strerror(errno)); BIO_free(bio); goto done; } BIO_free(bio); if ((bio = BIO_new_file(crtfile, "wb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create certificate file '%s': %s", crtfile, strerror(errno)); goto done; } if (!PEM_write_bio_X509(bio, cert)) { BIO_free(bio); papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write certificate file '%s': %s", crtfile, strerror(errno)); goto done; } BIO_free(bio); result = true; // Cleanup... done: X509_free(cert); EVP_PKEY_free(pkey); if (!result) return (false); # else // HAVE_GNUTLS // Create the paired encryption keys... gnutls_x509_privkey_init(&key); switch (credtype) { case _PAPPL_CREDTYPE_RSA_2048_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); break; case _PAPPL_CREDTYPE_RSA_3072_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 3072, 0); break; case _PAPPL_CREDTYPE_RSA_4096_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 4096, 0); break; case _PAPPL_CREDTYPE_ECDSA_P256_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 256, 0); break; case _PAPPL_CREDTYPE_ECDSA_P384_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 384, 0); break; case _PAPPL_CREDTYPE_ECDSA_P521_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 521, 0); break; } // Save the private key... bytes = sizeof(buffer); if ((status = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to export private key: %s", gnutls_strerror(status)); gnutls_x509_privkey_deinit(key); return (false); } else if ((fp = cupsFileOpen(keyfile, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create private key file '%s': %s", keyfile, strerror(errno)); gnutls_x509_privkey_deinit(key); return (false); } // Create the self-signed certificate... serial[0] = (unsigned char)(curtime >> 56); serial[1] = (unsigned char)(curtime >> 48); serial[2] = (unsigned char)(curtime >> 40); serial[3] = (unsigned char)(curtime >> 32); serial[4] = (unsigned char)(curtime >> 24); serial[5] = (unsigned char)(curtime >> 16); serial[6] = (unsigned char)(curtime >> 8); serial[7] = (unsigned char)(curtime); gnutls_x509_crt_init(&crt); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, country, (unsigned)strlen(country)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, hostname, (unsigned)strlen(hostname)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, organization, (unsigned)strlen(organization)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, org_unit, (unsigned)strlen(org_unit)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, state, (unsigned)strlen(state)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, city, (unsigned)strlen(city)); if (*email) gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, email, (unsigned)strlen(email)); gnutls_x509_crt_set_key(crt, key); gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); gnutls_x509_crt_set_activation_time(crt, curtime); gnutls_x509_crt_set_expiration_time(crt, curtime + duration * 365 * 86400); gnutls_x509_crt_set_ca_status(crt, 0); gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, hostname, (unsigned)strlen(hostname), GNUTLS_FSAN_SET); if (localname[0]) gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, localname, (unsigned)strlen(localname), GNUTLS_FSAN_APPEND); gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); gnutls_x509_crt_set_version(crt, 3); bytes = sizeof(buffer); if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); gnutls_x509_crt_sign(crt, crt, key); // Save the certificate and public key... bytes = sizeof(buffer); if ((status = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to export public key and X.509 certificate: %s", gnutls_strerror(status)); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (false); } else if ((fp = cupsFileOpen(crtfile, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create public key and X.509 certificate file '%s': %s", crtfile, strerror(errno)); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (false); } // If we get this far we are done! gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); # endif // HAVE_OPENSSL // Create symlinks for each of the alternate names... # if _WIN32 # define symlink(src,dst) CreateSymbolicLinkA(dst,src,SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) # endif // _WIN32 if (localname[0]) { char altfile[1024]; // Alternate cert/key filename snprintf(altfile, sizeof(altfile), "%s/%s.key", ssldir, localname); unlink(altfile); symlink(keyfile, altfile); snprintf(altfile, sizeof(altfile), "%s/%s.crt", ssldir, localname); unlink(altfile); symlink(crtfile, altfile); } return (true); } // // 'tls_make_certsignreq()' - Make a certificate signing request and private key. // static bool // O - `true` on success, `false` otherwise tls_make_certsignreq( pappl_client_t *client, // I - Client cups_len_t num_form, // I - Number of form variables cups_option_t *form, // I - Form variables char *crqpath, // I - Certificate request filename buffer size_t crqsize) // I - Size of certificate request buffer { pappl_system_t *system = papplClientGetSystem(client); // System const char *level, // Level/algorithm+bits *email, // Email address *organization, // Organization name *org_unit, // Organizational unit, if any *city, // City/locality *state, // State/province *country; // Country char hostname[256], // Hostname localname[256], // Hostname.local crqfile[1024], // Certificate request file keyfile[1024]; // Private key file _pappl_credtype_t credtype; // Type of credentials # ifdef HAVE_OPENSSL bool result = false; // Result of operations EVP_PKEY *pkey; // Private key X509_REQ *crq; // Certificate request X509_NAME *name; // Subject/issuer name STACK_OF(X509_EXTENSION) *exts; // Extensions X509_EXTENSION *ext; // Current extension BIO *bio; // Output file # else gnutls_x509_crq_t crq; // Certificate request gnutls_x509_privkey_t key; // Private/public key pair cups_file_t *fp; // Key/cert file unsigned char buffer[8192]; // Buffer for key/cert data size_t bytes; // Number of bytes of data int status; // GNU TLS status # endif // HAVE_OPENSSL *crqpath = '\0'; // Verify that we have all of the required form variables... if ((level = cupsGetOption("level", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'level' form field."); return (false); } else if (!strcmp(level, "rsa-2048")) { credtype = _PAPPL_CREDTYPE_RSA_2048_SHA256; } else if (!strcmp(level, "rsa-3072")) { credtype = _PAPPL_CREDTYPE_RSA_3072_SHA256; } else if (!strcmp(level, "rsa-4096")) { credtype = _PAPPL_CREDTYPE_RSA_4096_SHA256; } else if (!strcmp(level, "ecdsa-p256")) { credtype = _PAPPL_CREDTYPE_ECDSA_P256_SHA256; } else if (!strcmp(level, "ecdsa-p384")) { credtype = _PAPPL_CREDTYPE_ECDSA_P384_SHA256; } else if (!strcmp(level, "ecdsa-p521")) { credtype = _PAPPL_CREDTYPE_ECDSA_P521_SHA256; } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unknown 'level' form field '%s'.", level); return (false); } if ((email = cupsGetOption("email", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'email' form field."); return (false); } if ((organization = cupsGetOption("organization", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'organization' form field."); return (false); } if ((org_unit = cupsGetOption("organizational_unit", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'organizational_unit' form field."); return (false); } if ((city = cupsGetOption("city", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'city' form field."); return (false); } if ((state = cupsGetOption("state", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'state' form field."); return (false); } if ((country = cupsGetOption("country", num_form, form)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Missing 'country' form field."); return (false); } // Get the name this system is known by... papplSystemGetHostName(system, hostname, sizeof(hostname)); if (strstr(hostname, ".local")) { // Hostname is of the form "HOSTNAME.local"... localname[0] = '\0'; } else { // Hostname is not of the form "HOSTNAME.local"... char *localptr; // Pointer into localname papplCopyString(localname, hostname, sizeof(localname)); if ((localptr = strchr(localname, '.')) != NULL) papplCopyString(localptr, ".local", sizeof(localname) - (size_t)(localptr - localname)); else papplCopyString(localname + strlen(localname), ".local", sizeof(localname) - strlen(localname)); } // Store the certificate request and private key in the spool directory... snprintf(keyfile, sizeof(keyfile), "%s/%s.key", system->directory, hostname); snprintf(crqfile, sizeof(crqfile), "%s/%s.csr", system->directory, hostname); snprintf(crqpath, crqsize, "/%s.csr", hostname); # ifdef HAVE_OPENSSL // Create the paired encryption keys... if ((pkey = openssl_create_key(system, credtype)) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create private key."); return (false); } // Create the certificate request... if ((crq = X509_REQ_new()) == NULL) { EVP_PKEY_free(pkey); papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create X.509 certificate request."); return (false); } X509_REQ_set_pubkey(crq, pkey); name = openssl_create_name(organization, org_unit, city, state, country, hostname, email); X509_REQ_set_subject_name(crq, name); X509_NAME_free(name); // Add extension with DNS names and free buffer for GENERAL_NAME exts = sk_X509_EXTENSION_new_null(); if ((ext = openssl_create_san(hostname, localname)) == NULL) goto done; sk_X509_EXTENSION_push(exts, ext); openssl_add_ext(exts, NID_key_usage, "critical,digitalSignature,keyEncipherment"); openssl_add_ext(exts, NID_ext_key_usage, "1.3.6.1.5.5.7.3.1"); // serverAuth OID X509_REQ_add_extensions(crq, exts); X509_REQ_sign(crq, pkey, EVP_sha256()); // Save them... if ((bio = BIO_new_file(keyfile, "wb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create key file '%s': %s", keyfile, strerror(errno)); goto done; } if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write key file '%s': %s", keyfile, strerror(errno)); BIO_free(bio); goto done; } BIO_free(bio); if ((bio = BIO_new_file(crqfile, "wb")) == NULL) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create certificate request file '%s': %s", crqfile, strerror(errno)); goto done; } if (!PEM_write_bio_X509_REQ(bio, crq)) { BIO_free(bio); papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to write certificate request file '%s': %s", crqfile, strerror(errno)); goto done; } BIO_free(bio); result = true; // Cleanup... done: X509_REQ_free(crq); EVP_PKEY_free(pkey); if (!result) return (false); # else // Create the paired encryption keys... gnutls_x509_privkey_init(&key); switch (credtype) { case _PAPPL_CREDTYPE_RSA_2048_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); break; case _PAPPL_CREDTYPE_RSA_3072_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 3072, 0); break; case _PAPPL_CREDTYPE_RSA_4096_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 4096, 0); break; case _PAPPL_CREDTYPE_ECDSA_P256_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 256, 0); break; case _PAPPL_CREDTYPE_ECDSA_P384_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 384, 0); break; case _PAPPL_CREDTYPE_ECDSA_P521_SHA256 : gnutls_x509_privkey_generate(key, GNUTLS_PK_ECDSA, 521, 0); break; } // Save the private key... bytes = sizeof(buffer); if ((status = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to export private key: %s", gnutls_strerror(status)); gnutls_x509_privkey_deinit(key); return (false); } else if ((fp = cupsFileOpen(keyfile, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create private key file '%s': %s", keyfile, strerror(errno)); gnutls_x509_privkey_deinit(key); return (false); } // Create the certificate request... gnutls_x509_crq_init(&crq); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_COUNTRY_NAME, 0, country, (unsigned)strlen(country)); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_COMMON_NAME, 0, hostname, (unsigned)strlen(hostname)); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, organization, (unsigned)strlen(organization)); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, org_unit, (unsigned)strlen(org_unit)); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, state, (unsigned)strlen(state)); gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_X520_LOCALITY_NAME, 0, city, (unsigned)strlen(city)); if (*email) gnutls_x509_crq_set_dn_by_oid(crq, GNUTLS_OID_PKCS9_EMAIL, 0, email, (unsigned)strlen(email)); gnutls_x509_crq_set_key(crq, key); gnutls_x509_crq_set_subject_alt_name(crq, GNUTLS_SAN_DNSNAME, hostname, (unsigned)strlen(hostname), GNUTLS_FSAN_SET); if (localname[0]) gnutls_x509_crq_set_subject_alt_name(crq, GNUTLS_SAN_DNSNAME, localname, (unsigned)strlen(localname), GNUTLS_FSAN_APPEND); gnutls_x509_crq_set_key_purpose_oid(crq, GNUTLS_KP_TLS_WWW_SERVER, 0); gnutls_x509_crq_set_key_usage(crq, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); gnutls_x509_crq_set_version(crq, 3); gnutls_x509_crq_sign2(crq, key, GNUTLS_DIG_SHA256, 0); // Save the certificate request and public key... bytes = sizeof(buffer); if ((status = gnutls_x509_crq_export(crq, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to export public key and X.509 certificate request: %s", gnutls_strerror(status)); gnutls_x509_crq_deinit(crq); gnutls_x509_privkey_deinit(key); return (false); } else if ((fp = cupsFileOpen(crqfile, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { papplLogClient(client, PAPPL_LOGLEVEL_ERROR, "Unable to create public key and X.509 certificate request file '%s': %s", crqfile, strerror(errno)); gnutls_x509_crq_deinit(crq); gnutls_x509_privkey_deinit(key); return (false); } gnutls_x509_crq_deinit(crq); gnutls_x509_privkey_deinit(key); # endif // HAVE_OPENSSL // If we get this far we are done! papplSystemAddResourceFile(system, crqpath, "application/pkcs10", crqfile); return (true); } #endif // HAVE_OPENSSL || HAVE_GNUTLS pappl-1.4.9/pappl/system.c000066400000000000000000001037061476704353100154660ustar00rootroot00000000000000// // System object for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "pappl-private.h" #include "resource-private.h" #include "device-private.h" // // Local globals... // static time_t sigterm_time = 0; // SIGTERM time? static bool restart_logging = false;// Restart logging? // // Local functions... // static void make_attributes(pappl_system_t *system); static void sighup_handler(int sig); static void sigterm_handler(int sig); // // '_papplSystemAddPrinterIcons()' - (Re)add printer icon resources. // void _papplSystemAddPrinterIcons( pappl_system_t *system, // I - System pappl_printer_t *printer) // I - Printer { char path[256]; // Resource path pappl_icon_t *icons = printer->driver_data.icons; // Printer icons snprintf(path, sizeof(path), "%s/icon-sm.png", printer->uriname); papplSystemRemoveResource(system, path); if (icons[0].filename[0]) papplSystemAddResourceFile(system, path, "image/png", icons[0].filename); else if (icons[0].data && icons[0].datalen) papplSystemAddResourceData(system, path, "image/png", icons[0].data, icons[0].datalen); else papplSystemAddResourceData(system, path, "image/png", icon_sm_png, sizeof(icon_sm_png)); snprintf(path, sizeof(path), "%s/icon-md.png", printer->uriname); papplSystemRemoveResource(system, path); if (icons[1].filename[0]) papplSystemAddResourceFile(system, path, "image/png", icons[1].filename); else if (icons[1].data && icons[1].datalen) papplSystemAddResourceData(system, path, "image/png", icons[1].data, icons[1].datalen); else papplSystemAddResourceData(system, path, "image/png", icon_md_png, sizeof(icon_md_png)); snprintf(path, sizeof(path), "%s/icon-lg.png", printer->uriname); papplSystemRemoveResource(system, path); if (icons[2].filename[0]) papplSystemAddResourceFile(system, path, "image/png", icons[2].filename); else if (icons[2].data && icons[2].datalen) papplSystemAddResourceData(system, path, "image/png", icons[2].data, icons[2].datalen); else papplSystemAddResourceData(system, path, "image/png", icon_lg_png, sizeof(icon_lg_png)); } // // '_papplSystemConfigChanged()' - Mark the system configuration as changed. // void _papplSystemConfigChanged( pappl_system_t *system) // I - System { pthread_mutex_lock(&system->config_mutex); if (system->is_running) { system->config_time = time(NULL); system->config_changes ++; } pthread_mutex_unlock(&system->config_mutex); } // // 'papplSystemCreate()' - Create a system object. // // This function creates a new system object, which is responsible for managing // all the printers, jobs, and resources used by the printer application. // // The "options" argument specifies which options are enabled for the server: // // - `PAPPL_SOPTIONS_NONE`: No options. // - `PAPPL_SOPTIONS_DNSSD_HOST`: When resolving DNS-SD service name collisions, // use the DNS-SD hostname instead of a serial number or UUID. // - `PAPPL_SOPTIONS_WEB_LOG`: Include the log file web page. // - `PAPPL_SOPTIONS_MULTI_QUEUE`: Support multiple printers. // - `PAPPL_SOPTIONS_WEB_NETWORK`: Include the network settings web page. // - `PAPPL_SOPTIONS_RAW_SOCKET`: Accept jobs via raw sockets starting on port // 9100 (all but Windows). // - `PAPPL_SOPTIONS_WEB_REMOTE`: Allow remote queue management. // - `PAPPL_SOPTIONS_WEB_SECURITY`: Include the security settings web page. // - `PAPPL_SOPTIONS_WEB_INTERFACE`: Include the standard printer and job monitoring // web pages. // - `PAPPL_SOPTIONS_WEB_TLS`: Include the TLS settings page. // - `PAPPL_SOPTIONS_USB_PRINTER`: Accept jobs via USB for the default printer // (embedded Linux only). // // The "name" argument specifies a human-readable name for the system. // // The "port" argument specifies the port number to bind to. A value of `0` // will cause an available port number to be assigned when the first listener // is added with the @link papplSystemAddListeners@ function. // // The "subtypes" argument specifies one or more comma-delimited DNS-SD service // sub-types such as "_print" and "_universal". // // The "spooldir" argument specifies the location of job files. If `NULL`, a // temporary directory is created. // // The "logfile" argument specifies where to send log messages. If `NULL`, the // log messages are written to a temporary file. // // The "loglevel" argument specifies the initial logging level. // // The "auth_service" argument specifies a PAM authentication service name. If // `NULL`, no user authentication will be provided. // // The "tls_only" argument controls whether the printer application will accept // unencrypted connections. In general, this argument should always be `false` // (allow unencrypted connections) since not all clients support encrypted // printing. // pappl_system_t * // O - System object papplSystemCreate( pappl_soptions_t options, // I - Server options const char *name, // I - System name int port, // I - Port number or `0` for auto const char *subtypes, // I - DNS-SD sub-types or `NULL` for none const char *spooldir, // I - Spool directory or `NULL` for default const char *logfile, // I - Log file or `NULL` for default pappl_loglevel_t loglevel, // I - Log level const char *auth_service, // I - PAM authentication service or `NULL` for none bool tls_only) // I - Only support TLS connections? { pappl_system_t *system; // System object const char *tmpdir = papplGetTempDir(); // Temporary directory if (!name) return (NULL); // Allocate memory... if ((system = (pappl_system_t *)calloc(1, sizeof(pappl_system_t))) == NULL) return (NULL); // Initialize values... pthread_rwlock_init(&system->rwlock, NULL); pthread_mutex_init(&system->session_mutex, NULL); pthread_mutex_init(&system->config_mutex, NULL); pthread_mutex_init(&system->log_mutex, NULL); pthread_mutex_init(&system->subscription_mutex, NULL); pthread_cond_init(&system->subscription_cond, NULL); #if _WIN32 options &= (pappl_soptions_t)~PAPPL_SOPTIONS_RAW_SOCKET; #endif // _WIN32 system->options = options; system->start_time = time(NULL); system->name = strdup(name); system->dns_sd_name = strdup(name); system->port = port; system->directory = spooldir ? strdup(spooldir) : NULL; system->log_fd = -1; system->log_file = logfile ? strdup(logfile) : NULL; system->log_level = loglevel; system->log_max_size = 1024 * 1024; system->next_client = 1; system->next_printer_id = 1; system->subtypes = subtypes ? strdup(subtypes) : NULL; system->tls_only = tls_only; system->admin_gid = (gid_t)-1; system->auth_service = auth_service ? strdup(auth_service) : NULL; system->max_subscriptions = 100; papplSystemSetMaxClients(system, 0); papplSystemSetMaxImageSize(system, 0, 0, 0); if (!system->name || !system->dns_sd_name || (spooldir && !system->directory) || (logfile && !system->log_file) || (subtypes && !system->subtypes) || (auth_service && !system->auth_service)) goto fatal; // Make sure the system name and UUID are initialized... papplSystemSetHostName(system, NULL); papplSystemSetUUID(system, NULL); // See if the spool directory can be created... if (!system->directory) { char newspooldir[256]; // Spool directory snprintf(newspooldir, sizeof(newspooldir), "%s/pappl%d.d", tmpdir, (int)getpid()); if ((system->directory = strdup(newspooldir)) == NULL) goto fatal; } if (mkdir(system->directory, 0700) && errno != EEXIST) { perror(system->directory); goto fatal; } // Initialize logging... if (system->log_level == PAPPL_LOGLEVEL_UNSPEC) system->log_level = PAPPL_LOGLEVEL_ERROR; if (!system->log_file) { // Default log file is $TMPDIR/papplUID.log... char newlogfile[256]; // Log filename snprintf(newlogfile, sizeof(newlogfile), "%s/pappl%d.log", tmpdir, (int)getpid()); if ((system->log_file = strdup(newlogfile)) == NULL) goto fatal; } system->log_is_syslog = !strcmp(system->log_file, "syslog"); pthread_mutex_lock(&system->log_mutex); _papplLogOpenNoLock(system); pthread_mutex_unlock(&system->log_mutex); // Initialize authentication... if (system->auth_service && !strcmp(system->auth_service, "none")) { free(system->auth_service); system->auth_service = NULL; } // Initialize base filters... #ifdef HAVE_LIBJPEG papplSystemAddMIMEFilter(system, "image/jpeg", "image/pwg-raster", _papplJobFilterJPEG, NULL); #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG papplSystemAddMIMEFilter(system, "image/png", "image/pwg-raster", _papplJobFilterPNG, NULL); #endif // HAVE_LIBPNG // Load base localizations... _papplLocLoadAll(system); return (system); // If we get here, something went wrong... fatal: papplSystemDelete(system); return (NULL); } // // 'papplSystemDelete()' - Delete a system object. // // > Note: A system object cannot be deleted while the system is running. // void papplSystemDelete( pappl_system_t *system) // I - System object { cups_len_t i; // Looping var _pappl_timer_t *t; // Current timer if (!system || system->is_running) return; _papplSystemUnregisterDNSSDNoLock(system); cupsArrayDelete(system->printers); free(system->uuid); free(system->name); free(system->dns_sd_name); free(system->hostname); free(system->domain_path); free(system->server_header); free(system->directory); free(system->log_file); free(system->subtypes); free(system->auth_scheme); free(system->auth_service); free(system->admin_group); free(system->default_print_group); if (system->log_fd >= 0 && system->log_fd != 2) close(system->log_fd); for (i = 0; i < system->num_listeners; i ++) #if _WIN32 closesocket(system->listeners[i].fd); #else close(system->listeners[i].fd); #endif // _WIN32 cupsArrayDelete(system->filters); cupsArrayDelete(system->links); cupsArrayDelete(system->resources); cupsArrayDelete(system->localizations); _papplSystemCleanSubscriptions(system, true); cupsArrayDelete(system->subscriptions); pthread_cond_destroy(&system->subscription_cond); pthread_mutex_destroy(&system->subscription_mutex); for (t = (_pappl_timer_t *)cupsArrayGetFirst(system->timers); t; t = (_pappl_timer_t *)cupsArrayGetNext(system->timers)) { cupsArrayRemove(system->timers, t); free(t); } cupsArrayDelete(system->timers); pthread_rwlock_destroy(&system->rwlock); pthread_mutex_destroy(&system->session_mutex); pthread_mutex_destroy(&system->config_mutex); pthread_mutex_destroy(&system->log_mutex); free(system); } // // '_papplSystemMakeUUID()' - Make a UUID for a system, printer, or job. // // Unlike httpAssembleUUID, this function does not introduce random data for // printers so the UUIDs are stable. // char * // I - UUID string _papplSystemMakeUUID( pappl_system_t *system, // I - System const char *printer_name, // I - Printer name or `NULL` for none int job_id, // I - Job ID, negative subscription ID, or `0` for none char *buffer, // I - String buffer size_t bufsize) // I - Size of buffer { char data[1024]; // Source string for MD5 unsigned char sha256[32]; // SHA-256 digest/sum // Build a version 3 UUID conforming to RFC 4122. // // Start with the SHA2-256 sum of the hostname, port, object name and // number, and some random data on the end for jobs (to avoid duplicates). if (job_id < 0) // Negative job ID == subscription ID snprintf(data, sizeof(data), "_PAPPL_SUBSCRIPTION_:%s:%d:%s:%d:%08x", system->hostname, system->port, printer_name ? printer_name : "", -job_id, papplGetRand()); else if (printer_name && job_id) snprintf(data, sizeof(data), "_PAPPL_JOB_:%s:%d:%s:%d:%08x", system->hostname, system->port, printer_name, job_id, papplGetRand()); else if (printer_name) snprintf(data, sizeof(data), "_PAPPL_PRINTER_:%s:%d:%s", system->hostname, system->port, printer_name); else snprintf(data, sizeof(data), "_PAPPL_SYSTEM_:%s:%d", system->hostname, system->port); cupsHashData("sha2-256", (unsigned char *)data, strlen(data), sha256, sizeof(sha256)); // Generate the UUID from the SHA-256... snprintf(buffer, bufsize, "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", sha256[0], sha256[1], sha256[3], sha256[4], sha256[5], sha256[6], (sha256[10] & 15) | 0x30, sha256[11], (sha256[15] & 0x3f) | 0x40, sha256[16], sha256[20], sha256[21], sha256[25], sha256[26], sha256[30], sha256[31]); return (buffer); } // // 'papplSystemRun()' - Run the printer application. // // This function runs the printer application, accepting new connections, // handling requests, and processing jobs as needed. It returns once the // system is shutdown, either through an IPP request or `SIGTERM`. // void papplSystemRun(pappl_system_t *system) // I - System { cups_len_t i, // Looping var count; // Number of listeners that fired int pcount, // Poll count ptimeout; // Poll timeout pappl_client_t *client; // New client char header[HTTP_MAX_VALUE]; // Server: header value int dns_sd_host_changes; // Current number of host name changes pappl_printer_t *printer; // Current printer pthread_attr_t tattr; // Thread creation attributes struct timeval curtime; // Current time time_t next, // Next time for scheduling... subtime = 0; // Subscription checking time _pappl_timer_t *timer; // Current timer bool save_changes; // Save changes? // Range check... if (!system) return; if (papplSystemIsRunning(system)) { papplLog(system, PAPPL_LOGLEVEL_FATAL, "Tried to run system when already running."); return; } if (system->num_listeners == 0) { papplLog(system, PAPPL_LOGLEVEL_FATAL, "Tried to run system without listeners."); return; } _papplRWLockWrite(system); system->is_running = true; _papplRWUnlock(system); // Add fallback resources... papplSystemAddResourceData(system, "/favicon.png", "image/png", icon_md_png, sizeof(icon_md_png)); papplSystemAddResourceData(system, "/navicon.png", "image/png", icon_sm_png, sizeof(icon_sm_png)); papplSystemAddResourceString(system, "/style.css", "text/css", style_css); if ((system->options & PAPPL_SOPTIONS_WEB_LOG) && system->log_file && strcmp(system->log_file, "-") && strcmp(system->log_file, "syslog")) { papplSystemAddResourceCallback(system, "/logfile.txt", "text/plain", (pappl_resource_cb_t)_papplSystemWebLogFile, system); papplSystemAddResourceCallback(system, "/logs", "text/html", (pappl_resource_cb_t)_papplSystemWebLogs, system); papplSystemAddLink(system, _PAPPL_LOC("View Logs"), "/logs", PAPPL_LOPTIONS_LOGGING | PAPPL_LOPTIONS_HTTPS_REQUIRED); } if (system->options & PAPPL_SOPTIONS_WEB_INTERFACE) { if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) { papplSystemAddResourceCallback(system, "/", "text/html", (pappl_resource_cb_t)_papplSystemWebHome, system); papplSystemAddResourceCallback(system, "/addprinter", "text/html", (pappl_resource_cb_t)_papplSystemWebAddPrinter, system); papplSystemAddLink(system, _PAPPL_LOC("Add Printer"), "/addprinter", PAPPL_LOPTIONS_PRINTER | PAPPL_LOPTIONS_HTTPS_REQUIRED); } if (system->options & PAPPL_SOPTIONS_MULTI_QUEUE) papplSystemAddResourceCallback(system, "/config", "text/html", (pappl_resource_cb_t)_papplSystemWebConfig, system); if (system->options & PAPPL_SOPTIONS_WEB_NETWORK) { papplSystemAddResourceCallback(system, "/network", "text/html", (pappl_resource_cb_t)_papplSystemWebNetwork, system); papplSystemAddLink(system, _PAPPL_LOC("Network"), "/network", PAPPL_LOPTIONS_OTHER | PAPPL_LOPTIONS_HTTPS_REQUIRED); if (system->wifi_join_cb && system->wifi_list_cb && system->wifi_status_cb) papplSystemAddResourceCallback(system, "/network-wifi", "text/html", (pappl_resource_cb_t)_papplSystemWebWiFi, system); } if (system->options & PAPPL_SOPTIONS_WEB_SECURITY) { papplSystemAddResourceCallback(system, "/security", "text/html", (pappl_resource_cb_t)_papplSystemWebSecurity, system); papplSystemAddLink(system, _PAPPL_LOC("Security"), "/security", PAPPL_LOPTIONS_OTHER | PAPPL_LOPTIONS_HTTPS_REQUIRED); } #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (system->options & PAPPL_SOPTIONS_WEB_TLS) { papplSystemAddResourceCallback(system, "/tls-install-crt", "text/html", (pappl_resource_cb_t)_papplSystemWebTLSInstall, system); papplSystemAddLink(system, _PAPPL_LOC("Install TLS Certificate"), "/tls-install-crt", PAPPL_LOPTIONS_OTHER | PAPPL_LOPTIONS_HTTPS_REQUIRED); papplSystemAddResourceCallback(system, "/tls-new-crt", "text/html", (pappl_resource_cb_t)_papplSystemWebTLSNew, system); papplSystemAddLink(system, _PAPPL_LOC("Create New TLS Certificate"), "/tls-new-crt", PAPPL_LOPTIONS_OTHER | PAPPL_LOPTIONS_HTTPS_REQUIRED); papplSystemAddResourceCallback(system, "/tls-new-csr", "text/html", (pappl_resource_cb_t)_papplSystemWebTLSNew, system); papplSystemAddLink(system, _PAPPL_LOC("Create TLS Certificate Request"), "/tls-new-csr", PAPPL_LOPTIONS_OTHER | PAPPL_LOPTIONS_HTTPS_REQUIRED); } #endif // HAVE_GNUTLS || HAVE_OPENSSL } // Catch important signals... papplLog(system, PAPPL_LOGLEVEL_INFO, "Starting system."); #if !_WIN32 signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); signal(SIGHUP, sighup_handler); #endif // !_WIN32 // Set the server header... free(system->server_header); if (system->versions[0].name[0]) { char safe_name[64], // "Safe" name *safe_ptr; // Pointer into "safe" name // Replace spaces and other not-allowed characters in the firmware name // with an underscore... papplCopyString(safe_name, system->versions[0].name, sizeof(safe_name)); for (safe_ptr = safe_name; *safe_ptr; safe_ptr ++) { if (*safe_ptr <= ' ' || *safe_ptr == '/' || *safe_ptr == 0x7f || (*safe_ptr & 0x80)) *safe_ptr = '_'; } // Format the server header using the sanitized firmware name and version... snprintf(header, sizeof(header), "%s/%s PAPPL/" PAPPL_VERSION " CUPS IPP/2.0", safe_name, system->versions[0].sversion); } else { // If no version information is registered, just say "unknown" for the // main name... papplCopyString(header, "Unknown PAPPL/" PAPPL_VERSION " CUPS IPP/2.0", sizeof(header)); } if ((system->server_header = strdup(header)) == NULL) { papplLog(system, PAPPL_LOGLEVEL_FATAL, "Unable to allocate Server header value."); system->is_running = false; return; } papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Server header value is '%s'.", system->server_header); // Make the static attributes... make_attributes(system); // Start all child threads in a detached state... pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); // Advertise the system via DNS-SD as needed... if (system->dns_sd_name) _papplSystemRegisterDNSSDNoLock(system); // Start up printers... for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); // Advertise via DNS-SD as needed... if (printer->dns_sd_name) _papplPrinterRegisterDNSSDNoLock(printer); // Start the raw socket listeners as needed... if ((system->options & PAPPL_SOPTIONS_RAW_SOCKET) && printer->num_raw_listeners > 0) { pthread_t tid; // Thread ID papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Starting socket listener thread."); if (pthread_create(&tid, &tattr, (void *(*)(void *))_papplPrinterRunRaw, printer)) { // Unable to create listener thread... papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create raw listener thread: %s", strerror(errno)); } else { // Detach the main thread from the raw thread to prevent hangs... pthread_detach(tid); _papplRWLockRead(printer); while (!printer->raw_active) { _papplRWUnlock(printer); usleep(1000); // Wait for raw thread to start _papplRWLockRead(printer); } _papplRWUnlock(printer); } } } // Start the USB gadget as needed... if ((system->options & PAPPL_SOPTIONS_USB_PRINTER) && (printer = papplSystemFindPrinter(system, NULL, system->default_printer_id, NULL)) != NULL) { pthread_t tid; // Thread ID papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Starting USB listener thread."); if (pthread_create(&tid, &tattr, (void *(*)(void *))_papplPrinterRunUSB, printer)) { // Unable to create USB thread... papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Unable to create USB gadget thread: %s", strerror(errno)); } else { // Detach the main thread from the USB thread to prevent hangs... pthread_detach(tid); _papplRWLockRead(printer); while (!printer->usb_active) { _papplRWUnlock(printer); usleep(1000); // Wait for USB thread to start _papplRWLockRead(printer); } _papplRWUnlock(printer); } } // Loop until we are shutdown or have a hard error... papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Entering run loop."); for (;;) { if (restart_logging) { restart_logging = false; pthread_mutex_lock(&system->log_mutex); _papplLogOpenNoLock(system); pthread_mutex_unlock(&system->log_mutex); } gettimeofday(&curtime, NULL); _papplRWLockRead(system); if (system->shutdown_time || sigterm_time) next = curtime.tv_sec + 1; else next = curtime.tv_sec + 30; if ((timer = (_pappl_timer_t *)cupsArrayGetFirst(system->timers)) != NULL && timer->next < next) next = timer->next; if (system->clean_time && system->clean_time < next) next = system->clean_time; if (subtime < next && cupsArrayGetCount(system->subscriptions) > 0) next = subtime; _papplRWUnlock(system); if (next <= curtime.tv_sec) ptimeout = 0; else ptimeout = 1000 * (int)(next - curtime.tv_sec) - (int)curtime.tv_usec / 1000; if ((pcount = poll(system->listeners, (nfds_t)system->num_listeners, ptimeout)) < 0 && errno != EINTR && errno != EAGAIN) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to accept new connections: %s", strerror(errno)); break; } if (pcount > 0) { // Accept client connections as needed... for (i = 0; i < (cups_len_t)system->num_listeners; i ++) { if (system->listeners[i].revents & POLLIN) { if ((client = _papplClientCreate(system, (int)system->listeners[i].fd)) != NULL) { _papplRWLockWrite(system); system->num_clients ++; _papplRWUnlock(system); if (pthread_create(&client->thread_id, &tattr, (void *(*)(void *))_papplClientRun, client)) { // Unable to create client thread... papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unable to create client thread: %s", strerror(errno)); _papplClientDelete(client); } } } } _papplRWLockRead(system); if (system->num_clients >= system->max_clients) { for (i = 0; i < system->num_listeners; i ++) system->listeners[i].events = 0; } } else { _papplRWLockRead(system); if (system->num_clients < system->max_clients) { for (i = 0; i < system->num_listeners; i ++) system->listeners[i].events = POLLIN; } } dns_sd_host_changes = _papplDNSSDGetHostChanges(); if (system->dns_sd_any_collision || system->dns_sd_host_changes != dns_sd_host_changes) { // Handle name collisions... bool force_dns_sd = system->dns_sd_host_changes != dns_sd_host_changes; // Force re-registration? if (force_dns_sd) _papplSystemSetHostNameNoLock(system, NULL); if (system->dns_sd_collision || force_dns_sd) _papplSystemRegisterDNSSDNoLock(system); for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (printer->dns_sd_collision || force_dns_sd) _papplPrinterRegisterDNSSDNoLock(printer); } system->dns_sd_any_collision = false; system->dns_sd_host_changes = dns_sd_host_changes; } _papplRWUnlock(system); pthread_mutex_lock(&system->config_mutex); save_changes = system->config_changes > system->save_changes; pthread_mutex_unlock(&system->config_mutex); if (save_changes) { system->save_changes = system->config_changes; papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Saving state/config changes."); if (system->save_cb) { // Save the configuration... (system->save_cb)(system, system->save_cbdata); } } _papplRWLockRead(system); if (system->shutdown_time || sigterm_time) { // Shutdown requested, see if we can do so safely... if (system->shutdown_time && (time(NULL) - system->shutdown_time) > 60) { _papplRWUnlock(system); break; // Shutdown-System request } if (sigterm_time && (time(NULL) - sigterm_time) > 60) { _papplRWUnlock(system); break; // SIGTERM received } // Otherwise shutdown immediately if there are no more active jobs... for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); if (printer->processing_job) break; } _papplRWUnlock(system); if (i >= count) break; } else { _papplRWUnlock(system); } // Run any timers... gettimeofday(&curtime, NULL); _papplRWLockRead(system); for (timer = (_pappl_timer_t *)cupsArrayGetFirst(system->timers); timer; timer = (_pappl_timer_t *)cupsArrayGetNext(system->timers)) { if (timer->next > curtime.tv_sec) break; cupsArrayRemove(system->timers, timer); if ((timer->cb)(system, timer->cb_data) && timer->interval) { timer->next += timer->interval; cupsArrayAdd(system->timers, timer); } } _papplRWUnlock(system); // Clean out old jobs and subscriptions... if (system->clean_time && curtime.tv_sec >= system->clean_time) papplSystemCleanJobs(system); if (curtime.tv_sec >= subtime) { _papplSystemCleanSubscriptions(system, false); subtime = curtime.tv_sec + 10; } } papplLog(system, PAPPL_LOGLEVEL_INFO, "Shutting down system."); _papplRWLockWrite(system); ippDelete(system->attrs); system->attrs = NULL; pthread_attr_destroy(&tattr); if (system->dns_sd_name) _papplSystemUnregisterDNSSDNoLock(system); for (i = 0, count = cupsArrayGetCount(system->printers); i < count; i ++) { printer = (pappl_printer_t *)cupsArrayGetElement(system->printers, i); // Remove advertising via DNS-SD as needed... if (printer->dns_sd_name) _papplPrinterUnregisterDNSSDNoLock(printer); } system->is_running = false; _papplRWUnlock(system); pthread_mutex_lock(&system->config_mutex); save_changes = system->config_changes > system->save_changes; pthread_mutex_unlock(&system->config_mutex); if (save_changes) { system->save_changes = system->config_changes; papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Saving state/config changes."); if (system->save_cb) { // Save the configuration... (system->save_cb)(system, system->save_cbdata); } } if ((system->options & PAPPL_SOPTIONS_USB_PRINTER) && (printer = papplSystemFindPrinter(system, NULL, system->default_printer_id, NULL)) != NULL) { // Wait for the USB gadget thread(s) to complete... papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Waiting for USB listener thread to exit."); _papplRWLockRead(printer); while (printer->usb_active) { _papplRWUnlock(printer); usleep(100000); _papplRWLockRead(printer); } _papplRWUnlock(printer); } papplLog(system, PAPPL_LOGLEVEL_DEBUG, "System run loop completed."); } // // 'papplSystemShutdown()' - Shutdown the system. // // This function tells the system to perform an orderly shutdown of all printers // and to terminate the main loop. // void papplSystemShutdown( pappl_system_t *system) // I - System { if (system && !system->shutdown_time) system->shutdown_time = time(NULL); } // // 'make_attributes()' - Make the static attributes for the system. // static void make_attributes(pappl_system_t *system) // I - System { static const char * const charset[] = // charset-supported values { "us-ascii", "utf-8" }; static const char * const ipp_versions[] = { // ipp-versions-supported values "1.1", "2.0" }; static const int operations[] = // operations-supported values { IPP_OP_GET_PRINTER_ATTRIBUTES, IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, IPP_OP_GET_SUBSCRIPTIONS, IPP_OP_RENEW_SUBSCRIPTION, IPP_OP_CANCEL_SUBSCRIPTION, IPP_OP_GET_NOTIFICATIONS, IPP_OP_CREATE_PRINTER, IPP_OP_DELETE_PRINTER, IPP_OP_GET_PRINTERS, IPP_OP_CREATE_SYSTEM_SUBSCRIPTIONS, IPP_OP_DISABLE_ALL_PRINTERS, IPP_OP_ENABLE_ALL_PRINTERS, IPP_OP_GET_SYSTEM_ATTRIBUTES, IPP_OP_GET_SYSTEM_SUPPORTED_VALUES, IPP_OP_PAUSE_ALL_PRINTERS, IPP_OP_PAUSE_ALL_PRINTERS_AFTER_CURRENT_JOB, IPP_OP_RESUME_ALL_PRINTERS, IPP_OP_SET_SYSTEM_ATTRIBUTES, IPP_OP_SHUTDOWN_ALL_PRINTERS, IPP_OP_CUPS_GET_DEFAULT, IPP_OP_CUPS_GET_PRINTERS, IPP_OP_PAPPL_FIND_DEVICES, IPP_OP_PAPPL_FIND_DRIVERS, IPP_OP_PAPPL_CREATE_PRINTERS }; static const char * const printer_creation_attributes_supported[] = { // "printer-creation-attributes-supported" Values "copies-default", "finishings-col-default", "finishings-default", "media-col-default", "media-default", "orientation-requested-default", "print-color-mode-default", "print-content-optimize-default", "print-quality-default", "printer-contact-col", "printer-device-id", "printer-dns-sd-name", "printer-geo-location", "printer-location", "printer-name", "printer-resolution-default", "smi55357-device-uri", "smi55357-driver" }; static const char * const system_mandatory_printer_attributes[] = { // "system-mandatory-printer-attributes" values "printer-name", "smi55357-device-uri", "smi55357-driver" }; static const char * const system_settable_attributes_supported[] = { // "system-settable-attributes-supported" values "system-contact-col", "system-default-printer-id", "system-dns-sd-name", "system-geo-location", "system-location", "system-name", "system-organization", "system-organizational-unit" }; system->attrs = ippNew(); // charset-configured ippAddString(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-configured", NULL, "utf-8"); // charset-supported ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-supported", sizeof(charset) / sizeof(charset[0]), NULL, charset); // generated-natural-language-supported ippAddString(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "generated-natural-language-supported", NULL, "en"); // ipp-versions-supported ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-versions-supported", (int)(sizeof(ipp_versions) / sizeof(ipp_versions[0])), NULL, ipp_versions); // natural-language-configured ippAddString(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "natural-language-configured", NULL, "en"); // notify-events-default ippAddString(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events-default", NULL, "job-completed"); // notify-events-supported ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events-supported", (int)(sizeof(_papplEvents) / sizeof(_papplEvents[0])), NULL, _papplEvents); // notify-lease-duration-default ippAddInteger(system->attrs, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "notify-lease-duration-default", PAPPL_LEASE_DEFAULT); // notify-lease-duration-supported ippAddRange(system->attrs, IPP_TAG_SYSTEM, "notify-lease-duration-supported", 0, PAPPL_LEASE_MAX); // notify-max-events-supported ippAddInteger(system->attrs, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "notify-max-events-supported", PAPPL_MAX_EVENTS); // notify-pull-method-supported ippAddString(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-pull-method-supported", NULL, "ippget"); // operations-supported ippAddIntegers(system->attrs, IPP_TAG_SYSTEM, IPP_TAG_ENUM, "operations-supported", (int)(sizeof(operations) / sizeof(operations[0])), operations); // printer-creation-attributes-supported ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-creation-attributes-supported", (int)(sizeof(printer_creation_attributes_supported) / sizeof(printer_creation_attributes_supported[0])), NULL, printer_creation_attributes_supported); // smi55357-device-uri-schemes-supported _papplDeviceAddSupportedSchemes(system->attrs); // system-mandatory-printer-attributes ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "system-mandatory-printer-attributes", (int)(sizeof(system_mandatory_printer_attributes) / sizeof(system_mandatory_printer_attributes[0])), NULL, system_mandatory_printer_attributes); // system-settable-attributes-supported ippAddStrings(system->attrs, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "system-settable-attributes-supported", (int)(sizeof(system_settable_attributes_supported) / sizeof(system_settable_attributes_supported[0])), NULL, system_settable_attributes_supported); } // // 'sighup_handler()' - SIGHUP handler // static void sighup_handler(int sig) // I - Signal (ignored) { (void)sig; restart_logging = true; } // // 'sigterm_handler()' - SIGTERM handler. // static void sigterm_handler(int sig) // I - Signal (ignored) { (void)sig; sigterm_time = time(NULL); } pappl-1.4.9/pappl/system.h000066400000000000000000000371611476704353100154740ustar00rootroot00000000000000// // Public system header file for the Printer Application Framework // // Copyright © 2019-2023 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_SYSTEM_H_ # define _PAPPL_SYSTEM_H_ # include "device.h" # include "subscription.h" # include "log.h" # ifdef __cplusplus extern "C" { # endif // __cplusplus // // Types... // typedef enum pappl_netconf_e // Network configuration mode { PAPPL_NETCONF_OFF, // Turn network interface off PAPPL_NETCONF_DHCP, // Full DHCP PAPPL_NETCONF_DHCP_MANUAL, // DHCP with manual IP address PAPPL_NETCONF_MANUAL // Manual IP, netmask, and router } pappl_netconf_t; typedef struct pappl_network_s // Network interface information { char name[64]; // Interface name char ident[256]; // Interface identifier char domain[64]; // Domain name, if any http_addr_t dns[2]; // DNS server addresses, if any bool up; // Is this interface up (read-only)? pappl_netconf_t config4; // IPv4 configuration mode http_addr_t addr4; // IPv4 address http_addr_t mask4; // IPv4 netmask http_addr_t gateway4; // IPv4 router/gateway address pappl_netconf_t config6; // IPv6 configuration mode http_addr_t linkaddr6; // IPv6 link-local address (read-only) http_addr_t addr6; // IPv6 address unsigned prefix6; // IPv6 prefix length http_addr_t gateway6; // IPv6 router address } pappl_network_t; typedef struct pappl_pr_driver_s // Printer driver information { const char *name; // Driver name const char *description; // Driver description (usually the make and model) const char *device_id; // IEEE-1284 device ID void *extension; // Extension data pointer } pappl_pr_driver_t; enum pappl_soptions_e // System option bits { PAPPL_SOPTIONS_NONE = 0x0000, // No options PAPPL_SOPTIONS_DNSSD_HOST = 0x0001, // Use hostname in DNS-SD service names instead of serial number/UUID PAPPL_SOPTIONS_MULTI_QUEUE = 0x0002, // Support multiple printers PAPPL_SOPTIONS_RAW_SOCKET = 0x0004, // Accept jobs via raw sockets PAPPL_SOPTIONS_USB_PRINTER = 0x0008, // Accept jobs via USB for default printer (embedded Linux only) PAPPL_SOPTIONS_WEB_INTERFACE = 0x0010, // Enable the standard web pages PAPPL_SOPTIONS_WEB_LOG = 0x0020, // Enable the log file page PAPPL_SOPTIONS_WEB_NETWORK = 0x0040, // Enable the network settings page PAPPL_SOPTIONS_WEB_REMOTE = 0x0080, // Allow remote queue management (vs. localhost only) PAPPL_SOPTIONS_WEB_SECURITY = 0x0100, // Enable the user/password settings page PAPPL_SOPTIONS_WEB_TLS = 0x0200, // Enable the TLS settings page PAPPL_SOPTIONS_NO_TLS = 0x0400 // Disable TLS support @since PAPPL 1.1@ }; typedef unsigned pappl_soptions_t; // Bitfield for system options typedef struct pappl_version_s // Firmware version information { char name[64]; // "xxx-firmware-name" value char patches[64]; // "xxx-firmware-patches" value char sversion[64]; // "xxx-firmware-string-version" value unsigned short version[4]; // "xxx-firmware-version" value } pappl_version_t; typedef enum pappl_wifi_state_e // "printer-wifi-state" values { PAPPL_WIFI_STATE_OFF = 3, // 'off' PAPPL_WIFI_STATE_NOT_CONFIGURED, // 'not-configured' PAPPL_WIFI_STATE_NOT_VISIBLE, // 'not-visible' PAPPL_WIFI_STATE_CANNOT_JOIN, // 'cannot-join' PAPPL_WIFI_STATE_JOINING, // 'joining' PAPPL_WIFI_STATE_ON // 'on' } pappl_wifi_state_t; typedef struct pappl_wifi_s // Wi-Fi status/configuration information { pappl_wifi_state_t state; // Current "printer-wifi-state" value char ssid[128]; // Current "printer-wifi-ssid" value } pappl_wifi_t; // // Callback function types... // typedef http_status_t (*pappl_auth_cb_t)(pappl_client_t *client, const char *group, gid_t groupid, void *cb_data); // Authentication callback typedef const char *(*pappl_pr_autoadd_cb_t)(const char *device_info, const char *device_uri, const char *device_id, void *data); // Auto-add callback typedef void (*pappl_pr_create_cb_t)(pappl_printer_t *printer, void *data); // Printer creation callback typedef bool (*pappl_pr_driver_cb_t)(pappl_system_t *system, const char *driver_name, const char *device_uri, const char *device_id, pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data); // Driver callback function typedef bool (*pappl_mime_filter_cb_t)(pappl_job_t *job, pappl_device_t *device, void *data); // Filter callback function typedef bool (*pappl_ipp_op_cb_t)(pappl_client_t *client, void *data); // IPP operation callback function typedef const char *(*pappl_mime_cb_t)(const unsigned char *header, size_t headersize, void *data); // MIME typing callback function typedef void (*pappl_printer_cb_t)(pappl_printer_t *printer, void *data); // Printer iterator callback function typedef bool (*pappl_resource_cb_t)(pappl_client_t *client, void *data); // Dynamic resource callback function typedef bool (*pappl_save_cb_t)(pappl_system_t *system, void *data); // Save callback function typedef size_t (*pappl_network_get_cb_t)(pappl_system_t *system, void *cb_data, size_t max_networks, pappl_network_t *networks); // Get networks callback typedef bool (*pappl_network_set_cb_t)(pappl_system_t *system, void *cb_data, size_t num_networks, pappl_network_t *networks); // Set networks callback typedef bool (*pappl_timer_cb_t)(pappl_system_t *system, void *cb_data); // Timer callback function typedef bool (*pappl_wifi_join_cb_t)(pappl_system_t *system, void *data, const char *ssid, const char *psk); // Wi-Fi join callback typedef int (*pappl_wifi_list_cb_t)(pappl_system_t *system, void *data, cups_dest_t **ssids); // Wi-Fi list callback typedef pappl_wifi_t *(*pappl_wifi_status_cb_t)(pappl_system_t *system, void *data, pappl_wifi_t *wifi_data); // Wi-Fi status callback // // Functions... // extern void papplSystemAddEvent(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, const char *message, ...) _PAPPL_FORMAT(5, 6) _PAPPL_PUBLIC; extern void papplSystemAddLink(pappl_system_t *system, const char *label, const char *path_or_url, pappl_loptions_t options) _PAPPL_PUBLIC; extern bool papplSystemAddListeners(pappl_system_t *system, const char *name) _PAPPL_PUBLIC; extern void papplSystemAddMIMEFilter(pappl_system_t *system, const char *srctype, const char *dsttype, pappl_mime_filter_cb_t cb, void *data) _PAPPL_PUBLIC; extern void papplSystemAddResourceCallback(pappl_system_t *system, const char *path, const char *format, pappl_resource_cb_t cb, void *data) _PAPPL_PUBLIC; extern void papplSystemAddResourceData(pappl_system_t *system, const char *path, const char *format, const void *data, size_t datalen) _PAPPL_PUBLIC; extern void papplSystemAddResourceDirectory(pappl_system_t *system, const char *basepath, const char *directory) _PAPPL_PUBLIC; extern void papplSystemAddResourceFile(pappl_system_t *system, const char *path, const char *format, const char *filename) _PAPPL_PUBLIC; extern void papplSystemAddResourceString(pappl_system_t *system, const char *path, const char *format, const char *data) _PAPPL_PUBLIC; extern void papplSystemAddStringsData(pappl_system_t *system, const char *path, const char *language, const char *data) _PAPPL_PUBLIC; extern void papplSystemAddStringsFile(pappl_system_t *system, const char *path, const char *language, const char *filename) _PAPPL_PUBLIC; extern bool papplSystemAddTimerCallback(pappl_system_t *system, time_t start, int interval, pappl_timer_cb_t cb, void *cb_data) _PAPPL_PUBLIC; extern void papplSystemCleanJobs(pappl_system_t *system) _PAPPL_PUBLIC; extern pappl_system_t *papplSystemCreate(pappl_soptions_t options, const char *name, int port, const char *subtypes, const char *spooldir, const char *logfile, pappl_loglevel_t loglevel, const char *auth_service, bool tls_only) _PAPPL_PUBLIC; extern bool papplSystemCreatePrinters(pappl_system_t *system, pappl_devtype_t types, pappl_pr_create_cb_t cb, void *cb_data) _PAPPL_PUBLIC; extern void papplSystemDelete(pappl_system_t *system) _PAPPL_PUBLIC; extern pappl_loc_t *papplSystemFindLoc(pappl_system_t *system, const char *language) _PAPPL_PUBLIC; extern pappl_printer_t *papplSystemFindPrinter(pappl_system_t *system, const char *resource, int printer_id, const char *device_uri) _PAPPL_PUBLIC; extern pappl_subscription_t *papplSystemFindSubscription(pappl_system_t *system, int sub_id) _PAPPL_PUBLIC; extern char *papplSystemGetAdminGroup(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern const char *papplSystemGetAuthService(pappl_system_t *system) _PAPPL_PUBLIC; extern pappl_contact_t *papplSystemGetContact(pappl_system_t *system, pappl_contact_t *contact) _PAPPL_PUBLIC; extern int papplSystemGetDefaultPrinterID(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetDefaultPrintGroup(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplSystemGetDNSSDName(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern const char *papplSystemGetFooterHTML(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetGeoLocation(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplSystemGetHostname(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_DEPRECATED("Use papplSystemGetHostName instead."); extern char *papplSystemGetHostName(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplSystemGetHostPort(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetLocation(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern pappl_loglevel_t papplSystemGetLogLevel(pappl_system_t *system) _PAPPL_PUBLIC; extern int papplSystemGetMaxClients(pappl_system_t *system) _PAPPL_PUBLIC; extern size_t papplSystemGetMaxImageSize(pappl_system_t *system, int *max_width, int *max_height) _PAPPL_PUBLIC; extern size_t papplSystemGetMaxLogSize(pappl_system_t *system) _PAPPL_PUBLIC; extern size_t papplSystemGetMaxSubscriptions(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetName(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplSystemGetNextPrinterID(pappl_system_t *system) _PAPPL_PUBLIC; extern pappl_soptions_t papplSystemGetOptions(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetOrganization(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplSystemGetOrganizationalUnit(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern char *papplSystemGetPassword(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern int papplSystemGetPort(pappl_system_t *system) _PAPPL_DEPRECATED("Use papplSystemGetHostPort instead."); extern const char *papplSystemGetServerHeader(pappl_system_t *system) _PAPPL_PUBLIC; extern char *papplSystemGetSessionKey(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern bool papplSystemGetTLSOnly(pappl_system_t *system) _PAPPL_PUBLIC; extern const char *papplSystemGetUUID(pappl_system_t *system) _PAPPL_PUBLIC; extern int papplSystemGetVersions(pappl_system_t *system, int max_versions, pappl_version_t *versions) _PAPPL_PUBLIC; extern char *papplSystemHashPassword(pappl_system_t *system, const char *salt, const char *password, char *buffer, size_t bufsize) _PAPPL_PUBLIC; extern bool papplSystemIsRunning(pappl_system_t *system) _PAPPL_PUBLIC; extern bool papplSystemIsShutdown(pappl_system_t *system) _PAPPL_PUBLIC; extern void papplSystemIteratePrinters(pappl_system_t *system, pappl_printer_cb_t cb, void *data) _PAPPL_PUBLIC; extern bool papplSystemLoadState(pappl_system_t *system, const char *filename) _PAPPL_PUBLIC; extern const char *papplSystemMatchDriver(pappl_system_t *system, const char *device_id) _PAPPL_PUBLIC; extern void papplSystemRemoveLink(pappl_system_t *system, const char *label) _PAPPL_PUBLIC; extern void papplSystemRemoveResource(pappl_system_t *system, const char *path) _PAPPL_PUBLIC; extern void papplSystemRemoveTimerCallback(pappl_system_t *system, pappl_timer_cb_t cb, void *cb_data) _PAPPL_PUBLIC; extern void papplSystemRun(pappl_system_t *system) _PAPPL_PUBLIC; extern bool papplSystemSaveState(pappl_system_t *system, const char *filename) _PAPPL_PUBLIC; extern void papplSystemSetAdminGroup(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetAuthCallback(pappl_system_t *system, const char *auth_scheme, pappl_auth_cb_t auth_cb, void *auth_cbdata) _PAPPL_PUBLIC; extern void papplSystemSetContact(pappl_system_t *system, pappl_contact_t *contact) _PAPPL_PUBLIC; extern void papplSystemSetDefaultPrinterID(pappl_system_t *system, int default_printer_id) _PAPPL_PUBLIC; extern void papplSystemSetDefaultPrintGroup(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetDNSSDName(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetEventCallback(pappl_system_t *system, pappl_event_cb_t event_cb, void *event_data) _PAPPL_PUBLIC; extern void papplSystemSetFooterHTML(pappl_system_t *system, const char *html) _PAPPL_PUBLIC; extern void papplSystemSetGeoLocation(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetHostname(pappl_system_t *system, const char *value) _PAPPL_DEPRECATED("Use papplSystemSetHostName instead."); extern void papplSystemSetHostName(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetLocation(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetLogLevel(pappl_system_t *system, pappl_loglevel_t loglevel) _PAPPL_PUBLIC; extern void papplSystemSetMaxClients(pappl_system_t *system, int max_clients) _PAPPL_PUBLIC; extern void papplSystemSetMaxImageSize(pappl_system_t *system, size_t max_size, int max_width, int max_height) _PAPPL_PUBLIC; extern void papplSystemSetMaxLogSize(pappl_system_t *system, size_t max_size) _PAPPL_PUBLIC; extern void papplSystemSetMaxSubscriptions(pappl_system_t *system, size_t max_subscriptions) _PAPPL_PUBLIC; extern void papplSystemSetMIMECallback(pappl_system_t *system, pappl_mime_cb_t cb, void *data) _PAPPL_PUBLIC; extern void papplSystemSetNetworkCallbacks(pappl_system_t *system, pappl_network_get_cb_t get_cb, pappl_network_set_cb_t set_cb, void *cb_data) _PAPPL_PUBLIC; extern void papplSystemSetNextPrinterID(pappl_system_t *system, int next_printer_id) _PAPPL_PUBLIC; extern void papplSystemSetOperationCallback(pappl_system_t *system, pappl_ipp_op_cb_t cb, void *data) _PAPPL_PUBLIC; extern void papplSystemSetOrganization(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetOrganizationalUnit(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetPassword(pappl_system_t *system, const char *hash) _PAPPL_PUBLIC; extern void papplSystemSetPrinterDrivers(pappl_system_t *system, int num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_create_cb_t create_cb, pappl_pr_driver_cb_t driver_cb, void *data) _PAPPL_PUBLIC; extern void papplSystemSetSaveCallback(pappl_system_t *system, pappl_save_cb_t cb, void *data) _PAPPL_PUBLIC; extern void papplSystemSetUUID(pappl_system_t *system, const char *value) _PAPPL_PUBLIC; extern void papplSystemSetVersions(pappl_system_t *system, int num_versions, pappl_version_t *versions) _PAPPL_PUBLIC; extern void papplSystemSetWiFiCallbacks(pappl_system_t *system, pappl_wifi_join_cb_t join_cb, pappl_wifi_list_cb_t list_cb, pappl_wifi_status_cb_t status_cb, void *data) _PAPPL_PUBLIC; extern void papplSystemShutdown(pappl_system_t *system) _PAPPL_PUBLIC; # ifdef __cplusplus } # endif // __cplusplus #endif // !_PAPPL_SYSTEM_H_ pappl-1.4.9/pappl/test.html000066400000000000000000000447721476704353100156520ustar00rootroot00000000000000 Test Page for PAPPL Stylesheet

Example Printer

Make and Model, Location
Organization
Idle, No jobs.


Make and Model, Location
Organization
Printing, 1 job, Media Low.


Make and Model, Location
Organization
Stopped, 2 jobs, Media Jam.


List

Job IDNameStatus
5Green Eggs and HamPendingCancel
4Blue FishPrinting at 12:37pmCancel
3Red FishCompleted at 12:36pm
2Two FishCompleted at 12:35pm
1One FishCompleted at 12:34pm

Activity

Doing something that will take some time:

Form Change

Geo-Location: x
Main Tray Media:
IPv4 Address: Automatic
Manual

Meters

Cyan
Magenta
Yellow
Black
Waste Ink

Grid-Based Style Sheet

The following should collapse to a single column on small screened devices.

C-12
C-11
C-1
C-10
C-2
C-9
C-3
C-8
C-4
C-8
C-2
C-2
C-7
C-5
C-6
C-6
C-6
C-3
C-3
C-6
C-2
C-2
C-2
C-5
C-5
C-2
C-4
C-4
C-4
C-4
C-4
C-2
C-2
C-3
C-3
C-3
C-3
C-2
C-2
C-2
C-2
C-2
C-2
C-1
C-1
C-1
C-1
C-1
C-1
C-1
C-1
C-1
C-1
C-1
C-1
pappl-1.4.9/pappl/util.c000066400000000000000000000253271476704353100151210ustar00rootroot00000000000000// // Utility functions for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "base-private.h" #ifdef HAVE_SYS_RANDOM_H # include #endif // HAVE_SYS_RANDOM_H // // Local functions... // #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 static ipp_attribute_t *copy_col(ipp_t *dst, ipp_attribute_t *srcattr, int quickcopy); #endif // CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 // // '_papplCopyAttributes()' - Copy attributes from one message to another. // void _papplCopyAttributes( ipp_t *to, // I - Destination request ipp_t *from, // I - Source request cups_array_t *ra, // I - Requested attributes ipp_tag_t group_tag, // I - Group to copy int quickcopy) // I - Do a quick copy? { ipp_attribute_t *attr; // Current attribute for (attr = ippGetFirstAttribute(from); attr; attr = ippGetNextAttribute(from)) { ipp_tag_t group = ippGetGroupTag(attr); // Attribute group const char *name = ippGetName(attr); // Attribute name // Filter out attributes that are not requested... if ((group_tag != IPP_TAG_ZERO && group != group_tag && group != IPP_TAG_ZERO) || !name || (!strcmp(name, "media-col-database") && !cupsArrayFind(ra, (void *)name))) continue; if (ra && !cupsArrayFind(ra, (void *)name)) continue; // Copy the attribute... #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION) copy_col(to, attr, quickcopy); else #endif // CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 ippCopyAttribute(to, attr, quickcopy); } } // // 'papplCopyString()' - Safely copy a C string. // // This function safely copies a C string to a destination buffer. // // size_t papplCopyString(char *dst, // I - Destination buffer const char *src, // I - Source string size_t dstsize) // I - Destination size { #ifdef HAVE_STRLCPY return (strlcpy(dst, src, dstsize)); #else size_t srclen = strlen(src); // Length of source string // Copy up to dstsize - 1 bytes dstsize --; if (srclen > dstsize) srclen = dstsize; memmove(dst, src, srclen); dst[srclen] = '\0'; return (srclen); #endif // HAVE_STRLCPY } // // 'papplCreateTempFile()' - Create a temporary file. // int // O - File descriptor or `-1` on error papplCreateTempFile( char *fname, // I - Filename buffer size_t fnamesize, // I - Size of filename buffer const char *prefix, // I - Prefix for filename const char *ext) // I - Filename extension, if any { int fd, // File descriptor tries = 0; // Number of tries char name[64], // "Safe" filename *nameptr; // Pointer into filename // Range check input... if (!fname || fnamesize < 256 || (prefix && strstr(prefix, "../")) || (ext && strstr(ext, "../"))) { if (fname) *fname = '\0'; return (-1); } if (prefix) { // Make a name from the prefix argument... for (nameptr = name; *prefix && nameptr < (name + sizeof(name) - 1); prefix ++) { if (isalnum(*prefix & 255) || *prefix == '-' || *prefix == '.') { *nameptr++ = (char)tolower(*prefix & 255); } else { *nameptr++ = '_'; while (prefix[1] && !isalnum(prefix[1] & 255) && prefix[1] != '-' && prefix[1] != '.') prefix ++; } } *nameptr = '\0'; } else { // Use a prefix of "t"... papplCopyString(name, "t", sizeof(name)); } do { // Create a filename... if (ext) snprintf(fname, fnamesize, "%s/%s%08x.%s", papplGetTempDir(), name, papplGetRand(), ext); else snprintf(fname, fnamesize, "%s/%s%08x", papplGetTempDir(), name, papplGetRand()); tries ++; } while ((fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC | O_EXCL | O_BINARY, 0600)) < 0 && tries < 100); return (fd); } // // 'papplGetRand()' - Return a 32-bit pseudo-random number. // // This function returns a 32-bit pseudo-random number suitable for use as // one-time identifiers or nonces. On platforms that provide it, the random // numbers are generated (or seeded) using system entropy. // unsigned // O - Random number papplGetRand(void) { #if _WIN32 // rand_s uses real entropy... unsigned v; // Random number rand_s(&v); return (v); #elif defined(HAVE_ARC4RANDOM) // arc4random uses real entropy automatically... return (arc4random()); #else # ifdef HAVE_GETRANDOM // Linux has the getrandom function to get real entropy, but can fail... unsigned buffer; // Random number buffer if (getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)) return (buffer); # elif defined(HAVE_GNUTLS_RND) // GNU TLS has the gnutls_rnd function we can use as well, but can fail... unsigned buffer; // Random number buffer if (!gnutls_rnd(GNUTLS_RND_NONCE, &buffer, sizeof(buffer))) return (buffer); # endif // HAVE_GETRANDOM // If we get here then we were unable to get enough random data or the local // system doesn't have enough entropy. Make some up... unsigned i, // Looping var temp; // Temporary value static bool first_time = true; // First time we ran? static unsigned mt_state[624], // Mersenne twister state mt_index; // Mersenne twister index static pthread_mutex_t mt_mutex = PTHREAD_MUTEX_INITIALIZER; // Mutex to control access to state pthread_mutex_lock(&mt_mutex); if (first_time) { int fd; // "/dev/urandom" file struct timeval curtime; // Current time // Seed the random number state... if ((fd = open("/dev/urandom", O_RDONLY)) >= 0) { // Read random entropy from the system... if (read(fd, mt_state, sizeof(mt_state[0])) < sizeof(mt_state[0])) mt_state[0] = 0; // Force fallback... close(fd); } else mt_state[0] = 0; if (!mt_state[0]) { // Fallback to using the current time in microseconds... gettimeofday(&curtime, NULL); mt_state[0] = (unsigned)(curtime.tv_sec + curtime.tv_usec); } mt_index = 0; for (i = 1; i < 624; i ++) mt_state[i] = (unsigned)((1812433253 * (mt_state[i - 1] ^ (mt_state[i - 1] >> 30))) + i); first_time = false; } if (mt_index == 0) { // Generate a sequence of random numbers... unsigned i1 = 1, i397 = 397; // Looping vars for (i = 0; i < 624; i ++) { temp = (mt_state[i] & 0x80000000) + (mt_state[i1] & 0x7fffffff); mt_state[i] = mt_state[i397] ^ (temp >> 1); if (temp & 1) mt_state[i] ^= 2567483615u; i1 ++; i397 ++; if (i1 == 624) i1 = 0; if (i397 == 624) i397 = 0; } } // Pull 32-bits of random data... temp = mt_state[mt_index ++]; temp ^= temp >> 11; temp ^= (temp << 7) & 2636928640u; temp ^= (temp << 15) & 4022730752u; temp ^= temp >> 18; if (mt_index == 624) mt_index = 0; pthread_mutex_unlock(&mt_mutex); return (temp); #endif // _WIN32 } // // 'papplGetTempDir()' - Get the temporary directory. // // This function gets the current temporary directory. // // Note: On Windows, the path separators in the temporary directory are // converted to forward slashes as needed for consistency. // const char * // O - Temporary directory papplGetTempDir(void) { const char *tmpdir; // Temporary directory static char tmppath[1024] = ""; // Temporary directory buffer static pthread_mutex_t tmpmutex = PTHREAD_MUTEX_INITIALIZER; // Mutex to control access pthread_mutex_lock(&tmpmutex); if (!tmppath[0]) { #if _WIN32 char *tmpptr; // Pointer into temporary directory // Check the TEMP environment variable... if ((tmpdir = getenv("TEMP")) != NULL) { papplCopyString(tmppath, tmpdir, sizeof(tmppath)); } else { // Otherwise use the Windows API to get the user/system default location... GetTempPathA(sizeof(tmppath), tmppath); } // Convert \ to /... for (tmpptr = tmppath; *tmpptr; tmpptr ++) { if (*tmpptr == '\\') *tmpptr = '/'; } // Remove trailing /, if any... if ((tmpptr = tmppath + strlen(tmppath) - 1) > tmppath && *tmpptr == '/') *tmpptr = '\0'; #else // Check the TMPDIR environment variable... if ((tmpdir = getenv("TMPDIR")) != NULL && !access(tmpdir, W_OK)) { // Set and writable, use it! papplCopyString(tmppath, tmpdir, sizeof(tmppath)); } else # ifdef _CS_DARWIN_USER_TEMP_DIR // Use the Darwin configuration string value... if (!confstr(_CS_DARWIN_USER_TEMP_DIR, tmppath, sizeof(tmppath))) { // Fallback to /private/tmp... papplCopyString(tmppath, "/private/tmp", sizeof(tmppath)); } # endif // _CS_DARWIN_USER_TEMP_DIR { // Fallback to /tmp... papplCopyString(tmppath, "/tmp", sizeof(tmppath)); } #endif // _WIN32 } pthread_mutex_unlock(&tmpmutex); return (tmppath); } // // '_papplIsEqual()' - Compare two strings for equality in constant time. // bool // O - `true` on match, `false` on non-match _papplIsEqual(const char *a, // I - First string const char *b) // I - Second string { bool result = true; // Result // Loop through both strings, noting any differences... while (*a && *b) { result &= *a == *b; a ++; b ++; } // Return, capturing the equality of the last characters... return (result && *a == *b); } #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 // // 'copy_col()' - Copy a collection attribute. // static ipp_attribute_t * // O - Destination attribute copy_col( ipp_t *dst, // I - Destination IPP message ipp_attribute_t *srcattr, // I - Attribute to copy int quickcopy) // I - 1 for a referenced copy, 0 for normal { cups_len_t i, // Looping var count; // Number of values ipp_attribute_t *dstattr; // Destination attribute // Copy it... count = ippGetCount(srcattr); dstattr = ippAddCollections(dst, ippGetGroupTag(srcattr), ippGetName(srcattr), count, /*cols*/NULL); if (quickcopy) { // Do a quick (shallow) copy... for (i = 0; i < count; i ++) ippSetCollection(dst, &dstattr, i, ippGetCollection(srcattr, i)); } else { // Do a deep copy... for (i = 0; i < count; i ++) { ipp_t *dstcol = ippNew(); // Destination collection if (!dstcol) { ippDeleteAttribute(dst, dstattr); return (NULL); } _papplCopyAttributes(dstcol, ippGetCollection(srcattr, i), /*ra*/NULL, /*group_tag*/IPP_TAG_ZERO, quickcopy); ippSetCollection(dst, &dstattr, i, dstcol); ippDelete(dstcol); } } return (dstattr); } #endif // CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 pappl-1.4.9/pappl/win32-gettimeofday.c000066400000000000000000000014431476704353100175560ustar00rootroot00000000000000// // Windows gettimeofday implementation for the Printer Application Framework // // Copyright © 2021 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // # include "base-private.h" // // 'gettimeofday()' - Get the current date and time in seconds and microseconds. // int // O - 0 on success, -1 on failure gettimeofday(struct timeval *tv, // I - Timeval struct void *tz) // I - Timezone { struct _timeb timebuffer; // Time buffer struct // Get the current time in seconds and milliseconds... _ftime(&timebuffer); // Convert to seconds and microseconds... tv->tv_sec = (long)timebuffer.time; tv->tv_usec = timebuffer.millitm * 1000; return (0); } pappl-1.4.9/pappl/win32-gettimeofday.h000066400000000000000000000007201476704353100175600ustar00rootroot00000000000000// // Windows gettimeofday header file for the Printer Application Framework // // Copyright © 2021-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_WIN32_GETTIMEOFDAY_H_ # define _PAPPL_WIN32_GETTIMEOFDAY_H_ # include # include // // Functions... // extern int gettimeofday(struct timeval *tv, void *tz); #endif // _PAPPL_WIN32_GETTIMEOFDAY_H_ pappl-1.4.9/pappl/win32-pthread.c000066400000000000000000000221431476704353100165240ustar00rootroot00000000000000// // Windows POSIX threading implementation for the Printer Application Framework // // Copyright © 2021-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "base-private.h" #include // // Private structures... // struct _pthread_s { HANDLE h; // Thread handle void *(*func)(void *); // Thread start function void *arg; // Argument to pass to function void *retval; // Return value from function bool canceled; // Is the thread canceled? jmp_buf jumpbuf; // Jump buffer for error recovery }; // // Local functions... // static long pthread_msec(struct timespec *ts); static DWORD pthread_tls(void); static int pthread_wrapper(pthread_t t); // // 'pthread_cancel()' - Cancel a child thread. // int // O - 0 on success or errno on error pthread_cancel(pthread_t t) // I - Thread ID { if (!t) return (EINVAL); t->canceled = true; return (0); } // // 'pthread_cond_broadcast()' - Unblock all threads waiting on a condition // variable. // int // O - 0 on success or errno on error pthread_cond_broadcast( pthread_cond_t *c) // I - Condition variable { WakeAllConditionVariable(c); return (0); } // // 'pthread_cond_destroy()' - Free memory associated with a condition variable. // int // O - 0 on success or errno on error pthread_cond_destroy(pthread_cond_t *c) // I - Condition variable { (void)c; return (0); } // // 'pthread_cond_init()' - Initialize a condition variable. // int // O - 0 on success or errno on error pthread_cond_init(pthread_cond_t *c, // I - Condition variable const void *a) // I - Attributes (not used) { (void) a; InitializeConditionVariable(c); return (0); } // // 'pthread_cond_signal()' - Wake a single thread waiting on a condition // variable. // int // O - 0 on success or errno on error pthread_cond_signal(pthread_cond_t *c) // I - Condition variable { WakeConditionVariable(c); return (0); } // // 'pthread_cond_timedwait()' - Wait a specified amount of time for a condition // variable. // int // O - 0 on success or errno on error pthread_cond_timedwait( pthread_cond_t *c, // I - Condition variable pthread_mutex_t *m, // I - Mutex struct timespec *t) // I - Timeout { pthread_testcancel(); if (!SleepConditionVariableCS(c, m, pthread_msec(t)) || pthread_msec(t) <= 0) return (ETIMEDOUT); return (0); } // // 'pthread_cond_wait()' - Wait indefinitely for a condition variable. // int // O - 0 on success or errno on error pthread_cond_wait(pthread_cond_t *c, // I - Condition variable pthread_mutex_t *m) // I - Mutex { pthread_testcancel(); SleepConditionVariableCS(c, m, INFINITE); return (0); } // // 'pthread_create()' - Create a new child thread. // int // O - 0 on success or errno on error pthread_create( pthread_t *tp, // O - Thread ID pthread_attr_t *attr, // I - Thread attributes (not used) void *(*func)(void *), // I - Thread start function void *arg) // I - Argument to pass to function { pthread_t t; // Thread data if (!tp || !func) return (EINVAL); (void)attr; if ((t = (pthread_t)calloc(1, sizeof(struct _pthread_s))) == NULL) { *tp = NULL; return (ENOMEM); } *tp = t; t->func = func; t->arg = arg; t->h = (HANDLE)_beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE)pthread_wrapper, t, 0, NULL); if (t->h == 0 || t->h == (HANDLE)-1) return (errno); if (attr && *attr == PTHREAD_CREATE_DETACHED) return (pthread_detach(t)); else return (0); } // // 'pthread_detach()' - Detach a child thread from its parent. // int // O - 0 on success or errno on error pthread_detach(pthread_t t) // I - Thread ID { if (!t) return (EINVAL); CloseHandle(t->h); t->h = 0; return (0); } // // 'pthread_join()' - Wait for a child thread to complete. // int // O - 0 on success or errno on error pthread_join(pthread_t t, // I - Thread ID void **value) // O - Return value from thread function { if (!t) return (EINVAL); pthread_testcancel(); if (t->h) { WaitForSingleObject(t->h, INFINITE); CloseHandle(t->h); } if (value) *value = t->retval; free(t); return (0); } // // 'pthread_msec()' - Calculate milliseconds for a given time value. // static long // O - Milliseconds to specified time pthread_msec(struct timespec *ts) // I - Time value { struct timeval curtime; // Current time gettimeofday(&curtime, NULL); return (1000 * (long)(ts->tv_sec - curtime.tv_sec) + (ts->tv_nsec / 1000 - curtime.tv_usec) / 1000); } // // 'pthread_mutex_destroy()' - Free memory used by a mutex. // int // O - 0 on success or errno on error pthread_mutex_destroy( pthread_mutex_t *m) // I - Mutual exclusion lock { if (!m) return (EINVAL); // Nothing to do... return (0); } // // 'pthread_mutex_init()' - Initialize a mutex. // int // O - 0 on success or errno on error pthread_mutex_init( pthread_mutex_t *m, // I - Mutual exclusion lock const void *attr) // I - Lock attributes (not used) { if (!m) return (EINVAL); (void)attr; InitializeCriticalSection(m); return (0); } // // 'pthread_mutex_lock()' - Lock a mutex. // int // O - 0 on success or errno on error pthread_mutex_lock(pthread_mutex_t *m) // I - Mutual exclusion lock { if (!m) return (EINVAL); EnterCriticalSection(m); return (0); } // // 'pthread_mutex_unlock()' - Unlock a mutex. // int // O - 0 on success or errno on error pthread_mutex_unlock(pthread_mutex_t *m)// I - Mutual exclusion lock { if (!m) return (EINVAL); LeaveCriticalSection(m); return (0); } // // 'pthread_rwlock_destroy()' - Free all memory used by a reader/writer lock. // int // O - 0 on success or errno on error pthread_rwlock_destroy( pthread_rwlock_t *rw) // I - Reader/writer lock { if (!rw) return (EINVAL); // Nothing to do... return (0); } // // 'pthread_rwlock_init()' - Initialize a reader/writer lock. // int // O - 0 on success or errno on error pthread_rwlock_init( pthread_rwlock_t *rw, // I - Reader/writer lock const void *attr) // I - Lock attributes (not used) { if (!rw) return (EINVAL); (void)attr; InitializeSRWLock(rw); return (0); } // // 'pthread_rwlock_rdlock()' - Obtain a reader lock. // int // O - 0 on success or errno on error pthread_rwlock_rdlock( pthread_rwlock_t *rw) // I - Reader/writer lock { if (!rw) return (EINVAL); AcquireSRWLockShared(rw); return (0); } // // 'pthread_rwlock_unlock()' - Release a reader/writer lock. // int // O - 0 on success or errno on error pthread_rwlock_unlock( pthread_rwlock_t *rw) // I - Reader/writer lock { void *val; // Lock value if (!rw) return (EINVAL); val = *(void **)rw; if (val == (void *)1) ReleaseSRWLockExclusive(rw); else ReleaseSRWLockShared(rw); return (0); } // // 'pthread_rwlock_wrlock()' - Obtain a writer lock. // int // O - 0 on success or errno on error pthread_rwlock_wrlock( pthread_rwlock_t *rw) // I - Reader/writer lock { if (!rw) return (EINVAL); AcquireSRWLockExclusive(rw); return (0); } // // 'pthread_self()' - Return the current thread. // pthread_t // O - Thread pthread_self(void) { pthread_t t; // Thread if ((t = TlsGetValue(pthread_tls())) == NULL) { // Main thread, so create the info we need... if ((t = (pthread_t)calloc(1, sizeof(struct _pthread_s))) != NULL) { t->h = GetCurrentThread(); TlsSetValue(pthread_tls(), t); if (setjmp(t->jumpbuf)) { if (!t->h) free(t); _endthreadex(0); } } } return (t); } // // 'pthread_testcancel()' - Mark a safe cancellation point. // void pthread_testcancel(void) { pthread_t t; // Current thread // Go to the thread's exit handler if we've been canceled... if ((t = pthread_self()) != NULL && t->canceled) longjmp(t->jumpbuf, 1); } // // 'pthread_tls()' - Get the thread local storage key. // static DWORD // O - Key pthread_tls(void) { static DWORD tls = 0; // Thread local storage key static CRITICAL_SECTION tls_mutex = { (void*)-1, -1, 0, 0, 0, 0 }; // Lock for thread local storage access EnterCriticalSection(&tls_mutex); if (!tls) { if ((tls = TlsAlloc()) == TLS_OUT_OF_INDEXES) abort(); } LeaveCriticalSection(&tls_mutex); return (tls); } // // 'pthread_wrapper()' - Wrapper function for a POSIX thread. // static int // O - Exit status pthread_wrapper(pthread_t t) // I - Thread { TlsSetValue(pthread_tls(), t); if (!setjmp(t->jumpbuf)) { // Call function in thread... t->retval = (t->func)(t->arg); } // Clean up... while (t->h == (HANDLE)-1) { // pthread_create hasn't finished initializing the handle... YieldProcessor(); _ReadWriteBarrier(); } // Free if detached... if (!t->h) free(t); return (0); } pappl-1.4.9/pappl/win32-pthread.h000066400000000000000000000044551476704353100165370ustar00rootroot00000000000000// // Windows POSIX threading header file for the Printer Application Framework // // Copyright © 2021-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_WIN32_PTHREAD_H_ # define _PAPPL_WIN32_PTHREAD_H_ # include # include // // Constants... // # define PTHREAD_COND_INITIALIZER { 0 } # define PTHREAD_MUTEX_INITIALIZER { (void*)-1, -1, 0, 0, 0, 0 } # define PTHREAD_RWLOCK_INITIALIZER { 0 } # define PTHREAD_CREATE_JOINABLE 0 # define PTHREAD_CREATE_DETACHED 1 // // Types... // typedef struct _pthread_s *pthread_t; // Thread identifier typedef unsigned pthread_attr_t; // Thread creation attributes typedef CONDITION_VARIABLE pthread_cond_t; // Condition variable typedef CRITICAL_SECTION pthread_mutex_t; // Mutual exclusion lock typedef SRWLOCK pthread_rwlock_t; // Reader/writer lock // // Functions... // extern int pthread_cancel(pthread_t t); extern int pthread_create(pthread_t *t, pthread_attr_t *attr, void *(*func)(void *), void *arg); extern int pthread_detach(pthread_t t); extern int pthread_join(pthread_t t, void **value); # define pthread_attr_destroy(attr) # define pthread_attr_init(attr) *(attr) = 0 # define pthread_attr_setdetachstate(attr,s) *(attr) = (s) extern int pthread_cond_broadcast(pthread_cond_t *c); extern int pthread_cond_destroy(pthread_cond_t *c); extern int pthread_cond_init(pthread_cond_t *c, const void *attr); extern int pthread_cond_signal(pthread_cond_t *c); extern int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t); extern int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m); extern int pthread_mutex_destroy(pthread_mutex_t *m); extern int pthread_mutex_init(pthread_mutex_t *m, const void *attr); extern int pthread_mutex_lock(pthread_mutex_t *m); extern int pthread_mutex_unlock(pthread_mutex_t *m); extern int pthread_rwlock_destroy(pthread_rwlock_t *rw); extern int pthread_rwlock_init(pthread_rwlock_t *rw, const void *attr); extern int pthread_rwlock_rdlock(pthread_rwlock_t *rw); extern int pthread_rwlock_unlock(pthread_rwlock_t *rw); extern int pthread_rwlock_wrlock(pthread_rwlock_t *rw); extern pthread_t pthread_self(void); extern void pthread_testcancel(void); #endif // _PAPPL_WIN32_PTHREAD_H_ pappl-1.4.9/pappl/win32-socket.h000066400000000000000000000010631476704353100163700ustar00rootroot00000000000000// // Windows socket header file for the Printer Application Framework // // Copyright © 2021-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _PAPPL_WIN32_SOCKET_H_ # define _PAPPL_WIN32_SOCKET_H_ # include # include // // The BSD socket API is bolted on the side of Windows, so some names are // the same and some are different... // typedef ULONG nfds_t; # define poll(fds,nfds,timeout) WSAPoll(fds,nfds,timeout) #endif // _PAPPL_WIN32_SOCKET_H_ pappl-1.4.9/testsuite/000077500000000000000000000000001476704353100147045ustar00rootroot00000000000000pappl-1.4.9/testsuite/Dependencies000066400000000000000000000023411476704353100172150ustar00rootroot00000000000000pwg-driver.o: pwg-driver.c testpappl.h ../pappl/pappl.h ../pappl/device.h \ ../pappl/base.h \ \ \ \ \ \ \ \ \ ../pappl/system.h \ ../pappl/subscription.h ../pappl/log.h ../pappl/client.h \ ../pappl/printer.h ../pappl/job.h ../pappl/loc.h ../pappl/mainloop.h \ ../pappl/base-private.h ../config.h \ label-png.h testhttpmon.o: testhttpmon.c ../pappl/httpmon-private.h \ ../pappl/base-private.h ../config.h ../pappl/base.h \ \ \ \ \ \ \ \ \ \ test.h testmainloop.o: testmainloop.c testpappl.h ../pappl/pappl.h \ ../pappl/device.h ../pappl/base.h \ \ \ \ \ \ \ \ \ \ ../pappl/system.h \ ../pappl/subscription.h ../pappl/log.h ../pappl/client.h \ ../pappl/printer.h ../pappl/job.h ../pappl/loc.h ../pappl/mainloop.h \ ../pappl/base-private.h ../config.h testpappl.o: testpappl.c ../pappl/system-private.h \ ../pappl/dnssd-private.h ../pappl/base-private.h ../config.h \ ../pappl/base.h \ \ \ \ \ \ \ \ \ \ ../pappl/subscription-private.h ../pappl/subscription.h \ ../pappl/system.h ../pappl/log.h \ testpappl.h ../pappl/pappl.h \ ../pappl/device.h ../pappl/client.h ../pappl/printer.h ../pappl/job.h \ ../pappl/loc.h ../pappl/mainloop.h test.h pappl-1.4.9/testsuite/Makefile000066400000000000000000000033541476704353100163510ustar00rootroot00000000000000# # Test suite makefile for the Printer Application Framework # # Copyright © 2020-2024 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # include ../Makedefs OBJS = \ pwg-driver.o \ testhttpmon.o \ testmainloop.o \ testpappl.o TARGETS = \ testhttpmon \ testmainloop \ testpappl # Make everything all: $(TARGETS) # Clean everything clean: $(RM) -r $(OBJS) $(TARGETS) # Clean all non-distribution files distclean: clean # Update dependencies depend: $(CC) -MM $(CFLAGS) $(OBJS:.o=.c) | sed -e '1,$$s/ \/usr\/include\/[^ ]*//g' -e '1,$$s/ \/usr\/local\/include\/[^ ]*//g' >Dependencies # Install everything install: # Test everything test: testpappl $(RM) testpappl.log $(RM) -r testpappl.output $(MKDIR) testpappl.output ./testhttpmon 2>test.log ./testpappl -c -l testpappl.log -L debug -o testpappl.output -t api,client,pwg-raster 2>test.log # HTTP monitor unit test testhttpmon: testhttpmon.o ../pappl/libpappl.a echo Linking $@... $(CC) $(LDFLAGS) -o $@ testhttpmon.o ../pappl/libpappl.a $(LIBS) $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.$@ $@ # Test suite program testpappl: testpappl.o pwg-driver.o ../pappl/libpappl.a echo Linking $@... $(CC) $(LDFLAGS) -o $@ testpappl.o pwg-driver.o ../pappl/libpappl.a $(LIBS) $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.$@ $@ # Mainloop test program testmainloop: testmainloop.o pwg-driver.o ../pappl/libpappl.a echo Linking $@... $(CC) $(LDFLAGS) -o $@ testmainloop.o pwg-driver.o ../pappl/libpappl.a $(LIBS) $(CODE_SIGN) $(CSFLAGS) -i org.msweet.pappl.$@ $@ # Static resource header... resheader: echo Generating $@... ../pappl/makeresheader.sh label-*.png >label-png.h # Dependencies include Dependencies pappl-1.4.9/testsuite/get-wifi.test000077500000000000000000000006341476704353100173260ustar00rootroot00000000000000# Get Wi-Fi attributes { NAME "Get Wi-Fi attributes" OPERATION Get-Printer-Attributes VERSION 2.0 GROUP operation-attributes-tag ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en ATTR uri printer-uri $uri ATTR keyword requested-attributes printer-wifi-ssid,printer-wifi-state STATUS successful-ok DISPLAY printer-wifi-ssid DISPLAY printer-wifi-state } pappl-1.4.9/testsuite/label-lg.png000066400000000000000000001053071476704353100170770ustar00rootroot00000000000000PNG  IHDR^qqgAMA abKGD̿IDATxwy&=.2$&$H-VD\|Ͽw?LIVItl>٦eY"w"A0`# F9cٙgggw#ڙ7= nnnnnnnnnnnnnnnnnnnnm䖠pbkWRil';ewbhfTn_ ܎-֒xnSNtK\$޿c汓6]ISnp۟BU׃_m)fᒆNtG_L )E>#)7L?"~WV3/ `UWR$~ȡg޿ci#T6$ ]t).9䑟G:+{']#)/mgmw|wW]R 4t `6)2 xΙVl s%NtU|c3JObfo2?/~Ӹ'pTR,\kSfYNL7޿c<*w,N? :13ӿ>ԕ;0K')g:!;!t=R,9,yjώw|WSٖEIxcbc)v `f9}CK+)v `l*'?C72Oqc)v `&ljgĿ\XN2wUt,NtO߃Ygpe+)v #w'b@Y}#dJ`>g W7c|횧qqwpwc)v `:ֹAY '9~^7q36ړ8;6))v `r7 9|­P|mub?0Ꚓbk_݀ܯ,,wa#8/ ôYR<ՀSӲ] %:~-؂#|NRbl,Nuc+dpEgk̿q[&H< >bڳs{N~A_7їᅌ`6.R߇;{KOGϠSpj_7rA،،㊿8 <6Kh?;?,N GW⇸V؈pO ],%8ЎVnVc, xVx͛W|\Xw :6i@u~Xƫ_c4_l-xO yhpgpoy{y؀_@jtwV-?fL8йۿK1o0nh赕zLL4*6i+ `2 U\܌exE܁!l±k+pg o6lO qubghFN"t)p//]Ml:\+qn] z|xh(n&]G:>`spoRy/VRaqzx?`(v *\|܋a܌}rcN0^C}]'tc{>|T+j@v__$9(*5oOxqa7- >h}j(Ã/ =T їGwJ )=Cժz*3e>!܈B1OaAal& Hm~B|f TP֔@j6S)m)ԭ-a,~~g 7 Fz?t $x /:TGekJD p Y!:-|#/M~_ cSx?r ?Y c"qEF`#6q8E{QF* )ַ!2_10!A\9U؋؀m_@Kc7J5KJSӶsS\a&7q0!|c6)J(X*R$)iy枓SeS;ƽ(<X_Hp0j=S]U8'  qh*PDnCqWOSkj)@1܌!ܥ% >A|~܈a܇J起c6e,lm8yO4_xEIT8Sӳ矋!q_cU`#p& sXOaab#f .B]ř,g 1(R):N4Cjs;R7[1ƴ:zQXk a5>1}؈ x;>M<u0e80 \{֫ To<>A|+0b<ڙz'el&< m(`d)̷Ux|cӪ+a G >A\8)9b*S1A| 1w|u?$ !7@vhL5VȀVUpq3{WaU¯_ĝ jWbj  KsBH4NiWTt8I{{iUb7a7. C+ øY/Xf5ưp|7͚eR~;)m 5&@&Ť]'0p#0&c7aoM ĵ?R]ص?4RNs\^,k@gaUa7g1j, p#v^ |21!l]u|/0Ywaj1So~baKJv`Cx8cL_n02ΟA{0Bj @_N/Vd-&/$XUnÙW! cy9WaL 5~CƎ++S_P@wȯ6d(9܏4:m20r< WbN 5~CJNH6 }|9Tu|P5Sm<^ ~oP:^Xb4I= OTL~֟J2y䐟.w1x,v lb_ 4Ox{p8E ` _2JL\㏇€Pw b0fޏZ H6`wu錭x0yLqJNdkd_G&CZ _4Aݴ_v(6jcJtQ[n$ߓn ?P)~3^Db8R b=kӯ G>A\2!?v_G4)+5oඦq~XWHop1aW nwg(;>/'hYslxx[ b aDq.>A\g]W7xF: *8@&h lxA ǰAWa=]Mߘo~ 1)uq||WC@NS)c9@ڿo~9U{DWa?4FUbx(lۗl.GK#@J x/X1iOsbx~|c)>pӀ0jHF#k@?_(og|yUf c=~sdiW?b9;^)9_p klNz1~n[SǛ&He F<6xǑٍoyp ?S)gۆXbZa#x-\|TptNM-1;4N9<k_oċWzk۴Yga靭x'~q `S}ߏ)*-  ⊦7 <Nd]I#xxbn01+cE'k<|Nd6*D"f qe6/)h@Rxx&D/=iPpNK}ߗ:@VmԶ4^|<%p#q*ގA&7v/?SoWo c˗>x]Rg +Ng6<| JSMddM</%`⷏6`-zc%iU+~װQ'4,?' ~p1MO1zL b=MoV|px|ǝHsA|ث:k;dr3$~al b@Pf6|Ů:?q?@۟7Lw5i3Gwb$r\A|iq >c]ou~Rv _ %kچKN?<* øY/X8zŇChO6?q_p@)mj/=;S ٨i317\sѣ˱ SIؿ%j bY_!};>!܈]תO6 56ſZ7j}~j8'ob Çp5j2p'? i3Q c^i-޿p-ߚا⅘$wøii3) c/^HڷQvxV5N?'JPsx?ėbߏ!\/UcWB6<#J5pePc_'6sx&z{pR_R<(e L/~W9|#my!47[G?@ g;ӿi3M A ||e u$S_G~zN\?7Ӗ.kOu>Ti3cn4e<_4\':ͷpjqӏOj|" -6~o9<_r ? m|?7&I2_Op=2Oj|iHn>ƼSMlz /r後zs.5TN7b1@_?.6/+6?~?O\O/AIn@y @olTm {-~%E G cǚӀSpJ8oy䐟aǾ Җ/4 )p*77c5+)JT߫y}~vc/$~`Kq5W"Imb??9&Pݬ۟߇_M՗t~܎k᫸OR/%y^QELZX[;u\X=JGwz܌j\ zw3)Zޓ[x^/5QTU$ ͙/B*c(˸̈grnE\u6]>O#˂" ʵ3_H$ZM4}͝3l T7qο3iWM|=s< b|Ed3i˯* oZ9=+~vojhUjsb>|?! z13KU?kWvYЦO}< R|BZSDPsp~뭾spai0+Hoy~ME ~W0R?9Y{NgqqenqwƻM!XS_nԂukcK|O1mQ/*I˜|~m*}?9܈!.cދ@;S_{vECrC$RBX fa6%܂э $[N&(4;.i,n{qKTKomO̭$濤t(,fek[.P/4׿ˋW(>Jw~{zM6U}-9|)8hj^,xp@ a- It7*6M }1M8-<;plOՁ3PtMIѺ\v31uSsXp nr3Rh >2[ٱp_\ fSr-:?}A1TR^{.9sx{[vTl\:jU@g]'C_Rjh}ݑkz}<IY4YBL@b)onIsM^wWR} Q'? ߩ @R~}2Rjȋ}ߑe~( ;Q]a=BHRINDԲ~oljeJ66hZJџ?i'<1h)nG[P[ KWHA>ֵiTyj/?ߑK%@$iSY*+78<]}  :b+s~@ IC#qU[6OrT^vuVor~ s F@M;f%6kHAlKeZ@ 0B.XLu܊Zǻyn~ɁKmȥA|Yм必uC=ЗB)lJ.p.znfojxŬFr-})Xzj_?Pceǽx3VE|.R_'WSܟ񤠌Xo]B9U}F HQ:^{ ؆cnTIs/ЈWF*?}+ %-ZV[iQiW؂-8 p;&layy{m9 }  ޾i>Pb(K )\SJe Dq;Vc֢qd܌v| .2#MY13n&OZձ"Մ-I<p <ӾqlVp!vΠnŗ;)xAdRPD%@r܃&>g- ))_mit\cX pn#X 0<`b=v:h*Wg~:qLbPDeQ) ma%P5RQ=TԜ'UE꯮'Ii\̆؍ kp6S{g"? !E)k. %&ޭւ=y igg/O7>Ord>Yi$vXLV_p6bz/ p: fx8.Uz ye!-Vğ1oOYU,^XGmDJ3Ɓ&E =ŅX(8>ǔ5%IܥX'mnkk$ (*3`:ˬ"<%Z{ i8)VٰrlD==׋|}e1b-Nc^ċ\gxP ;GV}8\'ټ?$7<=U_mk0 =>7 4C^"jЋ x;0a-C)ZƳx}밪CGgQ2ӱ 'ϭcXךYqWhsr_5VJjH<'-V0 e5aOIXe/I<~:VL{x_oM4W;d._h]TYk_w%:QQSЋmb"9U{|026`S{p7Z@@2*oXrI+xbP8p 'o$Ǘ{e;zU_2`A7&YXJko/3= =Ri6 D fdG@ox soAo)gk oG9{>'6_E9(3H3(.~%%/:6v!`ۇ@qO)pv)jB4e0 @;ϼk:=*fROU\ӧ|R ^sFc1b-C*2d"o SV͗9~('{ތ(kxg&<_Lb H113/ )%mKa -ǝa` :98S<؊SB@ 밎)4j|nLG̗a.kx@J;zZY%|*r  dXwR 7_Էه}!=8p8ͱ TxleBۇ@J]|%뻛o_s])3y޲w_,)F 8]=TWFQ6<8% xKpRS*>ʢd~-[u.Η+/d_Ze ' h/ٍI4T? ^f ;p_SdG ^sQvxH>[$рx; 5uCUfa[Nt L& 6֯* ;^ )41t+_0Լg4 GWr&>7a q_LFS|'B؂թB /9cRP/V_7?fL- P>Q| jPl-V1uq Ȏ{j饙S|ĖCQg/s}jU:}x`sxq }XXT3۽b)H;Dc3(HK@1}'mh/)FtGNtV0 IJn cl>.Up.NǏـ.8|&?b^`x8?&Bg,n)_L;ې&$kBH'2^DOs*vI"10v 8(򘇗{Ng5?tMQAeX @X-_y8G'toH/b2S-8d! ;ZL@9mG _3*SYVT'KO*^hFzbjĔqv /@Z P %)}؇{p,l}z>`+}9#@-/B퉵 /@0I8x|H Xے BxdPGgg , `a\ts`_$YO!j}$j|ЃXBFcylemG880I@j][s|fVA06K|+ Hc}weD/Ml V>_~|,d ~o]s-Fh|<$Hh<>/st,8NOKx< ?8Ӂn4h.Oy>_&<13U=M||A3_`AOOЋ/$@lԝlZT@0ёҪS=#>R%\jq}s? p 뷯GZ1ڊ3a86 6P (F-Cb|yB_|HxF WEu6 z}ZSh ػ|qwZQAY/kL>W+Ch9S+:1-m4&ɛ _>hz}*JƮ at$-c$:^ ew _i.aNcZտ`y||ov褜>S[Z"X6>o|ɱӊ< 8:1"μկ5aZC/>^_>xhi}P!'R|5oo$=ƞi`5Z%9 o>~WdB^_v}TW,_~M'™:/QLŤx gz獅@-ڳVVTZMl^bwh6H  wENj>B3U$);{Et{Nm%rb9}K"3 kY/P;cG^{g<Ntw2/RRֺ R1QȘ#BWHM瓥 Wb^2OXJzMܳ']>y?Ȳ ]?IA AW[(iFC*.^2P# Y[΂i[AA^#Q#*潝΅&"%i*O|K$@~Lf<>?,s7gNUo-qw/@|1sa[4>0NGe#|@ڔ`0Ûs; a0/6P4hbe0d_| 0:oW7ltp@>EӆGs3:;DD^=a"ai=NLz}yOAKƧ0}|O.Sɍͯ:{P6J$ݲ 7sU0&<&4pWrp|BׇS,f>F?syڿef`tp ,2 43 x:i/ `+??;>f>2Ȃ^X~!sҰ/wV-c Ƴ`9^/ oe 'ʐ{Y:(w 殉 p}l^dt)Z+D^3v|h@S)S4ȫk`ko?t|~}֔BrߛO01b~"qMFn -@k"4uK{OY~b1j0d}JO,F/" &o|q '=lw:_m7k[?H?' r}ͷMxxЗԟ/bPK|`6-DL?B|4x)V1Q#GL)LT@ >oď@MRϗޘ zWƂ| [ݩx &I > *@ > #N4/<_g V/ 9/@s˧X;ﯗ1&"wx>* ;7 @}<3f<]|(pDE08|Ă8|I#_@3| 0KO>Oλ3`[hQM~%t7H%>G[ 0q 6~t^[00 { 0S vS{lѥ U'\6x~aMH96&k۾Rs4rs!K=v'$ ?@P>~Kr,}V$aWO(HHnZ2%ZPmTG>Fj+^/r?>ltFM0fղL;3Z_>,V` }KA3crlAky/-;<֑Z ʼDȱޯ:jUCmǏ2-{13 W}\.p@tDJ|)6_%\(>ez}-0 2`& WM$1.H7c䞹TL;_@| <:#j}:OAQ+{qht>#XTǠ*:tWB3&xmtTA[*ޯ*tO_5[ H<av`h/ 99O,+zԀ^_^_BeT~9]s%əM~i[+Wlxm?#IV<2 /i'B >pPXztО Y|M_S_YɉOKJ)l,Qm| pYc_s|"f>е _=7<~C'ks'5bP+ hFu; ^Q8[_V\* f;/eɰQ<ϖAjx2(_)]_g:ݧvyU zczU0BG6 l,ţqMoZ yn5e&*xpԯOhꢶcp2G!1]ӿ}%2F ~ rj$| %G*{ &S@=E B yƤWod#QZ )oOMa(Zw}Zcu}T5 G]?Pq:Ӑi}2}|;Uȭ,! RJg07lviVS @_̬=q78C!8SK.7i9'+i?Qz.7dTp#KMS8O %[6夹@>٦+ZR[a Z|ׇgB{~:AQB\.AT热TXMKl+z4Ixj9iTF &Z]Z 3嶶"TdbL c 0F4%D^}D6)'\ǧlIcVOrc1[a Gg109+[~<u}fBy[=gIod5@x֧u>vO=_/=v(eDS7&)5`v})5ytRߖ`i"嘠дecS=1|n=עL( -*1]K^dDjzPǰ_^ e{2 =4ef1'_Cῶ% ]:30L}=$`fSjPʈ4[ @ck*Q ̭jw5quodL|a7/@5jBUOQ*ŧY| 1>B Roj( ÆY[;D_$xm ~C=Ut0>~qj݄-I`ob7f)x/-XO ݑfq/,y<UZ%?s?@H ?=(Fч yZ9UO0v&/Vgoӣ \@rb\VN>S.XFXzV)ah>_XۢT@Yp b7f"} $ScGes`;dܨz\0p`l? *Ղ|&I˜I@KG t3[Z>#OjU`jxsPp*X5R!k4z>=NuKȐHs}Ic'8_fo\(iHfeaK@+73mKf6@'Fq1V+rBK n|j\- )\x|y5>s:0w:`Ksu؂n^0ʁG ؑ%QB{7eN!=Җo{UXs}`6>o\=t&S!7 }vq!<Eb$|I2=)h @K|'7ǧ*ywO?MI>ݛ y#@}r~7sbi`.J*F^RV+8tB7`y[ & .\A&'an%E `S?ĕ^ ⹣ `;# $(Վ|Pc/Tw3aN92qn=>|ç܋/ek>U/4?jE1}S 1gd@S-l\C.y8Ps AtYf0ڄ|,G iE4ׇbXZWyYWOəx9|!,'4%|d~(M@$|QGUASY=` +l| M_RShz}v. le;d o$?7ehY)\*[4"GLg=/@XbF3A^7 GzH':9E~ $_$O`JfHjVk?{ AA@i pp|Ixd~| ZHq4wBe}Ȁ @H }.oa/% .@="RڟG|Q9G 2E@J#0t+Ɉ||ftz2@qsd@ ?3<߀*n#]@-9/PQ:|<#Q1|^Y l}wZ"R|p~ʛKDhsOӥ&Qd{*da˟ KAأ m1?؛@6% 8Pl|`kdys@ZU>K⋴Vx`2=al}a,׃xyhm|h|@J| z3}EB[y#R%ORO(w+5b7ˊ 0M?k>@/cG1) &{ϝoNF`tZ~Q 6-ko#H>bF>AY,z+TaW2)Q[r 0Gdĉfct 7rE27M/@ݾ ͧ` 0)LNJW|I$&Oȗfi8 :zd3c08ܵ%;=cH0m8#`"@{~<(ST7TU.@(h7@6ޣ(Q~=`bP @ )OAۭO( :5Z(&QF %I]0{,5x+[ Ĩ8_1oJ%!tB"/.4u_C{Z 6)ՌBs8 ~Rv_O<в|]|9'?3 K1rh7ȷa  yILЏG/@I|\`N'׿M <-w|Qw81 $Ž/T;6@EaPHANf>(!y*$Ix<3_W%_Đ/)O.#wZXwr=n^ֆM^%"߰8Ye: y( {{AĖp|`:_oP$_C [(Id| Y2dX_0]>eCsBb/atB!Fwg)h}#ġ4|<q4_煫qo ʁd|xyr5 q)>\syl=W 5!>/꛿apYR< *Ø([&/axk$зP^2j3+[M\]~{?w{/J.@EOS `.@X;>Xͩ-:}^5es"y\O <~{K&>Ys u ~5(&BrtZa B V a0}y"#^>xW7ez9 T|y&"Ψ8Ue&O&@F)w`Ķݎ?\w#k]>`dGPffB|ִxtI؇J| 4/?$-ܓ?ᗏ7#_0n9I1a TfzFa^$xzbO`s^O#/d<߆տ.<|sxna8Kt'#Hnߢ}F UۊXcx??v>xWN26k7x/1nsmbW4)ҹġ*?hޥ{02*H( ҩe;`ËDxrLe Z\6 _ɓz &,i+$[ԭ SSa^=|W(}N/iߠ3uB'"(X͆'OF!^j (,#+?ֳUpM__bNW9Jb~=IہT,߾'P\s1M0tȍ#v/'& /H|N\W͛{djb&$m1v{ /3_(&OWC F>o %4"-fpy,r _ bVYxd&JUa?|esL%? uW?Nh9=)xsD$ϟ0dV%#s|3wPezOU]xʿ@(?v]& ,X=oO>qǻS~K!Wn gOՙ!ҏrwC5d(GMHfsm Y~#>?20k̄ˆJx|j,AHgkvY'rqQߟґ:ѷUߎ `bE>}5H7<3c,dpcȗݛw7/I9ب.d`=· RU)=QMn@5t ȷkC`U;#Өun3[ xXp`A;\¬T_ v8)_t\;ɇE~mz3q3PV e0PZ[d  Oa0I 5+_V{WG؈88* XLH/@ <?oՄ^TDgm͡=q`GFK`$χ-ȿhSa|p@nWf m8{Ğ%607Gy[8 DtwBq6Lxh.]h >zyKE瞏WdU YHAJxG|Nh}?wF_G`/& tnC %;߂*_ۏ/H>uϿϰoȥ\9Gzۿ7X7ֶf`B*B+9st'B0%~ȣWG#d`ڨ!_?OnOQ+1Z.UGI 8 !Bἇ,"I A`/lU0WIǖ/0A* WC#S?|=|㬿 jZä/9nvJ|TOls5rn,'0a#NY׬(]XtbXv oqV%*KwU7fC_QѬ|=_OUWFl 3]ޡ>Um.c 7!'WsijB>H;=< .>ԿJ @3Ếғ/#Ϲ5gQaʍ6_|jy (b^LtB|9Ke)ȷ'b'/'hBsn-q}׊|]y`x>LyX>loL*Ie?%c^ќ,4%0g bN̹%g (=\ZW{ů-\B+|=M}Z3|I;г,4|mfok7 xk0x_Ɠ@$j}\x))o$^W]t{{-sűg<z}ȧo׋ÔkQ᱿(ΰ6_Ԕ@@ߟͧ𦤓IhJ>p2F`4ȟ9r|,xaqлv*04;RZ|]%[ltDZ/Oθ6_7cCczΈ閯V2x|YOb+}e Gωů.Xqk˪&Vt^b&F9G&<9|5ӽZ)PŜIks2c#fݬWkoҴ˟:=B{49߁ImPopd#W[ 8oc>&G11geZ򉕏(꤭,9hL =yR|47@v=G\cJ sbs;fr&䗊_ߣysSJ`)rxz( *hOC;|09JUhIi}Uu%}8^%al3j@(: MRJ+c e?r/D "1?҉Omf|`J.b7pK1S a/=Ac3W'*iCIB>]bggIÛSIo{O/;|brjԸGm:SH^> $_ųxnSIsGo.VyC!|l]Cž_#LKjxs8>Ԍ|Btzs3Oa <X$ؿ8h@~uYs]Z8E7Iʼ?)ɇ_ϟ3ɧ&&y>LNVR՟<Ͱ6_w[CJ ϰf%_h)"D(_NfR&Mm}IIz}|tE8tScB}>AVXǷ&_²EMFˇ/_De -igګ?CC@@\wbִ `}i0:_DtS\NM.BWӑoڅA>SPy\QmX%^/Pk@p0Fp`?<߿^0&C~&(/_ۊ|>$(S/42|u >nkB\"qIz0E/ɇRo\WYTF-W'u_۟][e_Ohp=V 2$WkHih v/|n>!#<2|un IQx{vwORz|`)u_1ɏm[~Ss,l.@E@67lnEڅͣ\'PĨ(:*_-_d ʼQĐϯ)9ͱlIVBw6_ Yb [`ր?<ϣdxLM/"tqÚ#d`K lXH ?ОW3} E+M`zI1h_Ovt`,G=UuAz f&<5~n Q Yˆx4o8U/[>9k-`G;#| xn{m1{LĚRE6Q>%odz |$2T|X~d| S>7gsNv"i ҟ]0DD@rԊ#ǕCj._Xk̇ҬՓv-=d,o.@0PZ|k8VFE&G 0fd) Txk/˳W*Q?bN!N.b9~"M,am|h wz-?zʳWg*0x6< &ԕjN>5g狃[O ߟ r 7-.tEfF-R^p6zY /gaEsK1S \ĂK"RMKrI|+|x|u x#[NK͛`llaʅ>|Dʇ:K&_VsR>4Rx;|u @*їG6n簚sDd6|]0gMԼS 錋@ZVWIO~ xAS xO4 /&z#|,6_@X..?\Yj^~8Jvk /u_UPPRʖFv7A'$> 1Lz=Z0є|KQS ! Z:*ߜ||u %z{|"i=Twd`/}ww -I"Č'(1td#~2G>ȇ!.O>$_h.Ts7[|u^D(A8m'{zpѕj]/jM6rEDk։+_°e {9W+lU"<8i1:j]:YX~fZDsm3JG>gF,5 &hB&?^F_W׍m:_}%d%b`Oyrɍ=anzaB62vXX<S$uF3*%C0|~O?mf۶Vu G }cіqF鼋_*M'n0s6%Q~M!ŸIQ6qUz[е8y6_3CK!PU%.P1}"Em7a "푏Knk)bXd% LߒۖVW )U|4)_h!sM)1#|J\>حmfP%x|ƞ=Xl>my甄ho@ɏ:m M| '-oNPjU6_3QpPBv%G&^+ܞ{,ê* [F-gym#R>7ʸ>߁eM'C3Um_b(mfA` TQAmb^|bG,`Zd$\asOCϔ6_3[AR( &^*L_,8Ƴ}W+ 1|H=OHO/qyV*udXdHFeCLCO6_O@Da.(O<[Ի3+E7dEV/:A:Nn| k}@/O|rD/><{"nА+'!mxv7qYU%>fޑX>ǧ% OweܵJou5B/^2CwO>woxWs *`X7MƧWonsGi~`܌v?B[.3,Y `X/M19HXM^^H6/x~|Nwjz8o<5a_Ww)!P[9#V6XGU<;E\ k³C7*ˏ_GxKǀå|lW|p0Iѐ_|xk\3^d&PWTǂl䋦ViLb۠khKes/t_4d(~ăóL|Š7u0t>3YbB;!%)-e@vM=/z!r^jG QrDź&Kw\O1\nt%kWFg̾0T~@9ws>FƀwNR",n ډc?m:8c.M~.,HU)Wiw>0dD!#G&w6LL=^1a M K>|vY(!Rڒk@̸@D`܃^@B03@at]>jh:>C%ٕL_.6_N$XAcM}tXhD+-%d\.?)߁' |" k@A|vC n=ciȡId<\?"TI\j-ڑ 㒈A ~}"zr E[ )/ҡɇ8V t]# v46WgXo\/R BFАW& /7< സ7v̛@m(ތ| нrw]^ 4:ߞtmH.!/[cjg1`<go@>?)-$u߬~7+?I+sޤ͗;HAC^+Q|ߘ{\ XIDAT[)}4A\}Ց~=Urm([%rQ*Qܜ{8o//$\}4BxB?χ`~sE)vԨ@,vlJ,ǝO2> 7 k 6AC^zſ{*'E!I#1{=O0Z/%GV-z͗S3hr n{77rX~je|m:@DFCO7^Su\3xy9EjfD})k G ̀(FDtoY ۛ~77~$2P)YHDC^)?lȿN'em|g3 $ '|x 2t|90+l&iox|hȣOظ|V?i#ݗڲk 6AC+=lS7>ݼOb7]8%mj볽_+V\/fC (_o^@<\Wi>riBpmyWتa@4CSW!mFn0W 9X)pm`jdE#=i?S`FqBrɵr KlfRqf8G P |9@ `l) -S:.EnTD-KNY>!^rmB[I[-^ g!'@ ) 4~I!Yrm-Q( x`cn7DD[2ޟ%)4CC.JׂiGXMK`ʴf^ѵr АˏtJo O >]/P J1"qpxKn6_NCC^ʕ=>*,IMx~OPS*͗SnIJ̉Ba!NT7 -h\qmp#-" yÞgg۰MOx3T woŵr &5*VM; B_ ~x*\/h!hj WĭSԋ3d/ %PQ͗Sna ħ!+y)'-߇zq݂ |9Fʶ"R*'&zx,*!8'|9FOCnErw7K-(C})72 $!F*`L kjkMҐ; $#q.O{r 8-`!N4=A/k_嫁kmu!_^V`.*_ \/ܘ[ ~Μ!m{pr id  _9 4yFPFp|9ƴMѐ-4"VS_R>#շkl Ģ!MN, O΄aw@AyeF|94qiբrPX|%ݵ|܇ƍt?м?^Oԟ|@Z^y SrYntC :n<K>ˮ͗d[S)K rE*q2T_/WAf?Ynt-JD`'6agI@㡭_6$wm T)րyƕX$@o‡J(~]/`5`J`Jx;*qo "1pm8EՋDMU毸>?Nj(m)'_o]N12 %Pԓ}Sppc9 6:f;)7f-.WWA3p)7f-)B 1%n;l`oXBПN1$9 ZſN1lm(WN1Km0 w)7fA0˧N1@'(pkp 7p 7p 7p 7p 7p 7p 7p 7p 7p 7p 7p 7p 7?u *8eXIfMM*i(0%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ExifOffset26SetEXtexif:PixelXDimension512.tEXtexif:PixelYDimension512+!YIENDB`pappl-1.4.9/testsuite/label-md.png000066400000000000000000000133621476704353100170740ustar00rootroot00000000000000PNG  IHDRi7@gAMA abKGD̿IDATx]{te~2d22פ=MkSPʥ E]nbP\Q xY*ꮫz9 U9v)"[D-Py~IfN.͛{~G֑udYG^upުAuo-Coױf_dV=O0|p=&ъne[ߵ`w-80h'?R3D ^ F@K]twdzci1`7_ W> C ?`5nTk&W}hc+up# ܢ,N7s8/0>Q/ t^{uZ.P.^y ]Wo7Zm=a-d_7[y˂o5y@}1|ˢ2|c.fzi}{18ˑV _RE/LSg`zܧ1xN*:<)~4.n*+W?PIFK9Yx%j~SU"޹TԆqY*/1Uc_n_z"RE..;߿,~_sϔXd8=;B%J$߸kcTDO51s0. rCB=4 rr"ȅ6p+?nrR"eDp?ND‹)Z8 qL1¨f 8jQrJѤ i.8M̉>m-uRRsF" ƦS'8qQ ]1U =q͐/ )edׅaCPv,J8g~{CѵNsJ1äƅ՚.\/^ m>]HX"u w5tC,Mc:jZNsZ1'B6Ð .]2fJ/.;rO9~.űh2=gviW;!^kijrڧu]#ja@ scYPf$ڬCZ`g-mic#5/^7&}x|f.L(Z/ Nk9Lly( \%zxMךĊ+%ٹspmD9㰭hқn[]my(˿-C6X&JrmJ%PyN5'WϮyvR4sP4 9pEP4tml{:\Fv[m3hVfn (U2L25Lj\tj3PHYry͓OO9°Qp#YyLȽGc.nH[-s5 巜&izv]% zX-?| Fu`]KUmL`v'Ҽ;\Ƌq8}hYn BNn3lߙ* vL9"c(ѯC !|]seR誚'ԼI;b'g\ 7"я+VOvea' VIuaǴC1ZVNC<_I;[w+=is]ZeQkTE\J\14p!f )TctE3hd'^QgCOx.ĉDbmE_r_,|&lZG՛!="?y.;0@Ƅ3|.jJmq-uoKp!abCl჈2Īb$~P/Do#p6 {Ƴ2|_ "ȣ (jv{tc[ <N*X:!EAύAxiGZ9lqEG߆9 @kp:ƑCPoǐ&9+vѷ ULA2 g.?]<;\ &0>y x&Q,MhEFG/72 hp$ ԯ|woKWpP<[1vtc}=;C-8kPDp,^σ[p2& s0ȡ#rQ%Ђ4~+7s!7.YG֑ud0 (~*8eXIfMM*ikF&M%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ExifOffset26SetEXtexif:PixelXDimension128zߪtEXtexif:PixelYDimension128KIENDB`pappl-1.4.9/testsuite/label-png.h000066400000000000000000005240511476704353100167250ustar00rootroot00000000000000/* label-lg.png */ static unsigned char label_lg_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,2,0,0,0,2,0,8,4,0,0,0,94,113,28, 113,0,0,4,25,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,187,115,103,35, 36,206,83,108,52,133,116,168,63,13,37,13,147,86,52,161, 180,186,127,221,221,54,110,150,73,54,218,34,232,100,246,238, 206,152,201,206,56,51,187,253,161,79,69,80,124,49,234,155, 20,196,191,183,128,32,40,245,15,219,62,180,47,149,10,37, 218,212,32,40,62,180,248,131,80,232,139,166,235,153,59,51, 153,105,186,177,222,101,238,124,243,157,239,158,123,238,185,103, 239,5,232,185,170,88,150,145,20,1,22,154,174,45,23,50, 226,115,135,143,136,61,43,144,132,135,160,23,6,161,87,81, 29,43,93,169,76,2,54,79,11,119,181,91,223,67,194,123, 95,217,213,221,254,159,173,183,70,29,21,32,113,31,98,179, 230,168,11,136,143,1,240,167,85,203,118,1,122,250,145,31, 63,234,90,30,246,98,232,183,49,64,196,47,122,184,225,99, 215,195,115,62,126,141,105,102,228,44,226,211,136,5,85,83, 106,136,151,16,143,204,197,248,70,12,251,49,176,214,95,160, 77,106,235,170,232,229,162,98,155,117,221,160,177,112,239,97, 254,159,109,193,104,133,243,109,195,167,207,153,159,62,132,239, 97,92,251,43,53,37,231,225,81,196,75,170,146,159,70,252, 8,226,107,109,125,182,28,224,219,150,155,145,17,63,6,144, 220,222,154,175,166,17,239,68,92,172,219,7,170,190,159,164, 173,181,138,33,126,231,132,54,243,44,226,45,136,207,55,231, 202,83,193,216,171,170,147,197,156,193,118,196,183,53,90,242, 242,59,4,192,137,186,91,154,241,199,114,251,109,83,158,242, 231,229,234,53,154,203,123,121,68,252,250,188,121,72,246,125, 114,159,57,237,233,124,232,243,132,150,45,7,252,165,151,148, 131,21,196,131,136,127,161,70,65,246,231,226,254,177,220,74, 16,3,25,106,26,229,73,127,46,146,163,14,91,47,227,93, 109,166,232,207,75,12,23,55,212,31,75,22,235,250,129,82, 160,255,68,179,139,114,128,175,89,6,171,81,140,141,79,218, 45,185,234,235,249,81,197,206,23,124,159,124,133,54,171,129, 127,190,13,179,9,5,40,152,48,135,189,10,77,88,3,17, 100,40,64,6,223,22,216,104,169,131,14,6,50,20,173,20, 25,138,95,161,102,23,27,231,192,60,242,58,180,153,205,193, 190,194,148,254,200,200,95,131,249,184,206,180,42,100,135,62, 130,22,178,26,252,142,172,22,211,101,241,171,133,92,99,19, 63,126,44,55,2,63,38,25,32,18,217,131,207,94,50,73, 246,145,113,50,1,34,121,138,60,77,246,147,28,178,19,100, 239,250,216,74,108,69,94,60,55,214,253,188,140,51,82,166, 155,69,221,57,180,187,160,96,255,51,42,76,92,83,215,172, 44,14,182,134,35,203,41,251,5,93,189,252,198,95,177,92, 233,44,55,81,182,226,25,157,186,87,206,249,95,249,235,252, 50,246,43,252,106,164,224,127,228,87,241,183,114,199,90,204, 187,178,76,195,236,108,88,115,119,85,26,109,6,227,22,240, 209,153,197,137,197,29,243,113,241,228,87,15,70,126,150,201, 153,231,175,244,93,60,89,111,46,14,70,172,151,5,250,106, 249,86,25,78,141,68,172,244,131,244,135,180,44,189,39,125, 40,253,198,189,205,125,202,125,205,125,206,125,193,93,2,145, 59,203,157,227,190,225,46,112,31,115,95,198,246,106,243,26, 90,223,123,22,121,24,183,103,233,150,107,172,74,33,35,108, 21,30,22,114,194,54,225,81,97,50,242,39,12,8,99,66, 81,216,129,150,173,235,251,22,159,47,158,61,29,14,99,31, 230,167,251,92,190,46,86,1,137,251,177,2,244,77,254,85, 85,84,233,112,148,41,29,86,111,77,56,190,65,19,140,36, 67,100,140,148,54,84,247,184,87,243,161,34,149,79,229,82, 105,16,83,59,83,19,169,177,212,65,15,135,179,166,118,160, 109,2,251,252,29,213,169,110,178,82,234,210,99,222,125,2, 89,211,58,110,235,13,205,21,119,75,210,147,98,26,175,54, 42,150,154,234,232,136,168,24,134,200,76,142,104,83,135,218, 109,90,27,5,239,222,244,143,244,155,50,187,15,19,91,46, 71,156,251,12,192,190,63,241,236,251,46,226,142,180,0,150, 28,128,129,199,35,110,24,207,202,7,222,5,56,243,132,218, 178,219,193,29,145,72,124,11,224,212,247,236,246,191,250,50, 120,126,253,212,233,220,196,115,172,231,45,128,181,55,59,157, 191,223,239,116,214,62,64,255,171,0,103,141,127,1,160,159, 124,85,3,92,11,239,0,0,0,56,101,88,73,102,77,77, 0,42,0,0,0,8,0,1,135,105,0,4,0,0,0,1, 0,0,0,26,0,0,0,0,0,2,160,2,0,4,0,0, 0,1,0,0,2,0,160,3,0,4,0,0,0,1,0,0, 2,0,0,0,0,0,40,48,151,191,0,0,3,99,105,84, 88,116,88,77,76,58,99,111,109,46,97,100,111,98,101,46, 120,109,112,0,0,0,0,0,60,120,58,120,109,112,109,101, 116,97,32,120,109,108,110,115,58,120,61,34,97,100,111,98, 101,58,110,115,58,109,101,116,97,47,34,32,120,58,120,109, 112,116,107,61,34,88,77,80,32,67,111,114,101,32,53,46, 52,46,48,34,62,10,32,32,32,60,114,100,102,58,82,68, 70,32,120,109,108,110,115,58,114,100,102,61,34,104,116,116, 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49, 57,57,57,47,48,50,47,50,50,45,114,100,102,45,115,121, 110,116,97,120,45,110,115,35,34,62,10,32,32,32,32,32, 32,60,114,100,102,58,68,101,115,99,114,105,112,116,105,111, 110,32,114,100,102,58,97,98,111,117,116,61,34,34,10,32, 32,32,32,32,32,32,32,32,32,32,32,120,109,108,110,115, 58,100,99,61,34,104,116,116,112,58,47,47,112,117,114,108, 46,111,114,103,47,100,99,47,101,108,101,109,101,110,116,115, 47,49,46,49,47,34,10,32,32,32,32,32,32,32,32,32, 32,32,32,120,109,108,110,115,58,73,112,116,99,52,120,109, 112,69,120,116,61,34,104,116,116,112,58,47,47,105,112,116, 99,46,111,114,103,47,115,116,100,47,73,112,116,99,52,120, 109,112,69,120,116,47,50,48,48,56,45,48,50,45,50,57, 47,34,10,32,32,32,32,32,32,32,32,32,32,32,32,120, 109,108,110,115,58,112,104,111,116,111,115,104,111,112,61,34, 104,116,116,112,58,47,47,110,115,46,97,100,111,98,101,46, 99,111,109,47,112,104,111,116,111,115,104,111,112,47,49,46, 48,47,34,62,10,32,32,32,32,32,32,32,32,32,60,100, 99,58,99,114,101,97,116,111,114,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,62,77,105,99,104,97,101,108,32, 83,119,101,101,116,60,47,114,100,102,58,108,105,62,10,32, 32,32,32,32,32,32,32,32,32,32,32,60,47,114,100,102, 58,83,101,113,62,10,32,32,32,32,32,32,32,32,32,60, 47,100,99,58,99,114,101,97,116,111,114,62,10,32,32,32, 32,32,32,32,32,32,60,100,99,58,114,105,103,104,116,115, 62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114, 100,102,58,65,108,116,62,10,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,108,105,32,120, 109,108,58,108,97,110,103,61,34,120,45,100,101,102,97,117, 108,116,34,62,67,111,112,121,114,105,103,104,116,32,50,48, 49,57,32,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,114, 105,103,104,116,115,62,10,32,32,32,32,32,32,32,32,32, 60,73,112,116,99,52,120,109,112,69,120,116,58,72,101,97, 100,108,105,110,101,62,78,101,119,32,73,99,111,110,60,47, 73,112,116,99,52,120,109,112,69,120,116,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 112,104,111,116,111,115,104,111,112,58,72,101,97,100,108,105, 110,101,62,78,101,119,32,73,99,111,110,60,47,112,104,111, 116,111,115,104,111,112,58,72,101,97,100,108,105,110,101,62, 10,32,32,32,32,32,32,60,47,114,100,102,58,68,101,115, 99,114,105,112,116,105,111,110,62,10,32,32,32,60,47,114, 100,102,58,82,68,70,62,10,60,47,120,58,120,109,112,109, 101,116,97,62,10,221,242,56,27,0,0,136,242,73,68,65, 84,120,218,236,189,105,152,28,197,149,46,252,70,86,117,183, 122,213,46,33,196,34,1,66,18,8,12,24,240,138,61,198, 120,199,44,234,70,120,27,207,238,103,54,143,239,60,119,190, 59,51,159,231,218,247,142,237,241,246,217,30,251,218,227,229, 122,240,12,94,198,136,110,36,36,192,160,21,16,2,1,98, 19,59,18,8,132,214,214,174,222,107,201,243,253,168,45,35, 226,68,102,86,85,102,117,117,87,4,143,161,93,167,59,35, 43,50,207,137,179,189,111,0,118,216,97,135,29,118,216,97, 135,29,118,216,97,135,29,118,216,97,135,29,118,216,97,135, 29,118,216,97,135,29,118,216,97,135,29,118,216,97,135,29, 118,216,97,135,29,118,216,97,135,29,118,216,97,135,29,118, 216,97,135,29,118,216,97,135,29,118,216,97,135,29,118,216, 97,135,29,118,216,97,135,29,118,216,97,135,29,118,216,97, 135,29,118,216,97,135,29,118,216,97,135,29,118,216,97,71, 77,135,176,75,208,64,207,148,236,226,216,33,143,164,93,130, 73,168,248,193,102,221,154,2,59,172,7,48,9,159,163,40, 254,44,12,74,79,30,245,183,102,192,122,0,118,9,38,137, 250,203,255,83,141,128,172,252,36,41,191,53,3,118,231,176, 99,130,63,193,130,218,139,188,242,11,143,47,0,143,242,23, 254,205,153,2,107,8,172,1,176,99,130,170,191,252,143,35, 249,1,5,245,46,41,63,121,140,128,53,3,246,5,178,99, 194,187,254,5,181,247,254,79,55,0,165,127,92,197,8,144, 20,38,88,51,96,13,128,29,19,72,253,75,106,95,248,71, 180,53,15,103,61,38,64,85,126,87,49,8,124,88,96,205, 128,53,0,118,212,185,250,59,249,221,223,129,131,4,156,142, 38,231,3,180,28,87,97,182,120,197,189,71,108,74,63,55, 90,218,231,221,226,255,74,70,192,181,97,129,53,0,118,76, 100,245,119,32,144,128,131,4,18,93,31,197,255,166,133,148, 23,18,0,113,68,220,75,155,199,30,79,141,122,20,191,240, 15,25,13,129,53,3,214,0,216,49,65,212,63,183,247,39, 144,232,248,107,241,101,210,30,41,65,128,70,157,205,180,41, 243,240,200,49,143,250,7,25,2,72,255,182,97,129,53,0, 118,212,205,83,211,213,63,217,249,71,248,102,65,225,229,127, 151,108,129,216,78,27,178,91,134,95,135,11,23,89,131,17, 112,67,100,7,172,33,176,6,192,142,186,81,255,36,18,93, 55,187,63,16,194,171,242,37,19,160,154,4,241,58,221,231, 62,152,222,145,74,27,188,1,155,29,176,6,192,142,186,86, 127,201,245,71,178,243,227,248,25,28,72,170,175,27,3,89, 46,78,184,235,177,121,108,123,122,128,245,6,248,236,128,45, 26,90,3,96,199,184,71,255,165,130,95,18,9,36,219,175, 113,254,19,201,210,94,207,7,0,6,121,26,91,104,83,102, 235,232,33,197,8,232,217,129,194,127,97,139,134,214,0,216, 49,190,234,95,200,251,39,145,236,184,74,252,154,90,4,224, 179,219,19,2,229,59,176,62,187,37,179,51,149,85,242,3, 196,24,2,155,29,176,6,192,142,250,80,255,174,43,220,149, 162,45,183,187,67,138,247,75,197,64,129,208,242,3,184,215, 189,63,245,76,122,140,241,7,204,105,66,155,29,176,6,192, 142,26,170,127,62,239,143,100,251,91,18,189,212,165,254,42, 5,60,214,32,57,134,176,209,221,236,110,27,57,145,87,253, 172,209,27,176,69,67,107,0,236,24,47,245,239,88,234,220, 225,206,224,163,254,210,190,94,177,60,139,109,180,49,253,208, 216,94,45,73,168,166,9,109,75,177,53,0,118,212,64,253, 133,39,243,223,212,122,94,114,21,230,148,252,109,225,179,191, 87,35,23,175,184,235,178,247,103,95,74,101,60,254,0,41, 129,129,13,11,172,1,176,163,134,234,159,108,91,144,88,133, 249,222,184,94,175,249,3,17,202,15,139,245,153,251,211,219, 211,35,6,127,192,182,20,91,3,96,71,173,212,191,125,126, 98,149,187,64,248,70,249,132,24,228,163,226,254,124,75,113, 54,100,75,49,20,83,96,195,2,107,0,236,168,80,253,11, 133,191,185,206,29,180,72,141,227,185,253,59,38,57,57,79, 208,134,236,150,225,221,182,165,216,26,0,59,106,172,254,205, 51,91,122,113,161,30,171,115,105,190,120,229,206,27,116,159, 251,64,250,217,84,202,182,20,91,3,96,71,77,212,191,101, 122,203,111,233,82,147,187,206,39,248,226,149,227,36,54,208, 166,177,199,211,3,154,63,96,91,138,173,1,176,35,66,245, 79,76,233,106,254,13,189,77,194,251,51,251,245,184,200,211, 226,33,218,148,217,58,122,48,68,75,113,238,39,219,82,108, 13,128,29,161,213,63,129,228,148,206,166,91,233,221,194,184, 67,243,169,187,26,203,159,21,235,179,91,50,175,216,150,98, 107,0,236,136,84,253,91,219,154,110,161,247,251,226,253,181, 88,125,220,228,7,112,159,123,127,234,153,244,168,109,41,182, 6,192,142,40,212,191,53,249,19,124,52,28,222,191,94,228, 206,16,109,114,55,187,143,216,150,98,107,0,236,168,68,253, 69,161,238,223,218,146,252,33,110,128,18,143,251,227,253,235, 70,238,226,81,218,144,222,226,219,82,28,46,44,176,102,192, 26,128,70,84,255,182,230,228,119,233,230,10,241,254,117,35, 199,78,177,46,253,96,246,249,98,75,177,139,172,109,41,182, 6,192,14,78,253,133,167,235,47,153,248,166,251,217,170,241, 254,245,34,63,66,235,196,253,163,92,75,177,31,93,57,108, 209,208,26,128,70,83,127,7,73,36,145,236,252,10,254,52, 50,188,127,189,200,199,156,7,178,27,221,135,71,142,218,150, 98,107,0,236,48,169,127,2,77,93,255,68,127,165,254,106, 181,120,255,186,145,147,120,146,54,100,31,26,126,213,182,20, 91,3,96,159,131,144,64,63,73,36,208,212,249,63,232,111, 99,195,251,215,141,92,236,161,251,220,7,210,59,82,105,67, 209,208,102,7,172,1,104,48,245,79,32,137,100,231,223,226, 239,75,239,117,92,120,255,122,145,59,39,105,35,109,30,123, 212,182,20,91,3,96,213,63,137,100,215,95,208,151,107,136, 247,175,23,121,70,60,68,155,50,15,133,110,41,134,45,26, 90,3,48,25,119,255,63,161,175,141,3,222,191,126,228,207, 209,6,247,1,219,82,108,13,64,99,170,255,103,241,173,113, 196,251,215,143,252,0,214,185,15,164,158,178,45,197,214,0, 76,94,245,47,29,243,85,112,254,63,73,223,133,24,127,188, 127,189,200,197,16,109,118,55,141,109,203,28,151,90,138,201, 30,109,106,13,192,36,84,255,142,155,196,15,188,207,101,188, 241,254,117,35,119,241,24,109,72,63,104,89,138,173,1,152, 196,234,223,121,61,126,76,78,29,226,253,235,70,46,118,186, 235,179,15,100,95,240,28,109,106,91,138,173,1,152,36,234, 255,49,250,153,72,152,118,200,186,192,251,215,137,92,28,197, 58,218,60,106,89,138,173,1,152,36,234,159,64,83,215,7, 233,150,220,33,159,117,143,247,175,23,249,168,115,63,109,206, 108,45,131,165,216,102,7,172,1,168,19,245,87,142,248,110, 191,198,249,15,52,77,36,188,127,221,200,201,217,78,27,178, 15,89,150,98,107,0,38,198,154,51,234,223,241,62,113,43, 154,229,120,119,130,224,253,235,70,46,10,44,197,182,165,216, 26,128,9,162,254,57,200,79,178,227,61,226,87,212,50,177, 241,254,245,34,23,39,104,3,109,182,44,197,214,0,76,4, 245,207,165,254,222,69,191,22,173,240,217,237,38,16,222,191, 94,228,105,60,68,27,51,15,91,150,98,107,0,234,92,253, 219,222,158,252,47,183,109,146,225,253,235,71,254,44,214,103, 31,204,236,180,45,197,214,0,212,165,250,119,93,129,219,168, 93,254,197,73,131,247,175,31,249,1,220,231,62,144,122,42, 61,102,91,138,173,1,168,167,221,255,173,137,219,208,201,185, 178,4,129,165,248,26,230,99,53,214,224,249,73,205,7,80, 43,185,24,162,77,238,38,119,155,101,41,182,6,96,60,214, 185,68,245,153,87,255,246,75,19,43,169,171,240,62,201,25, 237,185,248,159,248,12,156,252,103,111,96,53,238,194,99,249, 55,113,114,242,1,212,76,238,138,109,180,49,128,165,184,97, 90,138,173,1,24,63,245,127,75,226,118,119,42,135,151,111, 194,23,240,223,209,174,93,230,48,238,198,29,216,138,244,100, 230,3,168,153,92,188,226,174,203,62,152,125,161,200,82,156, 245,0,140,26,166,165,216,26,128,241,82,255,139,156,219,49, 157,251,245,247,226,59,56,223,231,114,39,113,15,214,98,19, 134,208,208,124,1,81,201,143,136,117,84,29,75,241,132,54, 3,214,0,140,139,250,119,92,232,244,210,12,29,15,63,27, 223,192,77,161,46,59,138,245,184,19,27,112,180,177,249,2, 162,146,143,138,7,178,155,202,98,41,158,36,217,1,107,0, 198,67,253,151,58,125,52,83,199,195,223,140,111,97,70,89, 151,207,224,1,172,197,61,56,136,70,230,11,136,76,78,226, 201,236,122,218,218,72,44,197,214,0,212,92,253,59,23,163, 15,179,85,119,116,46,190,143,143,85,56,13,225,81,172,197, 221,120,173,177,249,2,34,147,139,55,104,93,163,176,20,91, 3,80,27,245,47,1,126,23,163,151,230,168,120,247,27,240, 175,101,238,253,220,120,22,119,99,53,94,104,112,190,128,168, 228,226,164,187,1,155,199,30,155,220,45,197,214,0,212,86, 253,23,81,159,152,43,255,226,20,124,27,127,16,225,196,175, 99,53,238,194,227,158,77,200,242,9,84,33,79,211,86,108, 204,108,157,172,44,197,214,0,212,84,253,209,135,185,50,184, 245,34,252,135,111,206,191,210,113,8,107,177,6,91,144,101, 93,94,203,39,80,182,252,89,108,200,62,56,249,88,138,173, 1,168,141,250,39,208,212,122,94,178,23,243,228,36,212,103, 241,29,180,196,120,35,167,112,23,214,98,35,70,97,249,4, 34,145,31,192,125,238,253,169,103,2,88,138,39,80,209,208, 26,128,218,168,127,178,245,188,100,47,78,247,190,90,205,248, 54,254,168,38,55,52,130,117,88,139,117,56,161,196,187,150, 79,160,50,57,134,176,201,221,236,110,27,57,62,241,91,138, 173,1,168,141,250,159,155,236,163,211,189,217,230,249,248,21, 46,175,233,141,101,112,63,214,226,30,28,130,229,19,136,68, 238,226,81,177,49,187,101,232,77,159,150,226,186,15,11,172, 1,168,133,250,159,147,232,19,243,189,47,210,229,248,45,230, 140,203,13,18,30,195,157,184,27,187,153,136,215,188,27,90, 185,89,238,236,194,186,244,131,217,231,61,44,197,122,96,80, 183,69,67,107,0,226,87,255,133,201,62,58,195,139,87,191, 30,63,67,235,56,223,234,14,172,197,157,120,9,150,79,32, 26,185,115,204,93,239,222,159,126,60,61,84,70,75,113,29, 20,13,173,1,168,129,250,227,12,239,175,253,45,254,87,25, 203,254,69,252,0,87,160,27,203,49,47,134,91,126,13,107, 176,22,143,107,94,130,229,19,168,80,158,18,91,104,99,250, 225,209,254,137,82,52,180,6,32,86,245,111,91,224,244,137, 51,189,47,205,191,226,143,203,186,108,39,6,243,151,127,55, 150,99,57,206,138,225,214,15,97,13,238,196,195,200,88,62, 129,168,228,207,96,125,118,75,102,87,42,235,211,66,84,23, 217,1,107,0,98,85,255,100,31,157,89,120,138,2,77,248, 57,110,44,243,194,95,196,55,224,122,254,255,149,232,70,55, 206,141,225,43,28,207,163,12,71,44,159,64,84,242,253,88, 231,222,159,126,42,149,170,152,135,40,118,127,192,26,128,248, 212,255,236,100,159,123,86,41,110,108,195,111,112,117,5,23, 63,136,62,244,225,65,169,165,231,50,116,163,39,150,6,162, 97,172,199,26,220,135,83,158,23,219,242,9,84,35,119,6, 105,179,187,217,125,164,62,121,136,172,1,136,77,253,157,62, 113,150,215,149,95,133,43,171,152,228,8,86,161,15,155,144, 246,124,118,1,86,160,27,203,98,248,74,105,60,136,59,113, 15,250,125,162,96,203,39,80,150,220,197,163,180,33,128,135, 40,56,63,16,185,17,176,6,32,182,221,159,206,42,197,137, 83,177,58,146,170,255,9,220,137,94,108,192,168,231,179,69, 184,9,221,184,44,134,175,230,226,81,220,137,123,176,219,242, 5,68,38,119,118,98,125,90,62,218,212,156,38,116,125,139, 134,214,0,212,191,250,231,70,23,238,196,91,35,156,116,16, 107,208,135,123,49,236,249,108,1,122,208,131,43,99,121,160, 207,96,45,214,224,69,203,23,16,153,92,28,197,250,204,253, 233,237,198,162,33,31,26,168,33,129,53,0,245,171,254,165, 95,234,192,218,72,213,191,20,173,223,131,62,220,141,1,207, 103,243,209,141,30,188,171,72,38,26,229,120,21,107,113,39, 158,240,117,119,45,159,64,89,114,190,104,152,85,76,129,203, 96,11,34,51,1,214,0,196,150,250,203,61,163,86,172,198, 59,99,188,137,49,220,135,94,220,133,227,158,207,230,98,57, 186,241,94,36,99,152,239,0,214,226,78,108,205,135,168,150, 79,32,18,249,51,88,159,221,50,188,211,163,254,89,35,39, 145,220,58,100,13,64,157,169,255,2,167,215,155,250,75,226, 191,240,161,144,23,220,131,63,193,22,44,195,10,220,136,69, 101,39,237,54,162,23,107,112,216,243,217,76,220,128,30,92, 93,56,113,52,210,113,12,247,224,46,108,42,162,12,45,159, 64,4,242,125,88,231,222,159,126,58,149,59,188,36,43,253, 219,107,6,34,53,1,214,0,68,170,254,201,62,58,211,67, 60,141,91,208,29,250,146,215,96,99,241,231,75,208,141,229, 184,160,204,155,202,226,126,244,97,53,14,120,62,155,138,235, 208,131,15,98,74,12,139,48,148,71,25,158,50,198,186,150, 79,160,92,185,24,164,77,238,38,119,59,57,180,127,44,139, 44,50,200,42,102,64,14,5,172,1,168,71,245,207,61,232, 111,226,47,203,184,232,20,140,41,159,44,198,205,184,17,151, 148,121,115,46,182,162,23,171,240,38,188,121,136,107,209,141, 143,48,103,13,84,63,82,121,148,97,191,229,11,136,78,190, 79,164,220,227,226,171,3,59,144,65,70,50,3,37,35,16, 137,15,96,13,64,68,234,223,186,176,169,55,215,245,87,120, 136,127,129,111,150,117,217,15,96,3,251,249,185,184,9,203, 113,69,217,183,249,40,122,113,7,94,243,124,210,138,143,160, 27,215,162,43,134,69,113,177,13,107,112,23,246,192,242,5, 68,38,31,166,27,134,94,71,6,105,205,8,68,230,3,88, 3,16,145,250,23,16,127,133,71,123,45,126,93,102,46,126, 15,254,16,155,141,210,179,208,141,110,188,179,236,7,246,36, 250,112,7,94,242,124,210,140,15,162,7,31,143,128,132,148, 27,79,99,45,214,224,37,203,23,16,137,220,185,247,212,223, 33,141,116,222,8,148,76,0,21,189,0,107,0,234,64,253, 207,73,244,138,51,188,15,242,82,220,91,17,224,247,85,220, 142,62,108,55,202,231,161,7,221,120,55,18,101,94,247,57, 244,161,23,207,193,155,158,124,63,186,113,125,76,172,4,187, 176,22,107,240,4,44,95,64,149,114,74,125,120,108,63,210, 72,21,141,64,201,4,68,226,3,88,3,80,189,250,159,155, 236,165,249,94,188,248,108,60,136,249,85,76,179,7,189,232, 197,54,227,211,157,141,229,232,198,239,161,169,204,235,238,196, 237,232,195,147,158,79,18,120,15,186,113,99,129,171,44,226, 177,31,107,177,6,91,225,90,190,128,138,229,244,149,193,213, 72,33,133,84,222,19,200,32,83,60,199,208,26,128,113,83, 255,68,129,235,215,203,245,151,27,77,184,11,239,136,96,186, 3,232,67,47,30,98,120,125,115,99,58,110,64,15,222,95, 54,169,232,235,232,69,111,254,164,225,194,23,123,39,122,98, 130,26,3,71,243,37,195,49,195,30,168,15,43,47,201,197, 186,83,95,66,10,41,140,21,253,128,140,148,9,176,6,96, 220,212,63,137,68,235,121,137,94,113,186,236,202,253,0,127, 24,225,180,135,113,7,250,112,191,4,2,242,142,46,124,28, 61,248,80,217,1,199,62,244,161,55,223,208,83,24,87,162, 27,203,113,94,44,203,55,152,71,25,14,42,17,175,229,19, 240,151,227,240,192,114,164,48,134,177,162,23,144,246,212,3, 172,1,24,71,245,207,237,254,243,114,143,171,176,148,159,197, 15,99,152,254,56,86,163,23,27,181,66,97,97,180,227,99, 232,198,71,209,81,230,117,15,225,14,244,225,1,100,60,159, 93,130,110,244,96,73,44,203,152,194,102,172,197,61,56,162, 237,121,150,79,192,36,79,93,55,118,20,99,146,9,200,72, 121,0,107,0,198,71,253,59,23,161,151,78,147,241,224,203, 176,41,212,94,92,89,215,223,41,172,69,47,238,195,136,65, 62,5,31,70,15,174,197,212,178,157,244,213,232,195,70,164, 60,159,93,128,30,116,227,226,88,150,211,197,195,88,139,187, 240,166,229,11,8,33,119,63,55,252,10,70,49,234,49,1, 17,6,1,214,0,84,170,254,231,83,175,122,200,87,59,30, 12,169,206,213,116,253,13,225,110,244,225,158,162,51,173,142, 102,92,131,30,92,135,153,101,126,205,147,88,131,94,172,147, 160,198,231,161,7,221,177,209,151,63,133,181,88,131,87,12, 81,176,229,19,200,201,179,255,115,248,97,140,98,172,104,2, 10,62,128,53,0,227,168,254,139,209,139,57,42,222,251,23, 232,9,121,209,234,187,254,70,113,47,250,112,87,241,176,15, 117,36,241,62,116,227,6,204,45,59,86,191,11,125,248,29, 134,60,159,157,141,110,244,224,237,49,189,44,175,96,13,238, 194,147,150,47,192,32,199,247,7,239,193,40,70,242,38,64, 246,1,172,1,136,93,253,115,6,192,160,254,222,241,73,252, 52,244,101,163,234,250,75,97,3,122,177,6,71,13,114,7, 87,161,27,203,203,46,74,142,224,119,232,195,93,82,151,255, 233,232,70,55,174,138,5,106,12,236,195,90,172,193,195,200, 90,190,0,85,126,235,192,111,49,130,81,79,24,32,7,1, 214,0,212,86,253,59,150,136,94,204,86,221,181,5,120,24, 157,161,47,28,109,215,95,6,155,209,135,213,56,100,252,26, 111,71,15,150,99,65,153,95,127,12,235,209,139,53,18,212, 120,14,110,68,55,222,23,11,212,24,56,146,47,25,166,12, 238,112,35,242,9,184,107,135,126,138,81,143,9,40,21,3, 173,1,168,145,250,231,254,201,169,255,5,226,118,154,165,226, 189,29,252,174,236,218,127,212,93,127,46,182,160,15,171,176, 215,248,27,151,163,27,221,101,67,141,51,216,136,62,172,150, 160,198,51,112,61,122,112,77,44,80,99,96,16,235,176,6, 235,48,0,203,23,32,128,7,6,190,147,55,0,35,249,106, 64,161,20,152,205,115,7,90,3,80,51,245,191,80,220,174, 102,215,8,2,255,29,95,174,112,154,168,187,254,8,219,208, 139,59,240,186,241,55,46,70,55,122,42,128,26,63,136,62, 172,194,126,207,103,93,184,14,221,21,244,32,132,245,63,10, 37,195,6,231,11,120,114,240,159,243,234,95,8,2,74,165, 64,107,0,106,169,254,237,23,37,86,210,12,29,188,185,4, 15,85,185,23,70,223,245,183,29,125,184,131,205,176,23,146, 142,55,161,187,108,168,49,225,97,244,226,14,236,241,124,150, 235,65,248,88,44,80,99,32,139,71,176,6,119,121,252,154, 134,227,11,120,121,224,31,48,138,145,98,16,80,74,3,230, 154,129,172,1,136,92,249,193,170,255,197,137,149,52,93,199, 115,39,176,33,162,66,89,244,93,127,59,208,135,94,188,96, 148,159,131,30,116,227,138,178,95,131,199,208,135,62,188,234, 249,164,210,30,132,176,227,73,172,197,26,236,108,68,190,128, 189,3,127,195,26,128,140,53,0,181,84,255,183,36,86,210, 52,57,94,203,253,247,243,248,90,164,55,16,125,215,223,203, 184,29,125,120,218,40,63,19,221,232,193,59,202,206,239,63, 141,62,244,225,69,207,39,185,30,132,235,99,129,26,191,140, 127,204,215,78,26,139,47,64,28,61,245,185,124,8,48,194, 212,1,170,44,4,90,3,16,78,253,47,77,220,230,78,229, 58,183,23,98,91,44,49,112,244,93,127,175,161,23,125,120, 220,248,190,204,195,114,116,227,61,101,67,141,95,64,47,250, 176,195,243,73,174,7,225,198,8,161,198,71,241,47,248,247, 60,170,16,104,44,190,0,49,116,234,15,242,202,63,82,244, 0,82,214,0,212,80,253,219,222,154,248,109,137,70,71,126, 108,125,248,64,140,55,20,125,215,223,155,232,67,47,30,49, 122,142,179,112,35,186,113,117,217,80,227,93,232,85,106,26, 14,254,33,18,223,200,197,207,240,85,79,71,66,195,241,5, 100,6,62,81,220,255,71,60,221,128,214,0,196,164,254,78, 209,0,228,212,255,242,228,111,221,78,30,175,125,61,126,85, 131,27,139,190,235,143,59,111,80,78,58,94,135,30,124,160, 108,168,241,27,232,243,212,52,58,164,51,11,42,27,207,224, 243,120,186,193,249,2,70,110,202,142,72,117,0,111,39,128, 53,0,177,169,127,18,9,36,59,175,20,255,69,29,92,158, 22,104,199,246,208,61,118,95,196,15,112,5,186,177,60,7, 31,172,96,68,223,245,199,157,55,232,29,157,248,56,186,241, 97,180,149,121,167,251,176,10,189,120,2,127,83,165,7,48, 136,175,225,199,140,175,210,104,124,1,195,55,103,135,60,105, 192,49,79,18,48,107,13,64,188,234,255,118,252,38,87,223, 226,114,180,255,140,255,22,122,130,206,188,27,47,240,110,44, 175,130,124,35,250,174,191,227,88,131,94,172,55,38,29,219, 240,81,116,227,99,101,244,57,70,51,182,224,207,241,166,229, 11,128,192,240,39,179,131,74,8,144,178,6,32,78,245,207, 147,125,117,190,83,252,154,218,114,143,67,239,217,90,136,199, 203,168,254,127,17,223,208,200,55,186,113,110,197,113,113,212, 93,127,3,88,171,157,55,40,39,29,115,84,162,211,106,242, 64,70,240,191,241,111,210,158,216,200,124,1,195,159,202,14, 40,33,64,202,83,6,180,6,32,38,245,127,151,248,149,219, 102,198,107,255,26,31,47,107,26,46,238,190,12,221,232,193, 249,21,222,120,244,93,127,220,121,131,222,209,132,107,208,141, 235,49,43,214,7,242,4,254,12,187,60,138,209,232,124,1, 195,159,206,158,210,66,128,116,52,112,32,107,0,12,234,223, 113,21,126,41,90,205,170,119,21,238,169,104,58,46,238,190, 0,43,208,141,101,21,127,133,168,187,254,114,231,13,174,53, 38,29,19,248,61,116,227,70,156,22,195,227,32,252,16,95, 70,218,242,1,120,228,195,159,201,158,180,6,160,182,234,255, 94,113,43,166,248,225,181,183,224,45,85,76,123,2,119,162, 23,27,36,242,141,69,184,9,221,184,172,226,107,70,221,245, 151,59,111,240,78,141,190,171,148,116,124,23,122,176,28,103, 68,248,56,142,226,47,112,175,229,3,80,228,195,191,159,61, 137,17,107,0,106,167,254,239,19,255,137,22,63,188,118,15, 110,137,96,250,65,172,209,226,238,5,232,65,15,174,172,248, 193,68,221,245,151,59,111,112,21,14,26,151,240,74,244,160, 27,11,35,88,143,109,248,67,236,179,124,0,154,124,244,179, 233,19,158,86,32,107,0,34,85,127,145,231,251,41,170,127, 251,251,157,95,120,11,224,122,174,54,129,237,21,167,239,194, 197,221,243,209,141,30,188,171,98,242,141,168,187,254,92,108, 69,31,250,124,146,142,87,227,23,85,210,138,255,2,127,135, 84,3,226,253,131,229,99,178,1,72,121,0,193,214,0,68, 172,254,77,237,215,56,183,80,179,63,94,251,143,240,253,200, 111,39,23,119,223,37,145,111,204,197,114,116,227,189,21,147, 111,68,221,245,71,120,12,189,232,195,110,86,122,13,214,87, 252,237,211,248,127,60,62,85,131,225,253,3,229,146,7,80, 96,4,136,136,18,68,88,245,247,170,127,215,7,220,91,68, 147,201,66,231,126,154,130,29,21,55,243,132,139,187,215,72, 228,27,51,113,3,122,112,117,197,128,227,232,187,254,158,68, 31,250,240,178,242,105,139,148,209,40,47,49,250,41,108,67, 195,226,253,3,229,121,15,64,102,4,176,6,32,98,245,79, 34,217,245,33,250,57,154,130,240,218,159,195,255,23,243,237, 229,226,238,213,56,224,249,108,42,174,67,15,62,136,41,21, 43,89,212,93,127,234,121,131,239,55,240,28,6,141,157,232, 145,124,138,134,195,251,7,202,71,173,1,168,133,250,183,127, 212,249,25,146,65,120,237,36,158,11,117,146,94,101,204,255, 106,220,221,139,85,120,211,243,89,7,174,69,55,62,82,49, 249,70,244,93,127,175,160,23,119,224,57,92,133,127,175,40, 7,240,8,62,137,163,147,27,207,95,181,60,95,5,176,6, 32,78,245,239,188,22,63,41,4,219,126,120,237,63,198,191, 134,154,166,26,230,127,121,60,138,94,220,129,215,60,159,180, 226,35,232,198,181,37,128,98,153,163,126,186,254,86,225,115, 24,195,228,198,243,87,47,183,6,32,126,245,255,56,126,66, 137,96,188,118,2,207,132,220,231,170,103,254,215,227,238,59, 240,146,231,147,230,188,154,86,74,190,49,254,93,127,255,129, 47,120,222,222,201,138,231,175,94,62,252,153,236,41,107,0, 226,84,255,235,233,223,68,2,62,214,184,240,217,39,240,179, 144,83,69,197,252,239,31,119,3,73,188,31,221,184,190,98, 242,141,241,235,250,251,63,248,34,26,2,207,95,181,220,26, 128,88,213,191,227,70,241,35,114,194,225,181,31,9,221,176, 27,45,243,191,154,54,187,29,125,120,82,82,211,247,160,27, 55,134,202,78,112,163,246,93,127,95,195,55,208,40,120,254, 170,249,0,172,1,136,81,253,151,139,31,170,253,54,166,46, 237,247,225,206,178,166,140,154,249,95,30,175,163,23,189,120, 204,243,252,5,222,137,158,42,160,198,181,235,250,251,95,248, 174,143,180,209,240,254,65,242,225,79,43,104,64,107,0,34, 83,255,30,252,64,56,64,56,188,246,42,188,191,130,169,163, 102,254,151,199,62,244,161,23,91,53,168,241,114,156,87,225, 82,197,223,245,247,85,124,171,161,240,252,213,202,173,1,136, 75,253,111,18,223,71,94,253,131,241,218,75,241,88,21,183, 16,61,243,191,119,28,194,29,232,195,3,200,120,62,187,4, 221,232,193,146,10,239,55,190,174,191,175,227,235,236,250,54, 46,222,63,4,31,192,160,53,0,145,171,127,215,10,250,62, 137,240,120,237,239,226,79,171,190,149,232,153,255,189,227,40, 86,163,15,27,165,147,245,46,64,15,186,113,113,197,119,28, 117,215,223,247,240,101,52,26,158,191,106,62,128,146,1,176, 173,192,145,169,255,205,238,191,10,225,23,133,201,150,184,19, 47,151,193,196,239,63,162,103,254,247,142,147,88,131,94,172, 147,84,244,60,244,160,187,138,227,75,162,234,250,251,37,254, 202,176,190,65,235,223,200,242,225,79,100,135,53,44,128,5, 3,85,165,254,159,160,239,65,148,131,215,142,190,1,56,122, 230,127,239,24,196,93,232,195,239,48,228,249,236,108,116,163, 7,111,175,248,161,87,219,245,119,55,62,5,2,44,222,191, 92,62,128,79,102,135,172,1,136,82,253,63,69,223,201,169, 191,158,123,53,117,103,61,142,197,177,220,98,244,204,255,222, 49,130,223,161,15,119,121,88,245,129,211,209,141,110,92,85, 49,212,184,210,177,21,55,96,172,33,241,252,213,202,135,111, 206,142,88,3,16,177,250,243,238,150,9,156,113,101,133,46, 111,216,17,61,243,191,119,140,97,61,122,177,70,130,26,207, 193,141,232,198,251,42,134,26,151,59,118,225,253,56,222,160, 120,254,106,229,35,114,8,48,106,9,65,170,84,255,92,234, 175,28,188,246,15,241,217,26,220,114,244,204,255,222,145,193, 70,244,97,181,4,53,158,129,235,209,131,107,170,60,219,56, 120,28,195,213,30,52,131,197,251,151,39,31,94,145,29,181, 140,64,17,169,191,251,29,53,245,23,140,199,238,192,206,200, 18,128,97,20,53,106,230,127,239,200,226,65,244,97,21,246, 123,62,235,194,117,232,174,184,246,16,60,210,184,14,91,97, 241,254,149,202,71,172,1,136,62,246,47,7,143,253,251,248, 81,168,105,115,167,255,172,64,55,102,87,253,21,162,103,254, 151,191,227,195,232,197,29,216,227,249,44,87,123,248,88,197, 80,99,243,248,43,252,210,119,125,131,214,191,209,229,3,43, 96,13,64,245,234,223,254,41,71,74,253,133,199,99,223,141, 171,66,77,92,56,253,39,129,247,97,5,150,87,152,184,147, 95,134,168,153,255,229,241,24,250,208,135,87,61,159,84,87, 123,224,198,45,248,130,197,251,87,37,47,26,0,203,10,92, 197,238,255,73,250,110,225,219,150,135,199,62,29,47,134,92, 38,249,244,159,36,174,198,205,184,161,98,184,174,119,68,205, 252,47,143,167,209,135,62,188,232,249,36,87,123,184,62,130, 123,127,28,31,70,218,226,253,171,145,211,192,205,214,0,84, 171,254,159,160,239,145,168,12,143,253,5,124,37,244,244,7, 209,139,149,82,103,126,19,62,128,21,184,62,18,114,141,168, 153,255,229,241,2,122,209,135,29,158,79,114,181,135,27,43, 134,26,3,135,241,238,34,177,153,197,251,87,40,119,139,199, 131,91,3,80,161,250,75,93,127,229,226,177,31,198,69,101, 222,198,126,220,142,149,120,196,243,100,154,241,33,172,192,117, 21,115,248,120,71,212,204,255,242,216,133,94,5,193,232,224, 31,42,60,229,215,197,117,120,192,226,249,171,149,103,7,62, 105,13,64,21,234,223,113,147,248,65,110,247,175,4,143,189, 8,79,84,120,59,123,177,18,43,37,184,110,11,62,140,155, 113,109,36,231,236,70,205,252,47,143,55,208,231,65,48,118, 24,89,131,252,199,183,240,85,88,60,127,213,242,204,224,167, 138,72,0,107,0,2,212,95,62,229,39,137,100,71,143,248, 65,88,188,63,39,255,59,124,169,170,219,218,131,149,184,77, 218,81,167,224,163,88,129,107,35,201,182,71,205,252,47,143, 125,88,133,94,60,129,191,169,200,3,216,134,15,27,238,203, 226,253,203,146,103,6,172,1,168,88,253,111,196,143,194,227, 253,57,121,117,103,0,22,198,110,172,196,74,137,195,167,13, 31,195,10,124,180,12,26,110,191,204,67,212,204,255,213,143, 227,120,23,222,180,120,254,40,228,233,129,79,91,3,80,145, 250,119,94,143,31,135,199,251,115,242,179,241,108,132,183,249, 42,110,195,74,60,227,249,164,29,31,199,10,124,164,98,182, 127,239,136,158,249,191,154,241,71,232,11,177,190,86,30,66, 110,13,64,5,234,159,64,83,231,181,248,41,37,170,195,99, 255,53,254,37,242,219,125,5,183,97,165,68,236,217,129,235, 112,51,62,20,201,14,29,61,243,127,37,99,21,254,32,212, 250,90,121,8,185,53,0,161,212,63,167,252,197,35,62,59, 63,66,63,23,73,191,40,43,12,30,251,30,188,59,166,219, 126,9,183,225,54,169,246,222,133,235,177,2,31,140,164,47, 127,124,153,255,251,113,133,1,248,83,238,250,91,57,128,244, 192,167,242,61,128,214,0,176,223,128,81,255,174,15,208,47, 114,135,124,85,131,199,238,194,235,49,163,229,158,199,109,88, 41,241,237,76,195,13,88,129,107,42,76,219,201,99,188,152, 255,87,224,222,80,235,107,229,161,228,153,98,25,176,0,7, 78,33,133,140,53,0,186,250,59,72,34,129,100,199,213,226, 63,209,92,61,30,123,57,254,179,38,95,226,25,172,196,237, 216,41,165,237,150,99,5,174,142,196,252,212,154,249,255,118, 252,73,200,245,181,242,80,114,221,0,20,40,193,220,70,55, 0,133,202,191,83,220,255,147,72,118,188,71,252,202,27,78, 87,142,199,254,9,62,85,195,47,243,20,110,195,237,210,17, 96,51,177,28,55,227,247,42,172,229,43,153,164,26,49,255, 31,195,229,202,28,22,207,95,165,60,59,248,9,38,7,144, 227,4,164,70,54,0,37,245,23,72,20,212,191,243,157,248, 13,181,70,131,199,126,53,2,84,95,185,99,59,86,226,118, 9,252,51,27,221,88,129,247,70,194,224,19,63,243,255,95, 225,151,22,207,31,173,220,245,160,1,85,3,224,130,26,213, 0,176,234,223,117,5,221,166,118,216,84,138,199,190,16,143, 140,219,151,123,20,43,113,187,116,46,240,92,244,96,5,222, 29,137,25,136,143,249,127,11,62,106,241,252,81,203,105,240, 38,143,7,48,166,36,1,27,212,0,120,213,191,4,248,189, 36,113,59,117,69,133,199,254,107,134,191,190,150,131,240,8, 86,162,23,251,60,159,205,195,77,88,81,241,145,98,234,245, 163,102,254,207,224,29,120,217,226,249,163,231,3,232,150,60, 128,20,198,144,105,108,3,160,171,127,2,77,29,23,56,119, 208,244,232,240,216,183,227,67,117,240,85,9,91,113,27,250, 138,152,58,0,152,143,155,112,51,222,22,209,195,139,142,249, 255,71,248,71,139,231,143,92,142,159,14,174,99,60,128,82, 21,0,141,102,0,74,160,31,111,221,255,124,172,42,132,236, 81,224,177,147,216,83,67,26,176,96,167,125,11,86,162,79, 162,9,59,11,55,97,5,174,140,104,134,234,153,255,15,227, 210,60,251,176,197,243,71,39,111,218,113,242,155,217,17,197, 3,104,104,3,192,170,127,235,57,201,85,52,47,74,60,246, 21,216,84,119,95,221,197,253,88,137,59,36,90,207,5,88, 129,21,120,107,68,51,84,195,252,255,151,248,149,197,243,71, 44,111,122,110,238,217,47,125,14,163,158,70,160,156,7,144, 241,148,1,27,202,0,200,234,159,79,253,181,207,119,86,227, 108,248,88,211,242,241,216,159,175,16,3,31,255,200,98,19, 86,98,149,196,29,124,14,110,198,138,138,25,129,162,24,59, 138,61,147,22,207,31,149,220,217,53,119,129,24,120,249,47, 139,234,95,96,4,44,120,0,17,24,0,103,226,171,127,199, 220,196,74,58,27,249,108,72,49,114,202,255,127,81,204,145, 148,39,127,71,221,46,66,2,31,192,255,197,65,220,139,63, 194,244,252,103,175,225,235,184,20,231,227,159,34,5,47,149, 51,190,20,241,250,91,57,246,206,158,47,146,148,1,21,255, 241,254,34,10,191,214,56,30,0,171,254,45,51,154,123,177, 140,203,163,250,37,214,130,229,187,35,160,244,140,127,164,177, 30,43,177,26,39,61,159,45,193,10,172,192,133,53,189,143, 77,184,33,226,245,111,120,249,225,57,77,137,105,128,115,224, 165,255,150,15,1,74,109,64,169,124,23,64,182,218,54,160, 137,228,1,112,124,63,137,41,157,205,191,204,169,63,121,76, 98,201,198,66,49,150,97,229,231,77,8,245,7,154,240,81, 252,7,250,177,6,159,41,210,141,189,132,127,198,50,92,136, 127,198,75,53,186,11,194,151,34,94,255,70,151,139,83,179, 221,196,52,1,128,210,249,61,159,164,95,162,106,203,127,19, 205,0,176,116,95,173,173,77,183,224,10,175,47,36,164,69, 22,69,23,167,92,249,91,49,145,70,51,62,142,95,162,31, 171,240,201,98,229,226,5,124,25,75,113,49,190,38,97,12, 226,25,125,69,142,131,168,214,191,193,229,163,51,142,39,231, 230,129,66,25,201,86,144,100,53,26,198,0,200,234,159,239, 251,107,157,210,244,99,122,111,33,110,42,89,85,33,217,213, 202,228,151,97,226,141,22,220,128,223,224,48,250,176,162,216, 12,249,44,254,9,231,227,82,124,93,226,254,143,118,184,248, 70,228,235,223,208,114,119,218,158,150,179,139,58,159,246,40, 125,228,234,63,241,60,128,34,230,175,61,153,248,54,125,76, 120,172,40,164,159,11,157,212,149,201,39,162,1,200,141,41, 88,142,219,208,143,149,232,41,30,245,245,52,254,95,156,135, 203,241,45,159,3,70,42,31,189,197,243,10,162,91,255,70, 150,119,188,208,118,126,33,75,32,128,140,199,237,87,99,133, 6,49,0,133,181,144,42,255,137,47,137,79,144,182,50,228, 73,178,8,84,42,119,34,225,1,28,207,209,134,155,112,59, 14,227,191,112,99,145,110,236,9,252,61,22,226,109,248,142, 116,32,88,181,35,139,111,70,190,254,141,44,111,125,186,107, 153,244,89,198,152,48,104,16,3,32,239,253,5,166,255,207, 211,95,144,18,71,161,184,168,66,90,230,242,229,75,34,225, 232,27,255,209,142,79,224,14,244,227,87,184,174,136,143,126, 12,127,135,5,120,7,254,213,7,10,84,222,254,191,51,242, 245,111,92,121,203,115,211,47,33,207,158,135,92,8,0,237, 127,136,42,24,112,38,140,250,123,146,127,157,159,166,47,122, 129,148,144,56,214,101,199,161,18,249,50,76,166,209,137,79, 227,78,244,227,86,124,44,79,55,70,216,134,191,197,89,120, 55,126,32,157,18,92,201,248,94,12,235,223,168,242,228,115, 51,151,145,39,60,200,39,1,229,93,159,164,24,98,146,27, 0,54,247,223,249,17,250,54,121,82,40,37,119,170,100,91, 171,147,95,136,201,55,186,240,251,184,11,135,240,11,124,36, 79,55,70,216,138,47,224,76,188,23,63,50,30,69,30,52, 238,195,11,49,172,127,99,202,157,151,103,93,32,60,249,128, 124,74,48,27,143,235,63,17,12,128,222,245,159,68,178,243, 29,248,137,112,74,105,1,104,253,85,133,207,43,151,47,195, 100,29,211,240,135,184,7,7,241,115,124,48,79,55,230,226, 65,252,53,78,199,23,43,220,255,227,88,255,70,148,59,187, 231,44,116,28,42,26,138,162,105,200,104,25,128,6,73,2, 234,125,127,9,36,58,46,20,183,82,139,156,12,21,82,204, 36,180,100,105,249,242,201,107,0,114,99,6,254,4,247,225, 0,126,134,247,231,233,198,92,252,160,130,235,60,134,173,177, 172,127,227,201,157,3,167,205,22,205,114,155,80,110,184,25, 105,201,35,247,1,156,9,164,254,201,182,51,197,111,220,46, 33,217,72,189,62,82,173,188,19,243,208,8,99,22,254,12, 27,176,31,63,198,251,208,129,191,169,224,10,63,138,101,253, 27,79,142,99,179,155,209,1,6,36,140,66,25,16,113,153, 129,100,221,190,159,66,106,253,73,32,209,50,35,241,27,156, 38,224,45,163,8,229,39,111,170,165,82,249,34,52,210,152, 131,63,199,159,87,244,151,251,113,167,103,87,139,110,253,27, 77,46,134,102,141,36,230,11,232,238,191,100,0,116,40,208, 36,246,0,228,202,127,174,239,175,173,229,22,177,184,240,49, 49,127,80,178,181,213,201,27,203,0,84,62,126,238,57,139, 48,202,245,111,48,121,122,250,161,228,124,21,37,80,210,115, 145,137,247,41,58,117,170,254,10,232,167,173,169,249,251,226, 157,5,229,151,173,169,26,107,201,117,212,242,229,214,0,132, 25,99,248,69,76,235,223,80,114,234,218,213,114,142,55,33, 40,164,36,97,62,7,64,141,100,0,88,186,207,230,127,204, 225,77,229,132,138,108,77,163,194,99,159,103,181,59,196,88, 133,35,22,207,95,181,188,253,185,246,165,178,103,95,144,20, 205,65,214,19,249,199,96,8,146,117,170,254,146,251,63,237, 51,248,60,36,27,170,90,83,161,88,93,174,3,59,172,252, 44,171,221,33,198,127,84,188,190,86,94,144,79,121,178,235, 50,41,25,88,60,42,204,147,50,204,54,82,8,192,86,254, 187,222,135,111,122,247,124,72,169,21,46,61,90,29,30,251, 108,171,221,129,227,21,108,133,197,243,87,39,111,218,49,227, 50,111,206,95,238,20,144,66,0,115,16,64,147,203,0,200, 165,63,7,9,36,166,45,77,254,76,36,160,197,70,197,28, 42,132,210,94,89,29,30,187,21,115,172,126,7,142,91,45, 158,191,74,121,211,243,179,47,38,205,84,200,158,109,62,4, 160,56,159,164,83,87,202,239,53,1,185,198,159,185,226,86, 234,132,164,230,222,95,43,152,65,217,52,84,131,199,62,211, 106,119,224,72,227,215,21,175,175,149,11,0,98,231,236,197, 36,25,139,82,62,139,100,111,192,212,8,68,147,205,0,48, 140,127,173,109,45,255,142,179,132,230,252,171,46,131,35,201, 100,43,90,46,30,123,190,213,239,192,177,30,71,96,241,252, 149,203,197,238,57,243,69,18,146,127,224,133,10,9,239,79, 217,104,21,190,94,13,128,202,249,147,163,252,250,22,174,52, 167,82,188,14,150,234,31,200,139,91,14,30,251,52,171,223, 129,227,183,22,207,95,141,188,127,246,116,167,141,20,35,33, 163,0,61,221,0,217,168,163,254,122,52,0,130,137,254,147, 51,62,39,110,86,99,127,175,157,240,86,12,161,248,0,66, 50,17,229,224,181,173,1,8,26,167,240,59,159,245,179,120, 127,127,57,78,206,166,28,221,167,23,27,232,221,218,20,62, 128,12,212,222,160,73,234,1,40,125,255,211,223,39,190,44, 59,252,66,219,225,101,169,195,248,2,234,223,7,227,181,231, 89,13,15,24,119,98,204,103,253,44,222,223,87,62,58,243, 120,114,174,148,228,99,67,123,15,31,128,94,6,140,148,23, 208,169,11,229,87,147,127,201,206,115,19,63,17,142,23,47, 173,182,0,9,201,114,136,162,51,37,32,91,87,33,153,138, 96,188,246,92,171,225,1,227,118,139,231,175,84,158,157,190, 167,101,1,151,240,147,115,86,94,121,222,0,80,92,97,128, 83,23,234,175,236,255,83,187,166,220,34,166,10,37,247,239, 77,141,176,206,85,126,217,8,142,20,28,168,158,131,63,94, 123,134,213,112,223,113,20,91,44,158,191,66,121,215,139,173, 231,107,120,127,5,35,160,201,221,120,203,128,201,186,81,127, 79,243,79,203,119,105,73,105,25,28,201,186,122,129,20,130, 61,82,153,60,11,232,74,149,89,146,26,51,133,39,100,16, 0,166,227,42,156,141,243,173,142,251,142,187,145,81,14,179, 214,241,238,86,206,201,219,159,106,191,84,86,115,64,110,13, 82,205,0,0,184,89,45,54,152,100,57,0,45,250,159,243, 57,92,167,59,250,165,239,238,104,142,190,252,95,199,243,23, 142,150,63,16,202,35,43,216,223,233,248,20,22,161,185,200, 168,111,7,63,86,91,60,127,69,242,230,103,187,46,101,241, 254,30,229,231,228,52,169,209,128,66,49,1,9,36,102,190, 93,124,9,172,85,85,35,124,53,211,47,52,85,87,255,94, 205,28,120,229,87,229,153,128,91,173,142,251,140,19,184,31, 0,239,198,170,8,56,43,47,201,19,207,206,186,72,253,92, 72,190,168,254,119,121,115,224,26,247,253,9,79,10,202,68, 255,211,231,37,127,154,103,169,82,162,117,217,94,144,178,243, 171,246,68,205,20,8,229,65,233,120,237,2,4,232,231,216, 138,227,86,211,13,99,3,50,176,120,254,114,229,137,23,230, 92,104,196,251,43,89,0,77,62,169,209,128,74,235,79,91, 115,203,255,193,92,82,50,161,66,203,150,170,221,86,114,89, 133,138,63,149,162,48,185,236,194,199,106,185,209,143,13,216, 128,51,176,12,23,160,211,106,188,50,238,3,88,118,27,175, 135,101,229,178,220,121,109,246,121,112,10,142,190,240,36,12, 189,209,190,73,238,170,85,0,154,44,6,64,232,173,63,83, 63,79,239,33,201,10,10,69,201,245,124,190,23,61,165,52, 81,230,93,28,23,28,123,128,122,173,55,36,34,144,189,216, 139,123,177,16,203,176,4,109,86,239,243,35,139,245,146,145, 149,107,51,186,17,182,114,129,196,190,217,179,69,179,140,10, 44,41,191,208,24,191,53,185,27,239,51,77,142,155,250,151, 204,64,222,253,159,243,14,252,143,220,7,46,211,25,77,18, 174,138,255,153,227,11,240,254,236,120,30,146,80,106,9,91, 112,166,118,30,208,110,236,198,221,56,23,23,225,252,226,201, 58,141,60,30,199,49,139,231,47,79,126,120,214,20,167,211, 23,239,31,192,7,80,68,3,82,60,89,128,228,184,169,191, 2,251,237,156,153,252,33,57,178,18,147,146,94,81,93,36, 189,40,8,233,33,184,140,92,190,126,73,118,2,191,193,123, 112,142,150,20,113,177,19,59,145,192,249,184,8,139,234,152, 67,181,54,1,0,49,207,71,72,222,154,149,123,140,192,208, 204,84,142,238,19,30,135,159,164,26,1,193,95,238,186,241, 36,255,198,223,3,16,74,239,223,55,49,159,43,234,241,188, 63,114,138,80,182,201,222,28,128,94,112,209,31,93,225,113, 157,196,90,76,193,98,44,198,233,26,230,48,139,23,241,34, 154,177,20,203,176,208,155,165,108,168,177,89,121,201,77,120, 119,43,7,4,144,154,126,176,229,92,82,240,254,84,84,116, 239,207,62,242,108,156,25,128,241,49,0,178,251,159,64,2, 137,121,159,192,117,250,46,14,67,138,132,148,128,64,70,254, 169,144,74,104,137,66,98,174,159,187,234,8,158,198,51,104, 199,98,44,97,154,130,83,120,6,207,160,21,23,224,34,156, 165,25,137,201,62,142,227,73,45,105,42,39,87,73,107,205, 106,96,57,77,221,53,229,2,217,79,21,74,132,175,250,177, 156,220,227,1,76,162,42,128,215,253,119,144,152,185,192,249, 170,73,49,189,177,187,126,194,138,10,166,16,70,107,67,12, 96,88,173,221,22,36,131,120,2,79,96,26,150,96,9,211, 26,60,130,39,240,4,58,176,12,203,26,138,61,96,139,178, 122,196,182,99,89,121,110,180,63,219,118,177,174,210,66,219, 134,130,228,110,204,88,128,228,184,40,191,228,254,183,53,77, 249,30,218,133,18,245,147,146,16,17,90,86,64,110,237,21, 18,10,91,40,9,21,161,192,53,56,31,67,157,255,36,182, 97,27,102,97,9,206,199,52,237,107,12,98,27,182,97,26, 46,194,133,13,2,32,218,172,69,186,114,48,165,238,143,141, 44,111,123,178,235,50,72,21,44,19,222,63,80,110,170,2, 208,196,52,0,186,251,159,156,254,39,226,157,122,162,78,87, 106,213,198,82,0,224,215,27,171,145,86,45,128,148,7,144, 73,28,28,143,252,40,30,194,67,152,135,197,56,31,29,218, 215,57,129,45,216,130,89,184,8,23,98,102,3,120,0,222, 10,138,9,15,111,229,205,207,76,191,76,223,223,133,146,222, 11,39,119,93,165,10,16,49,38,64,212,220,0,72,164,95, 104,154,179,168,101,35,77,129,98,255,228,188,135,208,218,38, 188,81,24,41,213,125,206,91,34,169,40,200,215,95,133,33, 219,82,250,233,12,44,193,34,99,179,240,233,88,134,11,48, 117,146,170,255,81,44,4,24,30,102,48,185,240,198,150,39, 159,155,189,12,154,135,202,245,160,132,145,31,252,179,147,253, 24,197,8,70,48,138,81,140,97,12,105,164,145,65,22,46, 34,64,10,38,107,172,254,94,35,144,115,255,191,77,83,212, 243,82,8,250,25,42,106,205,223,145,208,214,170,161,240,156, 175,174,76,47,36,163,65,26,185,184,208,154,50,75,115,238, 197,94,108,196,2,44,198,185,76,95,192,126,236,199,58,156, 133,139,176,116,18,66,138,30,81,214,66,101,93,36,37,39, 222,168,114,231,149,217,75,192,238,238,4,189,227,63,88,46, 92,196,122,50,80,237,67,0,9,250,51,227,211,244,78,221, 254,233,46,187,220,223,231,72,129,130,204,199,34,27,13,157, 66,148,32,164,164,34,105,102,135,197,100,121,174,191,27,187, 225,224,92,44,193,2,52,105,95,112,15,246,224,30,156,131, 101,88,162,53,22,77,228,177,205,99,46,85,122,21,53,10, 110,92,185,243,218,236,51,144,132,150,204,83,187,86,194,203, 179,174,244,154,83,244,10,57,30,202,159,63,242,99,250,188, 174,45,52,149,119,254,85,122,101,193,134,63,234,225,75,66, 169,149,112,142,189,183,193,216,213,102,33,99,32,33,180,131, 30,154,113,30,150,224,44,67,95,64,2,139,112,33,22,51, 70,98,34,142,171,177,93,89,83,225,227,18,55,168,252,208, 156,150,196,52,85,141,101,127,82,87,115,127,249,190,63,24, 58,145,15,0,70,48,138,49,164,144,66,102,34,134,0,204, 137,191,157,95,44,132,204,58,44,194,81,114,255,124,175,181, 147,79,146,122,139,40,142,146,97,149,29,123,239,149,189,100, 35,234,254,239,176,103,189,200,247,151,198,139,120,1,173,88, 132,37,56,131,105,30,122,9,47,161,9,139,113,17,206,157, 224,205,67,41,236,80,94,121,81,172,173,240,176,170,198,147, 227,196,28,74,76,243,110,35,60,207,79,121,242,236,36,194, 2,8,249,208,207,51,223,158,99,253,37,77,173,193,20,244, 248,218,0,105,142,188,252,59,58,50,16,30,67,224,230,31, 161,19,48,63,148,144,67,150,143,226,89,236,64,7,206,199, 18,134,82,52,141,231,240,28,90,112,1,150,97,65,157,158, 198,30,60,158,67,202,120,190,61,152,19,155,27,80,62,50, 227,68,98,129,158,195,130,212,190,86,129,156,226,226,2,170, 173,1,208,168,63,90,91,18,95,55,225,248,244,163,148,212, 148,28,24,57,135,247,23,90,6,64,237,4,80,97,24,114, 200,160,187,107,252,81,79,2,67,120,18,79,161,19,75,177, 24,179,181,175,63,134,167,240,20,218,176,12,203,24,95,161, 254,199,147,138,49,37,246,57,52,176,60,59,117,79,203,98, 239,110,174,190,33,234,110,31,86,238,198,124,56,104,45,67, 0,9,251,63,251,143,197,18,57,186,22,6,82,101,181,79, 175,22,124,1,220,157,232,8,68,253,254,6,240,24,30,197, 12,44,197,249,76,15,225,48,30,195,99,232,194,50,92,52, 193,206,31,120,66,89,95,139,247,151,229,29,47,182,47,171, 12,239,31,36,207,146,150,130,152,128,73,192,124,133,164,152, 254,107,154,51,175,253,97,106,151,17,126,196,54,72,66,138, 139,212,180,29,0,54,109,199,255,236,141,174,74,59,186,203, 124,170,194,52,137,253,73,191,63,239,156,115,177,4,231,163, 203,176,36,51,176,12,203,24,95,161,62,199,219,240,162,1, 239,14,166,131,179,209,228,237,79,79,189,4,76,189,137,227, 14,42,87,190,235,230,108,41,5,88,234,3,200,78,180,36, 160,144,11,128,109,95,16,197,82,185,83,220,111,29,101,223, 86,99,254,130,245,117,181,172,41,207,23,0,38,138,87,65, 155,80,248,2,100,27,15,54,195,0,237,254,28,169,21,36, 119,127,135,208,143,7,48,31,75,112,62,67,42,114,12,15, 226,65,204,197,69,184,144,105,52,174,183,20,224,78,88,188, 191,73,222,250,212,212,75,43,199,251,251,203,145,201,82,124, 37,192,90,25,0,141,251,239,244,115,157,63,144,247,84,40, 40,127,121,49,244,102,224,194,190,45,152,12,0,49,251,178, 138,27,224,249,2,244,136,15,198,164,34,88,102,194,18,12, 185,240,155,251,176,15,155,112,22,150,224,60,166,47,224,16, 14,77,0,2,178,87,144,177,120,127,131,60,177,99,198,165, 213,224,253,3,228,105,197,253,159,160,112,224,82,8,144,235, 255,251,123,55,33,43,146,26,227,203,103,172,131,205,193,235, 109,59,122,87,95,121,124,1,252,163,23,140,121,0,131,69, 228,179,6,185,159,223,192,27,88,143,115,176,24,231,50,125, 1,37,2,178,165,117,201,74,252,156,197,251,27,228,206,139, 115,150,85,137,247,247,151,167,129,137,94,5,208,206,253,61, 227,50,250,56,119,140,114,193,26,58,202,82,8,214,69,242, 62,24,82,232,191,120,88,113,37,124,1,114,76,230,199,71, 32,124,248,6,114,191,237,98,23,118,33,137,243,176,24,11, 152,133,47,17,144,45,70,115,157,25,0,139,247,231,228,226, 213,57,231,192,169,14,239,239,47,71,58,238,103,91,187,16, 160,136,254,159,242,79,28,54,95,69,252,171,173,57,60,208, 87,231,11,224,213,152,140,25,79,127,190,0,24,206,36,228, 234,16,66,99,49,228,130,147,76,177,61,104,9,206,52,16, 144,37,113,62,150,213,17,1,217,75,218,90,0,150,15,0, 251,230,204,113,90,170,197,251,7,200,51,241,30,12,22,191, 1,208,142,254,90,248,110,188,131,87,52,29,239,239,39,39, 248,49,8,240,124,1,38,51,18,134,47,0,236,108,208,90, 135,248,235,171,208,230,92,123,80,43,22,99,9,67,64,150, 193,11,120,33,79,64,118,78,29,52,15,189,194,239,127,141, 205,7,112,100,78,139,211,25,1,222,223,87,238,166,25,247, 159,162,76,10,214,42,4,40,238,255,201,191,225,249,125,133, 146,241,39,45,191,14,240,61,129,165,182,93,72,191,77,236, 241,161,213,243,5,8,86,14,173,153,184,116,109,199,99,134, 92,207,21,71,240,52,158,70,103,157,19,144,165,176,71,49, 195,150,15,64,12,206,28,77,156,17,5,222,63,64,158,81, 148,126,130,121,0,218,254,127,246,165,120,55,223,83,199,245, 233,169,93,121,144,148,73,245,34,28,133,27,192,203,23,160, 214,87,1,115,79,159,218,243,197,155,15,72,165,66,174,178, 171,246,43,56,249,147,139,213,111,52,128,237,120,28,211,177, 4,75,24,82,145,241,39,32,123,21,110,81,45,76,173,90, 13,38,79,77,59,212,116,174,208,186,250,161,236,236,213,203, 157,9,159,3,80,246,255,150,207,107,120,103,166,132,199,215, 6,160,237,215,60,95,128,76,31,226,207,23,0,205,56,8, 197,17,211,235,4,102,190,0,190,33,89,24,27,150,189,247, 116,2,219,176,13,179,177,4,139,25,82,145,241,36,32,219, 5,139,247,151,228,238,212,93,83,46,136,10,239,239,47,119, 179,241,56,254,181,13,1,138,21,128,51,22,227,195,36,37, 248,160,148,254,56,21,81,119,110,176,36,30,102,190,0,161, 21,248,184,29,218,107,130,212,164,162,154,59,0,252,248,2, 160,132,14,186,127,224,104,1,78,225,47,15,163,31,91,48, 15,75,124,8,200,102,99,25,150,49,141,198,113,141,221,202, 247,107,116,62,128,206,103,219,222,18,29,222,63,64,158,134, 185,173,181,238,13,128,80,250,255,156,182,191,212,155,108,212, 206,42,98,187,243,117,152,175,106,72,84,207,65,247,43,4, 184,131,65,5,120,118,65,189,241,88,24,214,157,239,84,40, 129,69,189,135,72,249,223,95,225,219,28,192,129,124,243,16, 71,64,118,24,155,177,25,167,99,25,46,52,54,26,71,57, 246,0,190,103,42,138,134,146,183,111,239,186,156,52,61,244, 38,242,84,234,186,170,228,153,184,159,110,178,6,251,127,62, 0,152,125,154,115,35,49,120,106,117,127,119,180,208,32,58, 190,0,72,134,68,48,153,1,110,175,230,114,1,142,214,187, 104,186,63,57,195,64,82,174,66,254,126,178,23,177,7,111, 98,35,206,198,18,156,199,244,5,212,142,128,108,143,197,251, 23,37,77,59,166,94,30,45,222,63,64,158,137,47,253,23, 183,1,208,18,128,211,111,166,164,74,215,69,74,244,165,22, 253,162,230,11,208,233,194,252,248,2,76,142,122,121,124,1, 252,252,250,253,59,12,157,153,139,221,216,141,4,206,193,82, 44,100,30,86,45,8,200,222,176,120,255,252,79,201,231,102, 93,28,57,222,223,95,158,142,214,225,175,117,8,80,242,1, 18,173,77,206,103,120,69,81,73,189,192,68,240,149,241,5, 4,165,231,204,113,190,126,135,168,146,47,128,79,15,6,221, 95,110,100,139,237,65,139,113,182,198,45,68,120,21,175,226, 46,44,194,50,156,31,3,1,217,30,88,188,191,0,32,94, 158,189,36,122,188,191,191,156,50,113,198,255,181,40,3,22, 67,128,249,191,39,206,208,1,53,92,98,141,180,60,57,42, 228,11,144,11,123,0,207,23,0,22,234,41,164,59,116,165, 136,62,136,47,64,206,71,232,168,67,29,173,72,90,244,169, 63,233,92,123,208,20,44,194,210,26,18,144,157,194,16,44, 222,159,224,188,62,247,76,36,163,199,251,251,203,61,57,128, 9,134,5,144,146,127,112,224,52,253,62,177,249,123,176,231, 251,232,110,189,238,70,123,83,107,48,240,5,8,152,188,14, 94,46,20,168,112,33,139,32,124,106,253,38,95,128,187,191, 32,15,198,127,125,8,2,35,120,22,207,162,13,75,124,8, 200,166,96,105,100,4,100,7,217,190,120,146,82,155,13,32, 63,56,103,154,104,243,86,227,132,210,117,66,74,181,46,34, 121,38,222,12,64,109,170,0,14,156,51,206,194,53,130,217, 227,202,193,227,235,251,58,39,15,230,11,16,204,252,250,30, 29,204,23,64,76,62,129,51,51,38,190,0,61,203,193,213, 62,244,124,1,64,24,198,147,120,18,93,6,2,178,81,60, 133,167,208,142,11,35,32,32,59,212,240,120,127,1,113,98, 14,57,211,128,232,241,254,65,242,108,86,137,246,38,96,18, 208,129,3,167,227,58,8,29,111,239,106,148,222,96,18,126, 58,37,56,7,185,241,254,174,96,144,1,28,95,0,2,248, 2,200,168,210,50,50,160,26,190,0,46,3,160,95,159,243, 33,4,78,226,81,108,195,76,44,197,98,76,215,30,192,80, 36,4,100,7,149,80,171,241,248,0,156,225,233,199,147,11, 41,30,188,127,128,92,168,85,128,200,107,2,201,216,246,126, 137,5,56,113,35,119,8,167,140,215,55,239,233,196,36,231, 76,81,53,192,161,183,252,146,59,128,137,47,0,62,37,70, 225,177,113,186,121,48,243,5,168,161,140,126,127,65,235,163, 206,127,12,91,241,16,230,98,41,75,64,118,10,15,227,97, 204,196,50,44,195,172,138,60,0,61,101,213,80,124,0,153, 105,111,182,44,142,13,239,31,32,167,108,156,9,192,184,61, 128,130,250,39,22,44,194,82,185,188,194,197,194,92,14,64, 142,165,85,246,64,111,161,15,129,120,124,50,148,239,212,220, 189,63,49,40,49,124,69,64,117,124,1,96,238,207,204,110, 44,148,76,67,238,154,253,232,199,253,56,195,64,64,118,20, 15,224,129,138,8,200,142,1,13,139,247,7,8,93,47,78, 185,40,62,188,127,32,31,192,132,109,4,146,104,192,218,174, 21,76,190,157,203,134,131,173,154,123,205,128,170,80,122,87, 189,153,47,128,140,181,123,93,229,116,31,65,55,13,100,100, 10,16,172,243,111,226,11,0,204,96,99,253,254,248,174,130, 220,127,75,4,100,139,152,211,11,75,4,100,23,50,141,198, 252,56,142,70,197,251,19,4,218,159,238,184,36,86,188,127, 48,31,64,172,25,128,120,12,128,144,227,127,56,226,70,174, 225,213,132,215,231,178,245,102,190,0,97,144,243,124,1,208, 42,14,97,248,2,244,251,227,130,9,151,85,97,84,196,23, 80,254,250,120,77,200,235,120,3,27,176,48,18,2,178,163, 64,99,226,253,33,208,242,228,212,203,226,197,251,7,202,179, 152,160,148,96,30,20,192,194,11,156,115,213,186,62,192,119, 224,123,187,254,205,124,1,170,195,207,49,248,122,85,220,97, 202,140,229,240,5,240,117,139,168,249,2,132,167,66,224,191, 62,65,124,10,2,185,230,161,28,1,217,18,44,96,250,2, 194,18,144,157,64,35,226,253,1,32,241,244,204,203,98,199, 251,35,36,31,0,63,168,94,13,128,28,0,188,223,175,134, 78,140,83,31,196,23,224,165,244,244,227,11,144,247,72,19, 95,0,16,230,254,120,250,175,106,249,2,252,238,95,149,59, 161,215,167,244,247,25,188,132,23,49,5,231,97,105,133,4, 100,39,27,17,239,15,32,241,252,220,139,227,199,251,7,202, 179,90,147,64,196,225,64,50,22,229,151,122,0,157,171,133, 86,252,144,129,15,130,113,202,43,225,11,224,26,106,85,80, 145,218,133,37,12,39,13,233,46,63,199,23,128,64,190,128, 48,247,199,55,12,87,190,62,106,250,116,12,207,227,57,180, 85,68,64,150,110,60,188,63,8,206,171,115,206,35,39,126, 188,127,144,60,155,141,55,0,64,12,135,214,122,207,255,77, 32,121,218,244,246,175,8,33,55,225,58,69,21,113,180,228, 153,55,53,163,214,207,213,223,21,134,136,88,20,101,66,73, 238,20,96,55,65,13,32,66,185,126,216,249,189,127,167,58, 151,66,251,45,174,246,31,221,250,192,179,171,229,232,72,15, 224,121,60,139,33,180,50,41,192,44,14,225,89,60,142,227, 104,193,84,207,149,79,96,42,250,49,162,52,73,11,230,250, 147,71,158,216,59,119,166,104,83,145,34,38,118,136,56,229, 238,227,199,95,69,198,243,79,225,68,32,23,20,205,41,1, 241,230,0,28,136,233,239,116,28,82,212,76,119,138,101,21, 168,158,47,0,17,241,5,16,51,191,244,128,24,24,18,87, 71,224,201,78,116,86,3,19,48,89,24,252,147,224,245,81, 141,220,32,30,199,118,76,199,98,31,2,178,78,92,88,36, 32,203,96,17,206,196,111,138,213,128,6,224,3,56,50,107, 138,232,4,83,127,137,1,239,31,32,215,192,64,52,17,60, 0,39,87,253,207,121,0,243,254,84,92,44,43,129,227,217, 189,28,99,235,142,195,112,179,20,98,97,161,236,168,96,142, 3,209,119,121,82,246,222,210,44,250,254,43,216,4,33,183, 215,251,205,47,36,111,130,164,226,147,48,222,159,227,185,162, 163,197,85,193,243,115,235,163,26,179,81,236,197,83,216,133, 49,116,48,48,226,20,246,226,73,236,192,16,218,241,24,8, 73,116,224,229,6,225,3,192,192,236,161,166,211,184,66,48, 124,136,227,227,146,103,31,57,241,6,210,200,32,131,180,180, 255,215,173,7,32,212,28,64,226,106,50,118,203,235,251,63, 199,23,96,94,52,142,47,128,107,248,209,201,61,56,190,0, 61,218,6,162,225,11,16,161,249,2,132,34,87,27,141,195, 241,41,248,245,20,120,61,134,126,28,246,33,32,59,142,45, 216,146,255,249,108,246,239,39,33,31,192,216,140,67,205,231, 213,16,239,31,32,167,172,230,84,70,164,248,113,247,1,228, 3,128,115,22,224,116,192,31,15,47,124,206,228,81,187,226, 73,115,210,203,225,11,16,76,47,34,52,199,90,48,109,69, 124,158,29,8,230,11,208,187,189,128,234,249,2,212,217,73, 201,5,240,124,10,124,177,244,0,14,96,51,206,52,16,144, 121,189,207,73,207,7,224,78,221,213,114,97,45,241,254,129, 242,44,98,30,241,97,1,4,4,156,214,183,4,227,225,229, 54,90,104,177,189,96,189,2,50,240,5,16,83,228,9,131, 199,215,177,138,2,225,249,2,136,117,42,57,149,172,158,47, 0,33,248,20,130,214,71,199,187,191,233,75,64,182,71,73, 85,78,78,62,128,142,29,109,151,212,22,239,31,40,143,189, 10,144,140,77,249,5,4,68,243,165,96,89,120,136,41,134, 113,231,165,235,251,61,135,215,142,134,47,192,212,119,31,134, 47,192,191,214,15,246,51,127,190,128,114,214,71,231,83,8, 90,31,146,230,47,172,87,22,187,241,26,154,176,16,75,112, 142,231,213,24,197,131,152,252,124,0,83,182,119,94,94,115, 188,127,144,124,194,193,129,133,148,10,116,112,185,25,143,175, 246,181,85,198,23,96,102,21,4,163,180,113,242,5,200,175, 151,31,95,128,206,103,224,176,243,115,124,1,81,172,143,222, 48,228,253,14,25,188,130,157,104,198,121,88,140,249,16,120, 3,91,60,253,128,147,149,15,160,233,233,233,151,215,30,239, 31,36,119,221,137,21,2,8,217,3,152,213,230,44,115,193, 225,225,121,60,190,186,175,185,30,185,107,228,11,128,198,23, 192,67,130,228,91,12,198,227,3,225,249,2,132,150,151,32, 109,126,142,142,84,53,86,196,242,1,112,128,227,40,249,20, 184,130,231,24,94,192,243,13,129,247,23,0,18,59,102,93, 50,30,120,255,64,121,198,243,232,40,14,111,32,214,36,224, 236,11,40,193,57,209,92,62,95,48,251,113,244,124,1,164, 213,131,77,120,124,93,49,245,61,85,221,211,77,124,1,252, 201,131,102,190,0,104,69,81,98,65,79,209,175,79,3,226, 253,1,136,151,230,92,48,62,120,255,64,62,0,87,81,246, 200,131,128,120,142,158,205,155,128,150,183,232,213,65,50,244, 209,9,229,168,78,117,143,212,123,250,132,210,124,0,173,96, 167,30,207,165,30,55,174,171,143,183,60,39,251,13,124,207, 159,249,250,194,80,207,240,38,162,132,114,255,254,235,3,168, 124,1,254,235,35,171,122,184,245,129,214,76,76,158,245,161, 73,41,23,175,205,61,43,183,17,122,115,35,208,0,105,227, 33,119,39,92,21,64,120,217,128,18,139,213,54,20,40,206, 167,31,63,111,16,95,128,222,95,232,199,23,0,35,95,0, 202,220,163,9,48,242,21,112,25,126,157,41,128,235,13,8, 94,159,32,190,128,234,248,20,248,59,154,236,120,127,1,236, 159,51,61,215,246,59,46,120,255,32,185,27,119,21,192,137, 107,247,135,128,131,197,38,87,159,235,149,135,161,67,14,74, 182,28,204,174,204,53,212,240,68,157,130,113,146,121,149,54, 247,2,154,91,147,100,101,21,134,25,201,72,78,198,175,15, 5,174,15,42,94,31,48,249,7,175,137,146,177,235,164,4, 76,19,93,46,78,204,18,137,233,114,142,68,199,235,143,159, 156,241,0,34,14,7,146,49,236,254,249,159,90,133,88,76, 70,192,138,105,55,54,225,241,161,117,253,19,203,205,99,230, 11,224,207,22,168,5,95,128,218,137,46,148,61,93,4,172, 143,131,104,249,20,188,158,150,195,28,145,38,88,163,3,76, 54,62,0,103,104,198,241,166,133,227,138,247,15,146,199,94, 6,140,207,3,112,230,158,46,218,245,250,186,96,236,69,24, 185,142,129,227,94,127,53,174,53,97,4,244,29,50,215,67, 79,21,223,159,222,175,175,223,159,8,248,123,170,106,125,28, 205,87,10,243,247,164,173,143,96,182,28,181,150,161,38,64, 39,164,60,51,109,111,203,66,126,91,53,157,241,92,107,57, 98,103,4,138,49,9,216,121,142,215,30,168,16,219,82,231, 147,80,98,53,46,110,211,19,111,66,122,141,29,165,10,201, 27,2,161,213,131,213,207,212,123,33,6,224,43,180,224,196, 171,124,188,156,55,100,164,205,169,222,95,208,250,16,187,62, 80,186,43,252,214,199,60,191,252,153,236,79,120,43,83,19, 84,78,93,47,76,89,172,215,66,248,132,220,120,201,93,87, 177,10,145,155,2,39,150,221,31,16,16,205,231,153,240,248, 66,82,21,53,75,94,194,179,233,177,124,206,106,58,74,145, 48,28,94,95,206,153,171,138,37,159,41,236,63,191,48,242, 5,232,237,16,220,254,171,255,61,143,244,11,94,31,39,96, 125,202,227,51,8,94,31,181,57,91,207,173,79,20,121,235, 83,237,23,11,37,226,230,0,57,227,43,55,54,2,81,61, 123,0,249,119,199,89,168,38,172,120,167,221,49,152,4,181, 53,71,223,11,85,151,91,176,103,240,10,102,127,135,214,96, 163,123,14,92,194,77,72,217,125,191,249,73,137,56,193,124, 63,189,112,194,237,242,186,119,17,180,62,84,209,250,56,33, 215,135,52,87,21,76,145,178,190,229,45,79,76,187,76,174, 239,240,71,189,143,183,220,117,217,221,159,234,213,3,144,223, 183,249,96,219,97,4,203,233,43,223,146,144,246,58,179,217, 112,124,98,109,190,138,160,242,5,8,166,45,84,128,195,227, 243,254,9,12,247,199,243,29,200,243,11,198,55,50,175,15, 133,94,31,33,173,15,66,173,15,12,235,195,241,41,128,73, 99,201,25,246,250,150,55,61,61,227,173,128,78,198,193,37, 116,199,87,46,98,111,5,118,34,85,126,217,3,152,47,91, 93,199,64,210,5,169,243,79,48,138,168,159,192,163,55,180, 8,45,154,229,103,18,198,18,159,96,73,58,132,199,177,246, 107,248,17,218,245,85,98,47,193,86,164,249,214,38,254,250, 194,167,33,73,48,161,0,180,128,197,188,62,194,176,62,94, 99,168,115,43,233,61,13,58,134,178,222,228,137,231,102,93, 172,183,62,233,127,87,15,242,172,27,103,15,64,180,6,64, 127,147,206,208,147,26,250,139,174,190,182,80,114,211,38,69, 33,246,37,37,134,139,87,24,210,91,92,170,11,76,2,15, 128,17,65,38,152,196,141,240,217,111,137,149,130,157,211,111, 125,192,38,5,121,67,66,33,214,7,33,214,135,152,245,81, 51,8,42,178,177,254,228,206,206,217,139,224,120,9,184,132, 82,52,149,91,239,199,87,238,102,165,66,198,132,65,3,10, 136,211,218,69,151,252,154,56,138,147,22,204,143,203,227,241, 97,32,246,80,155,89,121,60,60,216,14,60,98,92,125,32, 28,95,128,233,128,208,112,124,1,168,154,47,96,188,249,20, 188,134,165,222,249,0,18,111,206,61,13,45,117,132,247,15, 144,75,57,128,88,202,129,177,37,1,167,206,5,56,15,128, 12,205,154,130,141,193,133,49,87,192,33,2,136,137,81,29, 197,65,33,182,122,110,58,241,71,24,88,134,76,30,132,206, 1,232,40,75,163,183,228,242,223,172,240,125,156,144,235,195, 177,21,113,103,19,240,235,35,24,148,4,25,215,71,24,214, 71,205,183,203,12,6,117,32,63,60,171,21,157,240,152,85, 239,90,123,53,173,94,228,152,64,33,128,18,90,183,157,6, 198,85,55,101,188,5,27,131,171,241,170,78,180,41,43,133, 195,254,149,96,11,107,126,81,60,25,138,114,142,241,90,124, 64,160,255,189,222,133,31,221,250,8,105,125,68,197,235,227, 45,213,250,175,15,12,85,30,242,185,223,241,147,59,167,230, 140,38,103,113,199,198,242,231,73,215,131,60,235,22,173,3, 21,217,0,235,182,15,64,122,147,156,217,194,16,129,195,23, 185,38,12,145,177,185,244,7,232,167,238,241,78,176,92,116, 241,75,191,233,157,243,196,230,233,85,18,79,4,94,95,141, 168,5,91,13,40,119,125,248,210,40,119,164,72,148,235,195, 183,110,201,17,57,87,191,26,23,249,216,204,67,201,51,9, 60,248,25,90,167,67,125,200,221,108,212,36,160,241,135,0, 249,55,196,153,234,223,246,2,128,201,75,11,214,137,85,241, 109,252,17,27,126,123,62,41,157,6,92,93,64,176,115,8, 38,65,232,77,232,9,207,158,40,88,213,209,123,238,56,245, 50,103,232,195,172,15,124,238,93,190,63,211,250,40,92,110, 17,172,143,25,143,143,218,203,221,169,59,155,22,169,121,12, 210,76,69,189,201,243,244,223,156,15,64,245,106,0,242,223, 194,233,130,161,169,68,72,138,173,186,203,97,248,2,252,171, 239,60,95,128,142,199,175,142,47,0,101,242,5,56,198,202, 133,223,250,160,162,245,169,7,62,5,53,46,31,95,62,128, 206,29,237,203,234,17,239,31,36,207,102,20,213,71,212,245, 128,168,41,193,138,239,97,98,26,135,55,231,28,118,24,210, 96,60,95,0,2,168,179,253,0,66,193,120,120,254,254,130, 249,2,76,159,155,154,149,193,144,125,249,175,207,68,230,83, 24,111,62,128,246,237,157,151,215,41,222,223,95,254,120,54, 167,248,178,31,80,199,125,0,158,231,64,211,56,32,166,31, 30,93,127,205,205,232,124,110,55,162,128,124,189,26,213,59, 204,203,227,143,199,135,241,142,200,55,155,175,215,166,245,170, 186,96,206,167,215,151,119,252,248,20,116,154,177,242,248,20, 198,143,15,160,249,169,105,151,215,43,222,223,95,62,178,182, 168,252,234,63,117,217,7,32,61,123,103,26,177,47,101,73, 85,92,165,232,22,39,95,128,172,120,114,205,85,77,195,152, 240,248,106,153,208,204,23,224,61,196,132,187,107,149,171,128, 227,11,32,237,254,163,95,31,206,176,152,249,20,244,35,53, 194,175,15,129,231,67,136,159,15,32,249,204,204,75,168,126, 241,254,62,114,113,112,255,43,112,65,197,195,192,92,37,12, 168,227,36,32,32,48,205,212,147,231,117,208,204,48,224,241, 224,11,144,23,164,82,190,128,48,120,124,1,19,95,129,126, 253,248,248,20,196,56,243,41,200,158,65,28,124,0,226,197, 57,23,66,212,47,222,223,79,158,234,203,202,39,1,171,30, 64,221,49,2,73,137,99,103,170,107,140,66,137,137,44,245, 254,58,248,68,233,28,115,47,119,126,47,207,219,11,132,63, 128,203,68,25,46,24,47,67,102,236,37,246,239,189,123,85, 16,235,32,41,6,83,63,37,152,187,39,193,246,39,122,239, 143,0,195,253,17,115,138,178,121,125,168,194,245,145,251,11, 133,49,164,168,86,142,93,115,206,70,82,254,214,242,251,161, 51,241,214,141,124,172,255,9,184,112,181,227,64,35,246,1, 146,17,239,251,165,255,223,162,22,104,200,200,171,175,159,215, 194,15,98,14,215,86,51,222,220,249,64,122,210,141,207,23, 240,109,176,250,253,57,218,177,166,188,10,201,13,31,252,217, 124,196,228,8,4,155,244,227,13,9,180,53,149,239,143,59, 100,68,63,45,193,63,169,231,151,91,169,124,125,160,29,133, 66,26,128,186,42,249,254,121,51,209,38,88,140,128,154,140, 171,55,57,144,189,107,104,164,168,254,186,17,168,107,62,128, 220,99,105,81,59,227,28,31,167,208,204,23,32,2,248,2, 132,47,95,0,25,92,222,120,249,2,194,240,21,16,184,206, 193,232,215,39,58,190,128,120,248,20,226,226,3,192,241,89, 66,76,175,119,188,191,122,240,111,105,28,127,160,120,24,120, 54,175,250,110,244,41,192,248,56,1,145,104,81,31,190,63, 222,220,132,135,215,29,125,25,15,111,42,253,153,248,2,68, 40,190,0,81,21,95,0,24,229,246,203,5,192,24,107,87, 191,62,193,124,1,227,207,167,16,61,31,128,24,154,121,162, 105,94,253,227,253,161,117,76,228,255,247,232,209,163,200,230, 255,41,24,129,88,76,64,244,132,32,249,255,186,45,58,30, 222,220,137,31,134,47,64,84,192,23,0,159,238,125,190,245, 198,212,208,83,46,95,128,96,248,10,120,190,0,138,104,125, 252,88,16,234,159,79,33,82,62,128,244,212,61,45,11,235, 21,239,15,207,113,178,196,164,52,5,8,67,247,32,11,183, 104,2,178,69,19,64,81,99,2,99,11,1,68,139,254,114, 8,230,68,28,97,216,97,244,221,136,202,226,11,224,43,210, 254,124,1,220,252,186,163,204,243,5,8,246,254,204,124,1, 130,157,223,143,47,160,124,62,5,63,190,0,98,101,227,203, 167,16,17,31,0,77,125,161,117,105,253,224,253,245,214,61, 53,199,68,42,146,113,239,161,221,200,34,35,249,0,106,34, 176,142,207,6,4,68,139,3,199,140,135,247,99,179,231,249, 2,0,30,143,174,95,31,74,6,92,111,81,33,6,66,28, 134,47,64,176,32,78,249,254,195,243,5,160,108,190,0,71, 129,138,148,199,23,0,35,95,64,37,124,10,48,28,37,22, 21,159,66,53,124,0,173,79,117,92,86,31,120,126,0,82, 198,131,216,247,22,90,22,32,181,42,155,241,236,254,37,35, 64,209,195,131,227,160,4,3,208,222,162,226,225,249,44,118, 181,124,1,38,110,193,210,239,59,154,237,213,123,224,121,15, 66,149,147,49,94,134,177,94,31,37,95,0,127,150,112,88, 190,0,83,254,190,50,62,5,193,174,95,116,124,10,64,165, 124,0,45,219,167,93,86,15,120,126,206,59,17,158,142,94, 161,105,114,241,47,71,14,61,99,80,255,186,110,5,150,190, 113,83,66,69,241,195,128,135,231,89,239,170,229,11,0,84, 0,16,23,139,115,243,131,117,239,117,232,113,16,95,0,2, 208,125,229,243,5,68,185,62,213,240,5,192,55,203,16,23, 159,66,56,62,128,230,167,102,92,62,158,120,126,176,105,77, 72,221,15,94,117,7,19,28,184,119,141,142,228,213,62,147, 15,3,220,137,88,6,52,114,240,132,193,155,115,233,33,160, 26,190,0,176,138,165,238,131,164,237,187,96,243,9,229,240, 5,144,239,253,241,223,159,227,11,136,103,125,160,244,84,168, 124,1,230,245,169,5,159,2,175,82,38,62,128,196,179,51, 223,50,62,120,126,249,40,18,111,168,71,10,58,18,82,216, 160,182,76,17,128,163,91,242,170,159,201,27,1,213,7,136, 116,36,99,209,125,38,174,52,31,100,169,118,224,235,9,41, 189,115,80,63,235,69,62,143,143,24,69,215,27,107,228,199, 4,99,5,93,109,139,225,122,207,244,249,245,96,134,124,219, 89,249,251,227,214,71,13,21,184,245,145,103,224,186,21,1, 24,83,159,250,250,192,167,195,160,146,245,49,5,123,250,250, 16,155,99,208,225,90,206,203,179,207,23,142,220,235,40,148, 242,154,218,11,89,141,92,53,74,228,9,236,184,191,87,131, 2,181,171,33,255,211,214,19,199,24,247,63,134,244,95,244, 30,0,233,177,0,49,120,120,71,113,49,117,60,60,25,43, 3,114,167,157,126,206,29,127,42,176,95,173,128,11,23,56, 160,79,180,124,1,20,17,95,64,181,124,10,20,122,125,162, 230,11,16,101,174,79,16,31,128,243,198,236,211,157,150,120, 241,250,185,255,239,26,61,19,48,127,79,154,211,239,245,22, 244,36,224,208,125,197,253,63,163,213,1,98,96,7,142,167, 10,64,34,171,186,254,250,203,237,74,81,99,88,60,62,80, 14,30,223,140,77,7,83,123,230,94,83,26,119,190,128,56, 249,20,120,116,70,208,250,212,3,159,130,98,86,250,231,180, 57,157,113,226,245,193,4,52,58,253,9,95,223,215,17,44, 106,96,80,12,149,247,28,222,45,237,254,25,79,35,240,132, 73,2,2,200,100,85,188,182,78,58,45,180,82,24,191,255, 65,91,42,62,174,5,147,237,231,58,217,244,72,95,117,91, 73,75,137,5,241,5,136,64,60,188,31,15,48,192,195,90, 253,195,130,241,230,83,224,210,99,84,33,95,64,249,124,10, 146,114,158,156,61,230,204,86,19,110,64,52,120,125,121,125, 73,241,63,72,241,101,84,126,2,185,92,168,115,37,201,149, 140,209,85,217,92,212,239,221,255,99,13,1,162,246,0,242, 55,151,206,248,225,181,1,238,252,121,30,57,47,180,28,170, 218,97,197,227,225,69,76,124,1,240,225,11,16,40,151,175, 0,202,222,192,227,233,249,245,169,37,159,66,24,190,0,3, 32,183,2,62,5,238,254,132,97,51,16,192,232,204,254,166, 69,209,226,241,161,189,25,92,11,178,30,249,154,0,190,166, 138,191,178,146,195,71,158,145,18,127,153,120,75,128,241,120, 0,4,2,141,101,195,224,181,253,248,2,248,61,154,231,19, 224,228,113,241,5,152,239,223,97,190,95,101,124,1,20,98, 125,38,51,159,66,176,220,115,111,217,169,187,154,23,69,131, 199,247,70,232,130,141,218,193,236,228,94,185,156,244,227,102, 245,178,24,170,191,153,93,51,58,86,204,253,103,20,48,208, 132,8,1,138,126,208,40,29,187,126,244,72,214,231,124,118, 211,249,244,126,7,95,9,173,185,148,12,21,102,176,24,59, 14,47,200,85,196,133,65,81,249,99,59,121,52,129,80,202, 114,60,91,46,7,61,18,80,79,140,23,6,22,229,240,235, 35,124,214,199,148,194,227,238,175,190,214,7,64,145,238,83, 207,82,240,76,187,186,92,125,121,85,135,222,152,227,134,222, 213,72,70,40,59,159,80,148,175,127,236,33,73,249,99,46, 0,198,227,1,20,227,148,29,47,29,123,244,48,78,96,204, 120,126,187,255,249,244,166,138,183,74,96,173,166,81,248,58, 183,154,238,50,19,149,3,60,184,86,199,11,234,247,71,26, 108,71,135,186,168,199,117,130,113,56,245,86,153,112,235,67, 198,245,129,18,104,84,122,127,194,144,207,24,175,245,105,123, 188,243,82,25,35,192,3,133,84,57,180,159,188,177,186,92, 26,230,243,252,42,73,47,159,3,40,169,132,124,125,110,126, 122,240,212,9,79,242,79,133,0,213,249,217,128,164,244,100, 18,136,246,17,70,48,2,7,237,104,69,146,77,180,145,22, 121,66,33,206,224,146,133,92,247,188,78,73,13,99,81,79, 205,241,171,204,55,178,147,168,86,173,73,170,236,251,151,214, 228,244,38,25,26,123,73,235,48,227,238,207,127,125,72,59, 88,68,93,31,213,140,192,135,132,84,142,132,131,238,143,195, 31,168,184,15,157,105,200,180,62,164,193,169,76,243,55,63, 49,245,10,21,114,43,207,16,180,135,147,84,131,210,217,6, 204,249,13,63,191,192,36,37,86,94,152,121,208,91,0,204, 42,61,128,177,29,15,234,68,184,247,67,62,184,128,14,20, 150,113,0,253,56,140,161,60,146,129,195,115,151,119,62,189, 96,91,52,189,95,201,175,7,94,71,237,115,145,167,238,136, 251,241,5,232,153,109,51,30,94,24,102,69,136,239,111,150, 155,248,2,252,215,103,34,243,41,36,158,158,113,153,172,252, 102,60,62,95,139,247,150,229,248,40,95,72,167,114,8,237, 175,244,43,234,153,0,255,249,139,123,230,238,35,123,52,4, 64,172,209,127,124,125,0,249,219,205,28,104,246,56,7,25, 156,196,41,76,65,43,90,160,50,196,10,246,161,169,110,156, 163,164,18,5,147,91,54,213,164,185,174,64,190,160,165,243, 224,241,28,251,28,187,175,90,176,35,105,111,211,115,234,252, 157,22,86,172,244,125,157,178,214,135,128,200,214,135,12,228, 29,65,235,163,238,239,220,185,4,230,245,225,153,16,229,251, 115,94,152,189,140,132,247,119,84,186,60,189,17,151,171,68, 112,16,99,185,7,213,116,125,176,253,0,20,106,126,249,56, 85,0,24,203,21,0,189,45,64,110,188,5,192,232,13,128, 236,3,184,217,131,122,54,117,20,35,112,208,134,41,104,214, 106,210,164,193,84,185,131,64,76,14,180,186,180,34,212,139, 200,183,167,146,79,238,155,175,148,251,29,91,78,158,198,39, 19,123,45,49,205,51,220,119,114,67,172,143,9,158,75,12, 23,96,24,69,197,56,174,143,48,173,207,171,51,22,80,82, 125,191,244,83,137,248,208,17,108,81,142,152,146,172,220,211, 199,151,108,133,198,172,200,205,175,190,185,202,29,12,246,63, 107,216,255,99,220,253,163,247,0,188,30,14,13,29,106,99, 241,210,46,134,48,132,4,218,49,5,9,95,188,183,252,66, 5,241,5,128,121,121,204,124,1,66,67,1,112,205,198,65, 93,115,97,249,2,0,127,190,0,189,67,159,208,72,124,10, 65,235,163,144,200,238,155,61,3,109,106,180,31,84,125,23, 74,150,64,104,73,97,174,119,146,24,15,205,188,187,155,231, 231,178,20,165,111,152,189,51,157,98,26,128,106,16,2,196, 209,9,152,191,221,161,227,72,153,241,210,89,156,196,33,28, 207,87,9,0,14,239,93,41,95,0,183,247,192,240,95,14, 143,111,190,190,254,179,163,205,195,243,1,112,4,150,38,90, 51,239,157,56,6,247,17,90,213,188,81,248,20,112,108,166, 192,116,193,152,34,57,163,239,135,215,87,211,182,196,100,1, 84,195,17,26,207,31,114,126,207,147,163,163,91,181,6,32, 55,238,2,96,156,101,192,92,51,144,75,123,130,240,212,35, 56,142,131,56,137,52,194,225,189,133,129,162,42,24,15,207, 53,247,170,77,55,102,190,0,32,152,47,192,143,229,142,175, 166,251,179,238,169,40,254,202,249,20,194,172,15,48,49,248, 20,156,193,105,39,156,211,73,81,55,157,167,200,68,157,39, 148,215,20,44,209,58,49,5,66,37,105,7,176,152,192,74, 230,167,251,7,79,41,13,64,217,248,11,128,209,87,1,72, 45,4,138,189,97,240,212,192,16,142,162,31,131,200,26,240, 222,194,135,14,147,139,70,57,60,60,213,144,47,0,33,240, 240,196,30,234,237,205,169,151,203,167,16,180,62,240,93,159, 9,194,167,144,238,120,179,233,28,245,47,72,217,169,117,69, 86,19,84,58,176,136,199,243,67,9,107,92,45,111,19,197, 252,67,235,180,6,32,55,254,2,96,60,85,0,233,0,35, 218,27,30,111,157,193,169,98,149,192,1,127,254,187,8,224, 11,144,79,228,33,192,216,87,30,158,47,64,173,7,155,58, 20,170,225,11,16,190,120,120,32,44,159,66,208,250,64,91, 159,234,249,20,106,177,62,197,122,61,117,60,223,114,9,148, 191,128,143,134,8,6,136,166,42,166,80,122,38,192,238,237, 250,42,250,207,79,26,166,212,56,255,206,99,123,149,238,255, 154,20,0,227,44,3,230,13,65,246,64,130,73,42,145,102, 45,75,242,81,140,194,201,153,1,42,156,233,166,150,199,252, 206,245,17,12,229,38,95,226,19,218,105,61,0,119,68,25, 41,7,90,240,93,98,250,252,50,67,172,80,204,20,31,247, 18,83,17,241,114,35,168,229,65,29,195,22,126,125,248,249, 77,40,195,74,214,135,180,118,162,106,215,167,229,137,150,203, 193,86,50,212,215,143,143,208,115,195,213,140,33,135,231,39, 205,15,32,229,157,49,181,6,151,59,255,216,157,217,172,39, 253,87,179,2,96,60,85,0,239,57,230,68,251,43,193,99, 187,24,193,48,154,196,20,180,33,193,58,170,225,248,2,128, 32,188,57,1,134,102,87,176,9,41,140,59,95,64,45,249, 20,76,39,3,194,88,4,140,151,79,161,105,123,251,229,124, 25,79,119,214,229,122,6,143,231,7,84,54,127,98,86,67, 176,254,147,105,254,114,248,4,242,127,113,242,240,243,76,1, 208,123,16,72,172,35,198,42,0,40,125,160,114,60,118,26, 3,56,132,163,24,102,187,180,56,62,1,192,124,20,152,9, 29,111,114,171,213,108,54,212,66,20,27,77,151,203,23,32, 124,249,2,28,95,214,188,70,227,83,104,122,162,227,114,221, 53,215,153,129,121,60,63,49,201,59,120,122,244,245,180,159, 183,250,207,147,128,153,241,254,97,230,47,200,211,185,2,160, 202,1,20,19,5,104,188,30,128,198,214,148,62,216,138,234, 206,79,31,195,24,78,162,181,24,18,168,231,191,115,177,175, 185,167,143,235,123,19,62,254,129,137,47,192,27,247,6,243, 5,168,78,45,223,168,74,12,30,159,79,56,249,241,41,148, 90,133,130,248,20,130,248,2,234,139,79,1,59,58,46,229, 43,238,65,71,136,65,58,109,129,195,243,155,14,237,128,143, 171,143,0,30,160,160,249,75,241,192,241,109,134,246,223,216, 11,128,113,123,0,0,13,30,22,196,47,82,57,120,109,194, 48,142,226,160,24,68,154,221,193,72,250,42,58,94,158,140, 175,95,88,60,188,154,107,55,225,245,121,15,194,123,127,38, 60,60,161,28,190,0,24,230,55,177,242,155,255,126,98,240, 41,56,47,119,45,134,163,166,238,132,230,146,243,204,193,170, 115,79,62,217,121,147,156,175,244,83,40,230,98,149,35,64, 186,151,77,249,2,160,190,255,199,30,253,199,149,3,240,24, 129,193,20,14,98,94,52,231,167,187,24,192,0,90,208,138, 41,12,194,155,103,169,149,203,110,122,58,17,224,89,245,136, 201,180,19,227,160,154,162,100,191,254,59,115,127,155,158,133, 55,93,211,235,118,114,117,2,253,206,5,211,95,23,229,250, 192,216,159,24,102,125,248,231,87,244,90,94,239,152,39,90, 76,237,187,96,195,27,242,193,251,235,85,9,174,167,80,15, 68,200,144,208,54,93,159,124,19,149,185,107,14,110,80,114, 255,37,231,191,70,38,32,250,42,128,55,17,8,218,43,230, 69,121,126,250,24,198,0,180,162,13,45,4,193,159,15,15, 22,180,41,164,166,78,189,14,32,36,24,43,152,58,2,1, 236,245,137,173,101,115,17,55,105,176,29,97,84,84,61,79, 78,76,32,194,191,194,66,203,88,144,33,29,24,245,250,232, 53,5,63,132,128,122,127,236,250,28,236,104,67,87,80,167, 191,186,90,208,126,147,175,36,233,138,76,198,74,82,12,243, 191,124,116,159,167,1,72,143,255,49,49,67,0,175,167,181, 55,142,243,213,71,112,20,7,197,0,50,134,158,56,249,255, 59,224,58,213,0,48,61,110,60,207,142,57,41,88,72,214, 113,7,91,169,231,33,9,214,105,246,59,227,24,204,253,233, 117,118,33,221,135,185,53,74,24,234,26,81,174,143,94,85, 16,210,250,152,169,224,133,22,98,1,2,56,209,150,22,115, 204,209,56,41,101,72,213,103,33,205,179,240,143,219,245,218, 75,16,159,64,53,243,143,173,102,186,255,106,86,0,140,211, 0,20,125,0,119,95,92,231,171,187,24,64,63,142,96,48, 223,44,5,101,135,50,227,221,29,150,24,76,85,155,240,124, 1,106,150,92,109,251,229,10,153,165,89,184,115,124,195,241, 5,8,45,247,46,203,213,108,251,196,225,83,40,94,117,164, 173,63,113,38,152,252,58,177,173,185,58,95,143,220,120,43, 216,134,29,78,78,140,113,224,209,255,85,204,127,252,232,75, 76,3,80,205,10,128,241,24,0,82,206,61,216,31,239,249, 235,105,156,194,33,156,196,40,136,4,19,123,146,114,44,57, 223,223,46,159,153,167,43,170,254,178,242,61,1,230,254,126, 98,20,67,151,251,157,204,7,230,254,161,220,191,255,253,57, 62,13,195,196,48,10,134,95,31,193,172,143,40,107,125,216, 179,8,179,205,175,58,231,131,9,27,228,226,177,137,103,199, 155,48,4,91,148,211,187,66,205,254,1,63,63,66,205,15, 118,254,204,234,116,74,105,0,170,105,1,48,174,28,128,212, 9,144,57,216,2,176,172,108,106,228,84,141,124,24,195,112, 68,27,90,145,100,234,205,168,154,47,0,134,115,105,194,225, 241,185,84,34,65,199,200,187,158,25,77,217,3,2,140,77, 183,149,242,5,84,191,62,241,240,5,52,61,211,116,25,152, 40,156,88,215,93,48,29,1,106,118,94,48,249,20,248,164, 235,72,163,137,171,108,126,48,199,138,35,123,252,81,100,198, 179,0,24,159,1,240,152,188,2,43,80,252,231,179,19,134, 48,136,36,218,209,66,73,193,31,238,72,101,243,5,128,205, 199,151,195,23,0,31,60,188,144,220,99,199,192,192,167,115, 10,154,248,2,80,21,95,128,122,229,202,248,20,84,131,66, 21,174,79,226,177,166,43,229,115,247,244,221,84,104,247,71, 108,223,189,233,201,201,201,60,142,169,128,180,223,54,203,121, 142,0,245,205,41,252,174,187,126,120,144,57,4,172,134,5, 192,56,66,0,149,8,149,6,250,249,40,41,174,243,217,51, 56,137,126,113,12,35,32,34,246,33,153,248,2,76,49,111, 181,124,1,130,73,200,169,243,146,225,20,97,46,211,160,122, 19,142,81,117,213,249,107,195,167,160,238,123,78,69,235,227, 108,111,185,146,59,109,7,172,31,196,115,247,171,94,131,140, 231,215,13,144,25,239,207,117,249,169,70,210,4,0,22,202, 113,96,133,223,29,218,104,216,255,169,150,53,128,120,14,6, 241,104,228,201,1,103,144,79,130,197,121,126,251,40,142,227, 144,56,133,52,155,168,82,51,210,142,47,30,30,145,224,225, 29,95,35,80,30,95,128,122,125,71,202,231,35,38,190,128, 154,242,41,60,213,242,86,243,241,92,82,150,217,112,20,44, 49,77,59,96,15,2,225,229,64,216,249,3,178,224,208,219, 147,1,128,158,63,118,192,176,255,187,62,211,78,136,36,160, 2,9,114,247,212,226,124,118,93,238,230,89,6,6,144,37, 213,96,232,39,225,153,241,240,48,168,19,25,32,71,102,54, 91,61,207,173,215,221,199,147,47,160,110,248,20,158,107,189, 40,247,129,218,230,203,17,120,104,47,28,184,195,216,11,170, 234,42,120,127,210,120,252,192,210,150,171,29,125,130,121,233, 195,204,95,144,167,214,132,96,0,158,144,85,0,205,20,208, 155,164,40,46,199,33,23,151,60,139,1,28,202,135,4,122, 141,160,180,187,145,178,23,234,187,25,12,123,166,240,40,33, 159,225,23,108,149,93,63,203,71,61,25,199,155,153,39,109, 255,14,202,188,243,101,69,24,238,159,235,52,144,215,71,132, 88,31,17,98,125,68,208,250,236,154,178,144,146,28,179,174, 94,148,147,43,241,114,158,129,39,248,22,134,180,28,105,70, 90,39,249,240,155,159,202,155,255,216,145,151,138,229,191,140, 114,8,136,91,187,4,96,124,85,0,175,65,220,95,14,31, 64,60,242,49,140,194,17,57,150,1,18,222,93,179,82,190, 0,189,26,224,199,23,16,196,87,224,143,135,39,248,241,5, 148,44,121,20,124,1,136,136,79,161,226,245,217,219,60,211, 109,247,107,219,17,6,133,47,253,215,101,73,75,133,33,155, 160,31,70,235,199,55,96,154,223,187,210,46,147,192,149,231, 207,222,145,77,43,13,64,227,80,0,140,203,0,200,254,16, 185,251,18,145,156,207,94,173,156,48,140,97,36,69,43,218, 40,33,160,185,206,38,28,122,16,95,128,124,98,1,143,135, 39,197,141,22,90,25,206,212,6,197,243,231,114,24,123,50, 204,95,57,95,0,16,5,159,2,25,131,15,87,1,244,8, 208,209,102,135,166,235,165,58,158,57,154,59,139,136,175,253, 32,160,190,79,12,222,223,52,63,149,49,191,224,231,207,156, 120,220,115,4,88,102,188,10,128,241,133,0,146,153,165,3, 213,158,207,30,165,60,131,1,244,139,163,24,133,235,10,54, 120,128,164,66,225,248,2,248,3,56,56,190,0,132,192,195, 147,33,105,166,215,39,252,249,2,128,114,248,2,120,100,126, 156,124,10,90,74,113,32,113,146,78,231,170,62,194,128,167, 39,6,32,36,227,238,72,243,245,184,120,159,171,238,155,230, 71,232,249,97,152,159,238,243,20,0,185,51,0,48,25,66, 128,98,70,36,117,48,137,202,249,0,226,145,143,33,5,56, 83,208,134,22,18,194,196,118,23,196,23,0,13,111,47,27, 13,215,112,34,160,222,225,40,140,120,120,10,228,11,224,15, 171,168,132,47,64,55,27,250,247,143,143,79,65,164,176,215, 89,170,23,147,120,159,14,12,20,87,63,114,78,24,16,131, 122,226,207,204,240,95,206,252,60,223,128,58,255,192,38,109, 255,207,142,71,1,48,190,42,128,68,13,154,58,196,57,95, 149,157,223,30,165,156,48,138,163,232,23,3,72,187,48,156, 216,99,198,195,243,61,242,2,28,31,1,216,138,58,133,192, 195,243,89,122,57,101,73,134,235,155,248,2,28,237,142,193, 118,68,248,243,41,4,173,143,185,231,193,192,167,64,120,193, 89,42,119,209,235,189,133,106,151,61,25,123,0,248,157,90, 199,230,131,217,217,189,121,124,19,7,16,63,63,2,231,7, 104,199,137,67,218,254,95,58,3,0,181,221,255,227,11,1, 138,94,192,137,163,34,91,221,249,237,113,202,51,24,192,17, 231,40,70,224,186,124,145,79,104,217,109,238,136,108,193,86, 183,73,233,129,55,29,219,105,190,62,105,7,105,243,85,122, 135,253,123,98,238,159,111,125,210,209,122,178,25,112,148,110, 130,234,214,71,104,134,204,121,194,185,68,101,15,224,232,56, 212,228,37,247,25,239,23,64,171,244,243,175,173,96,35,89, 24,126,246,199,10,114,220,131,99,107,152,250,127,118,60,10, 128,113,25,0,37,92,75,101,176,175,252,243,219,107,43,31, 195,9,28,116,142,99,20,185,106,161,96,27,123,212,120,153, 147,203,138,32,180,179,126,132,166,6,106,50,74,134,237,232, 187,40,177,133,69,50,150,24,193,168,136,122,164,186,206,74, 32,24,127,134,63,223,152,95,31,17,122,125,0,0,143,225, 114,210,138,110,122,220,175,246,244,9,166,118,79,134,79,244, 174,66,181,109,53,236,252,38,102,104,125,126,230,254,14,31, 219,41,69,254,25,41,0,168,113,2,48,190,62,0,9,17, 72,123,162,230,3,136,71,62,130,99,56,148,15,9,100,112, 113,9,128,107,198,195,139,154,243,5,16,179,167,154,249,2, 132,145,47,128,235,33,168,29,159,130,128,216,46,174,52,237, 225,50,231,147,222,201,71,172,129,67,192,190,92,14,222,223, 107,26,185,64,178,188,249,179,171,178,41,205,3,144,25,128, 38,65,21,0,74,30,96,95,28,124,0,241,200,179,24,196, 97,231,8,134,64,89,181,69,52,8,111,47,171,82,229,124, 1,94,137,99,216,63,101,229,162,0,190,0,21,86,21,204, 23,16,63,159,66,81,246,140,184,204,20,53,151,90,128,76, 81,190,96,241,252,130,221,149,77,120,126,97,168,97,203,87, 226,243,5,193,243,75,30,65,250,248,99,1,12,192,53,31, 241,49,2,21,215,223,221,31,31,31,64,60,242,20,78,162, 63,113,18,163,68,46,135,215,39,69,133,28,69,245,203,231, 11,0,219,35,39,7,15,149,243,5,232,156,59,126,124,1, 66,171,144,87,203,167,224,211,181,248,146,88,66,14,152,74, 129,80,210,112,130,221,151,195,224,249,73,11,102,244,52,30, 215,187,32,140,121,0,53,188,84,231,119,153,210,167,0,144, 253,221,232,16,19,255,103,149,67,192,106,58,146,49,237,253, 158,102,32,218,31,55,31,64,28,114,23,195,24,22,9,209, 138,182,108,50,97,102,28,228,248,2,160,57,134,234,223,19, 179,115,242,240,226,104,249,2,248,35,196,160,245,237,149,199, 23,0,4,241,5,200,202,88,84,212,221,226,116,106,209,139, 104,38,2,80,1,238,119,133,22,115,243,223,86,101,8,214, 251,17,131,240,252,220,153,128,130,137,249,77,243,15,110,68, 26,25,164,37,35,224,142,95,2,48,222,62,128,162,103,148, 57,144,64,252,124,0,241,200,179,24,196,96,162,9,173,104, 203,56,73,104,199,68,149,203,23,192,243,1,148,199,23,0, 102,71,227,19,138,48,220,31,215,90,28,204,23,96,230,83, 208,147,156,97,214,135,14,160,221,237,2,19,101,171,41,54, 17,208,124,11,109,229,1,142,72,21,62,213,127,33,149,248, 72,121,50,130,49,188,164,152,17,255,249,129,236,79,78,29, 204,171,125,90,9,1,198,73,249,227,14,1,242,235,147,62, 4,212,138,15,32,30,121,26,167,112,48,121,12,35,132,44, 49,213,123,110,191,149,99,115,97,196,14,134,225,11,208,73, 71,160,117,11,232,127,79,249,20,30,177,201,61,104,85,123, 63,62,2,17,200,167,0,67,78,192,200,167,112,194,77,211, 28,30,79,175,31,133,74,62,120,127,176,120,127,254,249,202, 120,62,243,243,87,87,134,42,226,27,240,254,158,123,235,193, 7,144,65,26,233,162,23,32,183,0,99,124,76,64,188,101, 64,2,64,39,15,213,154,15,32,30,249,40,142,139,67,137, 83,72,103,136,229,23,144,161,188,81,242,5,80,8,190,0, 85,125,133,199,115,80,43,8,230,251,3,120,92,96,48,159, 130,137,47,192,192,167,48,226,30,162,179,184,247,93,40,25, 100,222,240,17,83,160,211,73,66,57,76,158,174,238,241,204, 47,255,59,251,219,3,247,49,234,239,221,255,199,97,247,143, 203,3,80,142,7,25,26,21,71,213,104,59,126,62,128,120, 228,89,12,225,112,242,48,134,144,77,169,9,37,142,47,64, 221,119,253,248,2,116,117,137,143,47,64,79,207,153,210,143, 166,251,171,134,79,193,201,100,119,185,139,249,220,63,129,3, 22,17,115,236,23,23,98,184,76,94,68,48,208,94,46,163, 31,110,126,50,206,95,74,255,169,167,84,184,119,28,190,59, 175,252,5,19,192,103,0,38,85,8,224,73,5,150,56,1, 106,205,7,16,143,60,131,147,56,212,124,12,163,46,50,106, 150,95,175,7,152,216,239,161,33,228,57,188,125,53,124,1, 34,4,95,128,8,193,23,32,16,204,23,0,132,231,83,200, 62,227,94,4,41,218,39,246,180,62,249,132,68,57,73,200, 31,192,169,83,179,144,175,119,93,254,252,48,206,15,211,252, 119,245,175,206,166,145,70,10,41,201,4,200,167,0,97,242, 120,0,106,242,150,176,87,77,196,168,185,247,137,40,31,197, 113,231,96,242,56,82,41,34,174,252,38,88,186,77,146,8, 50,72,139,197,73,51,39,186,59,205,225,249,117,58,116,121, 118,71,43,95,10,131,207,35,148,110,124,249,106,114,55,35, 105,1,135,218,1,160,251,15,217,71,51,111,133,84,221,215, 75,119,0,79,192,65,90,213,130,175,184,235,215,7,187,155, 115,243,187,122,37,187,204,249,165,28,248,186,67,189,217,180, 71,245,75,234,95,58,3,0,227,23,2,36,107,160,254,68, 251,196,184,243,1,196,35,39,140,96,164,57,129,54,180,143, 57,45,124,6,129,124,249,2,228,156,180,202,23,192,157,30, 204,159,173,83,143,124,1,236,253,63,158,125,155,250,77,185, 14,60,21,30,45,211,119,153,170,26,124,25,81,15,22,184, 249,57,62,1,193,20,136,203,153,159,238,239,255,175,236,24, 82,249,253,63,231,3,100,20,22,0,26,15,16,80,188,30, 128,66,10,66,251,235,133,15,32,30,185,139,1,28,108,57, 138,145,172,155,134,20,233,171,144,36,50,240,1,4,241,5, 240,236,121,102,190,0,174,23,49,104,126,10,49,63,25,143, 2,11,199,167,224,62,153,186,92,24,220,119,253,196,29,210, 142,140,213,207,238,37,233,88,46,30,187,199,201,137,245,54, 252,230,215,255,150,130,230,223,218,127,107,118,12,233,162,250, 151,60,0,142,3,112,82,121,0,222,167,73,217,3,137,186, 226,3,136,94,14,0,99,24,75,136,196,20,180,143,53,55, 67,8,182,21,132,227,11,0,91,191,215,249,2,252,241,246, 42,95,128,8,228,11,40,4,4,178,135,82,14,95,0,80, 30,95,0,61,151,186,24,130,52,79,70,24,214,23,76,48, 32,140,33,3,95,140,242,67,230,155,231,231,82,133,130,241, 191,200,111,254,199,15,223,146,29,147,246,254,148,39,5,88, 170,0,96,252,246,255,184,115,0,121,67,48,118,176,254,248, 0,170,151,115,164,16,132,17,28,110,57,36,78,33,59,226, 207,241,207,227,237,205,124,4,60,23,113,48,95,0,23,133, 171,121,3,111,204,111,230,11,112,180,206,129,242,248,2,240, 202,200,66,36,161,53,226,138,80,120,122,111,207,61,23,121, 235,127,229,151,218,227,79,3,0,244,174,127,82,51,218,1, 243,23,229,79,31,249,105,122,180,168,252,37,15,128,11,0, 198,109,255,143,147,15,192,83,218,24,59,88,175,124,0,149, 203,97,216,39,0,228,184,136,91,143,96,56,227,166,130,248, 2,76,108,253,178,153,8,226,11,16,70,190,0,68,198,23, 128,50,248,2,24,6,128,55,71,102,137,118,93,181,192,38, 255,72,217,123,133,113,139,84,243,46,208,158,159,233,89,249, 245,221,132,229,27,208,231,207,127,239,231,143,252,91,122,164, 168,248,99,82,8,144,81,240,255,227,212,3,24,127,8,80, 220,22,7,79,204,28,67,11,124,206,155,83,143,96,170,119, 185,234,116,203,238,102,238,47,198,48,150,20,104,69,219,200, 148,22,215,81,251,199,185,23,137,88,210,48,210,250,251,156, 226,181,28,173,230,204,59,234,186,131,205,241,25,114,221,253, 106,82,76,38,65,133,20,46,232,180,92,197,21,59,60,146, 192,12,24,40,55,73,73,86,18,119,5,166,104,103,238,228, 135,15,243,48,152,147,125,249,249,57,67,18,102,126,241,202, 177,239,167,135,242,206,191,170,252,153,241,229,0,172,93,18, 208,147,83,25,35,103,79,253,243,1,248,201,77,97,26,5, 236,81,46,134,112,164,117,191,115,138,178,131,66,83,124,111, 39,29,25,249,0,28,152,241,250,196,34,252,204,124,1,208, 170,218,165,221,219,81,40,70,192,118,6,234,129,72,48,95, 128,56,53,58,64,167,19,179,190,114,27,21,249,212,225,1, 14,66,69,33,158,143,0,164,68,157,208,158,159,128,31,17, 57,111,172,125,230,223,125,244,187,163,195,158,216,95,14,0, 244,236,255,184,142,120,249,0,74,228,224,123,39,6,31,0, 39,15,194,147,115,117,98,185,163,44,139,1,113,160,163,31, 67,41,26,53,31,155,69,170,211,12,51,95,0,5,242,5, 240,109,185,94,57,111,48,116,190,0,181,183,192,204,23,32, 183,6,23,191,197,216,200,155,217,115,120,150,60,30,79,207, 214,146,153,90,59,49,175,91,57,207,71,109,252,141,98,126, 241,230,177,111,143,13,22,247,254,49,101,247,47,236,255,117, 225,254,199,159,4,44,173,222,222,137,195,7,32,227,185,213, 116,27,49,4,216,96,162,79,253,32,138,20,142,55,239,155, 114,12,99,131,148,13,199,23,160,119,5,242,120,1,135,225, 11,0,67,210,233,199,23,16,204,103,224,40,121,2,157,47, 0,220,245,221,177,23,51,23,234,175,133,10,17,230,34,111, 149,19,145,124,246,103,174,145,202,236,23,112,207,199,52,63, 149,51,255,193,19,223,24,59,165,237,253,41,5,0,68,245, 225,254,199,95,6,44,26,70,119,191,163,68,154,245,195,7, 64,44,158,155,139,242,201,248,154,232,81,168,9,79,62,140, 225,142,36,166,184,157,131,201,174,32,190,0,10,193,23,224, 245,32,4,3,114,229,206,3,50,93,51,14,190,128,177,39, 82,87,112,229,83,61,247,192,225,233,193,134,2,48,62,31, 193,118,213,248,205,175,94,141,35,9,55,207,175,60,235,35, 131,255,50,124,210,147,248,27,211,156,127,53,247,63,238,65, 64,156,231,2,120,52,198,61,144,64,61,225,253,185,100,145, 48,158,15,111,250,122,130,57,191,94,166,159,208,89,229,114, 39,22,14,58,131,93,77,232,24,109,115,69,91,53,124,1, 144,206,156,231,191,137,96,124,32,254,181,231,122,10,195,242, 5,168,240,152,220,39,99,143,142,190,13,10,145,9,177,81, 58,135,167,151,229,48,62,31,97,48,202,66,83,126,210,148, 159,180,140,138,126,20,137,223,252,30,179,120,252,212,87,135, 142,121,218,126,184,226,95,157,169,127,45,250,0,8,4,74, 31,172,47,188,191,158,127,247,59,31,94,207,4,16,115,62, 124,41,124,224,79,159,87,231,79,227,248,148,253,109,71,49, 114,18,25,84,200,23,128,0,190,0,97,228,11,64,145,47, 0,154,81,224,249,12,252,249,2,192,220,95,246,241,209,183, 193,248,253,161,249,96,130,61,118,59,248,249,112,189,3,130, 125,114,28,1,88,245,243,3,0,78,157,250,234,208,81,164, 153,189,191,142,213,63,222,42,128,167,31,32,125,144,175,154, 214,26,239,175,239,46,229,157,15,47,216,151,74,207,124,147, 118,208,52,63,191,139,17,28,158,186,47,121,50,155,62,81, 57,95,0,140,124,1,100,84,127,57,223,224,72,57,0,50, 38,42,1,51,95,128,122,63,238,211,3,111,53,175,63,161, 28,60,189,96,119,96,115,158,158,140,207,167,210,249,3,222, 143,161,161,175,12,245,51,145,127,74,65,254,213,153,250,215, 224,120,240,220,191,143,245,131,198,11,207,47,239,255,28,158, 155,12,123,137,249,124,120,190,92,197,225,201,195,204,159,197, 169,196,129,105,7,48,48,236,14,84,194,23,192,201,85,190, 0,98,229,186,90,9,214,111,16,128,49,61,201,207,159,125, 97,112,41,28,174,147,143,59,102,211,180,62,28,246,130,88, 98,47,249,249,8,99,66,202,127,126,87,155,95,63,70,140, 116,136,240,232,200,87,6,14,178,177,127,166,254,42,255,181, 49,0,202,154,165,210,226,64,173,241,252,234,222,173,226,185, 77,200,49,53,191,205,119,141,169,24,53,238,184,234,242,230, 79,225,120,219,222,206,67,24,61,78,169,202,248,2,100,213, 228,249,2,244,147,4,28,214,39,0,252,248,2,192,112,16, 120,175,64,175,13,204,119,91,100,163,226,143,167,23,108,218, 84,176,250,34,152,245,231,225,195,48,62,31,126,126,193,228, 255,245,231,175,84,148,82,35,95,57,185,207,16,251,167,235, 91,253,227,205,1,72,134,159,246,198,143,215,47,156,207,206, 187,113,106,132,200,119,157,11,95,60,185,138,48,227,90,87, 92,214,205,12,198,147,231,254,59,134,254,233,123,155,143,165, 51,71,205,124,1,128,137,47,64,45,115,170,124,1,220,201, 133,165,92,0,73,125,6,130,205,5,112,124,1,26,231,225, 254,83,29,238,84,189,195,94,72,235,3,159,231,99,218,237, 121,188,63,49,142,185,96,155,116,184,231,19,118,126,240,243, 103,70,191,118,114,143,33,246,175,123,245,143,63,9,88,90, 175,189,96,242,189,130,217,117,43,147,155,250,182,5,11,184, 10,62,31,158,127,73,189,153,226,224,249,185,92,58,87,56, 84,231,119,49,208,180,127,230,62,156,26,160,19,60,18,0, 74,174,64,231,1,226,146,116,106,27,15,41,181,123,253,10, 194,147,40,52,5,7,26,15,210,241,83,233,204,28,253,251, 19,219,105,25,238,249,64,123,62,194,240,124,76,235,175,63, 31,161,29,153,82,193,252,238,216,215,79,236,102,246,254,148, 145,247,175,174,212,63,254,70,160,226,6,232,238,87,99,54, 32,26,60,190,252,95,98,98,62,127,60,55,124,170,199,196, 156,15,79,101,205,15,148,143,39,71,161,74,208,185,103,218, 65,12,31,206,245,15,114,213,128,242,248,2,76,145,188,236, 214,155,174,31,142,47,192,25,62,209,159,62,219,124,106,46, 73,113,55,21,189,11,211,161,30,166,231,67,218,27,97,94, 127,61,249,7,223,249,41,236,252,148,250,214,137,157,76,236, 159,210,64,191,110,125,170,127,188,125,0,18,175,130,187,47, 81,37,30,31,82,172,72,108,188,230,135,39,47,27,207,13, 47,67,188,122,39,196,176,249,152,122,7,202,157,223,155,120, 26,197,232,108,129,142,84,231,241,166,57,66,84,203,23,224, 237,233,11,226,11,64,8,190,0,53,40,112,50,39,118,165, 47,230,215,83,40,207,143,71,236,169,77,64,166,142,12,19, 108,75,24,161,218,38,190,1,19,75,64,240,252,233,239,28, 127,193,208,245,231,45,252,213,177,250,215,172,15,0,228,30, 228,221,105,222,249,226,229,166,243,217,205,76,47,122,246,215, 127,255,214,75,67,193,243,251,131,135,42,193,147,235,202,56, 208,188,127,238,62,113,242,68,230,88,56,190,0,191,44,189, 12,4,230,178,248,48,4,83,58,95,128,242,42,209,192,211, 99,23,251,69,237,102,188,63,152,76,190,31,75,128,96,206, 109,52,189,31,38,190,1,248,206,111,186,223,194,172,217,239, 31,219,81,76,253,113,125,255,89,184,200,214,183,250,215,2, 11,144,255,105,236,64,165,120,124,127,213,50,203,185,184,143, 140,80,92,115,194,49,202,249,97,56,33,55,204,252,105,28, 155,182,119,198,1,26,62,64,195,42,30,191,60,190,0,160, 60,190,0,132,228,11,24,121,108,248,114,190,107,222,124,118, 174,128,76,77,34,216,245,52,253,127,130,137,68,180,156,249, 253,222,15,193,248,113,0,144,253,241,209,39,149,216,63,205, 80,126,213,185,250,199,137,5,80,78,88,24,233,239,44,11, 111,175,30,14,69,74,143,124,56,60,57,127,36,20,41,169, 63,104,225,69,84,243,235,134,194,85,152,129,195,207,159,251, 247,168,24,157,231,160,99,164,243,88,203,105,148,208,247,111, 158,47,0,33,248,2,184,64,64,197,76,8,246,212,194,220, 95,142,62,58,240,54,19,165,42,25,159,15,223,111,89,217, 243,49,83,186,6,205,95,238,251,225,254,223,35,219,12,177, 127,78,253,51,210,153,63,117,171,254,113,151,1,61,217,128, 19,131,98,160,50,188,189,80,178,229,225,241,228,193,251,8, 149,57,63,191,195,8,223,111,21,46,81,18,60,191,183,221, 248,84,235,190,249,111,36,78,28,205,246,171,12,254,60,95, 0,160,119,239,145,193,107,80,205,133,163,252,151,11,26,4, 210,219,79,94,169,135,108,100,8,39,224,131,213,83,241,246, 194,119,125,192,172,79,152,249,195,61,41,254,249,208,173,71, 30,98,98,255,148,135,240,67,62,242,171,110,213,31,72,196, 120,237,66,159,73,2,14,18,72,204,252,136,152,195,197,142, 122,170,70,24,218,111,57,231,145,152,4,161,233,138,194,208, 116,82,233,252,220,111,251,37,244,252,230,39,229,224,81,243, 252,165,28,250,72,219,169,246,97,55,177,47,41,156,150,146, 196,219,54,204,119,250,135,227,11,80,115,9,36,237,25,114, 174,193,221,113,116,25,37,194,62,31,97,196,74,6,125,127, 142,175,39,252,243,137,102,126,247,183,71,214,21,137,190,229, 216,95,239,250,67,61,43,127,45,146,128,30,143,141,246,82, 224,254,236,221,125,4,235,34,170,153,110,24,121,102,212,215, 0,33,252,3,121,126,147,143,194,133,23,166,235,151,137,39, 15,49,191,28,222,140,57,135,206,120,163,179,127,40,245,134, 200,200,105,189,146,162,58,224,58,2,84,191,64,231,35,144, 77,128,89,142,87,250,207,165,38,254,249,4,127,127,242,225, 91,224,52,72,40,132,170,230,247,67,40,215,231,249,30,100, 121,208,252,180,234,248,189,1,136,191,82,244,143,255,191,189, 107,253,141,227,186,238,231,204,46,41,89,116,244,178,252,210, 195,18,149,4,109,26,20,65,31,104,210,126,40,208,2,69, 63,245,67,210,127,40,145,21,59,78,226,6,6,2,23,133, 139,162,117,251,193,8,10,23,181,40,89,85,228,88,113,44, 201,142,236,88,177,34,217,145,108,73,182,68,145,162,100,138, 34,185,220,221,217,153,57,253,64,114,119,238,189,231,220,123, 103,184,164,246,113,47,97,154,246,238,236,111,102,118,238,185, 231,156,123,206,239,215,251,38,160,186,81,211,31,8,38,109, 172,122,200,236,184,3,51,145,248,142,119,96,202,105,116,253, 120,179,89,183,140,62,252,90,240,249,43,90,59,62,193,226, 216,226,88,4,91,111,111,205,42,79,34,112,68,38,54,190, 0,117,117,148,75,152,117,190,130,229,255,155,125,126,123,87, 54,134,222,215,79,2,251,128,217,151,33,63,31,36,248,89, 200,220,43,96,249,30,56,124,176,224,175,140,163,179,255,155, 198,108,222,191,213,143,211,127,35,148,129,58,180,96,43,149, 0,250,90,6,226,218,9,154,180,53,79,214,192,245,147,163, 208,254,73,130,115,110,215,143,71,35,13,86,22,95,53,123, 101,240,245,145,117,38,34,220,123,124,14,54,37,219,110,140, 237,192,237,106,38,223,206,23,160,39,5,81,75,252,89,249, 2,102,102,170,217,78,179,218,159,167,205,194,82,247,95,191, 167,168,9,134,228,107,250,144,201,3,72,124,3,40,236,44, 240,11,13,0,157,152,253,239,148,143,253,251,116,250,175,183, 7,160,108,178,38,211,21,45,99,75,12,241,2,41,169,43, 52,90,61,248,126,114,53,218,228,74,129,116,174,217,110,225, 147,128,239,202,68,184,241,249,125,4,243,177,85,223,217,168, 54,198,17,182,220,223,241,197,232,94,24,229,72,69,76,70, 31,222,23,88,157,90,102,220,156,123,239,253,219,139,203,124, 127,40,246,251,203,165,94,230,245,219,190,31,115,173,7,102, 97,40,242,124,216,50,1,12,254,169,217,101,153,47,158,239, 39,97,98,255,158,159,254,27,17,2,180,55,3,211,41,211, 133,51,247,94,209,99,111,0,196,154,65,20,100,164,245,199, 120,253,241,145,93,75,144,21,177,144,240,229,12,57,143,223, 57,143,197,109,181,109,17,108,189,185,149,170,251,208,216,184, 35,163,121,136,243,97,242,175,71,198,54,26,0,1,54,103, 110,198,95,151,210,106,32,220,31,179,188,70,231,107,4,139, 92,14,90,242,34,126,248,220,243,225,129,127,122,246,63,211, 88,140,253,245,150,159,62,153,254,235,205,7,160,200,131,196, 183,249,126,122,245,225,32,75,63,55,88,250,185,243,233,29, 42,164,15,191,254,248,80,24,31,156,248,122,13,28,25,248, 41,204,237,253,108,223,205,120,225,19,250,194,76,252,17,67, 64,14,192,241,5,128,196,23,144,125,113,169,241,117,117,187, 140,155,88,249,176,33,83,54,229,252,190,31,59,223,130,142, 79,34,62,172,5,255,220,236,191,165,13,69,232,163,217,142, 252,91,185,125,255,62,155,254,182,29,185,110,24,23,132,10, 84,160,10,35,48,2,155,70,183,28,184,64,85,41,1,136, 98,77,190,41,172,109,123,167,239,22,157,153,96,130,174,224, 147,70,193,217,77,124,255,59,165,143,177,217,237,119,54,239, 135,205,102,16,65,76,73,45,183,198,234,159,78,48,255,235, 185,191,240,197,183,95,191,107,29,177,109,246,18,35,163,210, 13,124,229,251,57,63,247,211,182,206,79,211,40,251,73,32, 129,172,183,123,254,30,84,18,16,243,102,57,78,96,146,246, 35,211,28,203,165,255,228,150,92,50,190,112,62,66,38,103, 182,184,200,163,193,117,16,216,241,213,20,148,13,159,172,248, 36,104,218,216,240,117,106,210,197,157,181,157,17,124,233,250, 142,172,114,48,111,74,50,53,201,149,35,225,208,85,117,84, 234,19,130,218,59,247,190,197,225,171,98,234,166,89,244,185, 255,246,231,35,99,146,168,221,194,207,147,138,183,95,191,56, 247,98,110,250,115,238,127,223,78,255,141,40,4,202,149,2, 237,252,27,220,175,231,163,205,7,31,193,20,216,230,106,232, 213,189,1,180,172,184,36,230,195,193,138,15,93,192,71,49, 34,229,214,78,142,89,87,54,82,232,133,223,113,191,27,219, 239,239,88,108,224,149,81,138,198,58,95,17,39,85,162,243, 9,232,90,2,141,95,223,249,38,48,20,226,92,157,160,30, 6,217,124,23,0,249,249,48,239,168,252,124,148,197,55,247, 75,224,242,253,159,180,101,190,98,33,245,215,67,66,31,189, 152,4,236,116,4,78,234,229,51,25,128,81,119,141,150,246, 14,189,225,83,183,230,196,56,235,40,164,222,212,213,6,141, 152,92,247,75,100,1,105,44,129,15,90,166,29,197,243,3, 203,234,238,135,159,191,63,241,230,153,175,205,192,150,153,29, 119,182,28,160,49,208,106,234,228,80,35,95,215,23,127,48, 253,231,8,192,114,251,187,240,185,176,198,254,253,240,187,40, 0,188,174,97,119,241,225,218,194,63,181,58,50,95,188,206, 95,79,9,125,244,158,1,200,221,20,186,165,139,94,32,184, 245,225,137,213,171,147,28,104,31,253,120,50,50,223,182,126, 126,98,214,18,185,44,165,12,190,125,19,145,75,41,174,21, 127,233,177,218,99,72,219,175,108,163,145,175,46,31,226,203, 23,0,144,94,156,250,35,140,214,130,111,26,47,137,25,0, 132,231,67,218,167,161,194,248,96,99,6,184,49,191,42,243, 21,43,101,63,177,40,242,221,103,211,127,253,235,0,148,4, 110,122,43,98,108,52,23,53,147,97,247,185,13,50,2,190, 6,140,239,218,147,18,122,104,176,152,35,179,238,184,240,129, 253,44,223,132,162,25,219,131,120,127,138,227,235,53,112,43, 127,225,189,175,206,65,165,182,227,234,182,157,184,199,84,22, 224,53,132,178,171,147,123,87,233,62,51,35,225,233,143,207, 191,31,141,165,129,191,126,254,251,225,250,247,117,124,178,164, 158,85,124,156,158,239,200,124,53,69,153,175,190,158,254,27, 90,7,0,148,78,141,240,174,1,111,127,5,39,143,143,133, 37,9,111,16,87,2,42,144,8,52,41,38,245,250,56,191, 124,182,148,208,84,39,126,17,252,78,84,44,95,15,90,174, 63,25,187,243,199,119,96,203,228,206,59,15,29,196,173,230, 158,128,230,113,76,78,62,156,110,211,207,175,12,62,58,191, 127,233,117,179,136,58,79,185,230,194,151,11,180,213,191,163, 187,139,207,52,251,76,230,171,119,67,128,21,35,208,186,189, 137,121,244,187,175,207,46,101,243,209,169,15,47,109,58,73, 248,84,10,159,55,77,40,172,76,228,168,105,52,9,70,125, 238,143,250,153,181,61,181,61,81,182,245,163,29,217,232,31, 174,38,134,25,1,177,217,201,36,222,211,45,124,211,200,21, 229,91,0,176,209,137,175,5,31,238,45,30,174,247,157,204, 87,47,110,3,42,245,27,139,51,15,51,143,33,122,247,243, 243,185,123,176,70,187,96,172,17,15,26,223,220,242,114,197, 173,40,68,184,124,89,17,79,132,98,43,125,93,217,37,136, 230,190,54,7,35,247,119,124,186,117,103,116,192,236,83,140, 106,159,221,105,254,129,11,95,53,29,54,124,0,142,108,197, 228,233,69,70,53,209,213,207,201,191,234,141,63,191,116,184, 222,135,50,95,229,182,234,214,247,211,163,149,82,160,42,140, 194,40,108,254,242,25,216,165,199,96,188,53,231,90,102,236, 253,244,224,89,254,35,119,127,151,197,47,199,55,96,63,91, 27,190,100,105,215,142,191,138,250,208,245,93,119,31,250,10, 108,207,225,183,166,46,45,126,195,78,96,90,156,239,64,194, 39,35,253,104,251,220,181,61,31,58,62,214,234,223,173,77, 91,184,126,123,156,233,191,216,168,172,179,1,200,87,2,84, 161,178,243,239,225,73,94,198,82,127,76,244,24,15,197,12, 49,104,239,145,119,134,1,84,153,203,110,225,35,139,15,125, 136,191,186,210,38,219,231,119,207,86,147,11,163,211,35,187, 32,66,0,186,243,193,253,63,149,241,209,185,146,96,238,189, 170,223,195,225,243,60,137,32,166,73,237,247,19,64,229,53, 176,225,71,141,250,161,218,84,127,202,124,245,110,18,176,157, 6,164,155,240,39,188,115,134,57,142,60,100,168,156,244,126, 110,46,202,150,26,57,124,251,237,81,236,183,151,250,201,193, 130,15,133,241,225,1,225,11,173,77,213,185,111,204,193,200, 236,246,43,219,31,153,187,123,239,91,110,124,87,42,149,10, 224,115,59,31,200,238,237,200,228,238,37,240,227,230,211,181, 73,35,242,143,251,69,231,167,119,119,1,86,141,192,36,106, 213,231,144,211,162,37,224,117,100,185,126,110,119,13,61,104, 27,84,96,52,120,10,153,110,47,124,96,180,230,237,248,28, 37,137,142,79,107,194,151,238,15,10,89,117,179,62,209,196, 111,237,156,249,230,29,128,175,128,192,171,68,162,204,168,220, 3,153,119,242,93,248,38,9,169,254,137,110,124,105,39,6, 53,93,64,74,154,223,95,252,92,40,251,25,200,233,191,17, 186,0,10,41,8,221,226,21,255,72,76,44,121,235,179,107, 74,124,186,116,152,93,31,30,172,248,212,21,252,229,145,129, 180,33,182,118,124,244,192,151,250,245,203,224,251,126,63,220, 253,69,79,124,236,2,62,136,248,202,243,145,37,207,46,246, 181,204,87,47,26,0,101,250,3,181,166,148,136,128,21,129, 80,87,23,79,125,118,54,255,91,84,31,94,194,199,46,226, 163,134,47,251,61,197,175,159,88,124,178,94,63,10,81,118, 49,124,100,241,165,189,1,93,50,213,247,251,33,81,221,23, 45,170,2,228,248,252,213,255,213,250,225,124,159,203,124,245, 166,1,80,238,123,235,54,41,78,191,222,207,206,247,115,75, 10,49,54,178,9,206,234,171,250,240,69,240,169,139,248,220, 214,35,121,242,13,216,241,193,202,55,160,78,40,40,136,79, 204,196,67,182,119,194,31,159,119,19,109,248,25,211,154,140, 130,206,143,105,28,108,248,173,231,23,250,94,230,171,247,12, 128,65,10,210,152,50,45,56,40,113,88,62,178,227,203,118, 212,126,48,137,127,73,215,143,151,245,225,125,240,1,248,246, 161,50,248,8,110,125,122,89,192,204,108,143,241,195,55,184, 252,24,124,178,224,203,5,55,100,73,60,234,248,234,10,172, 238,36,216,175,223,100,28,148,175,31,11,224,47,191,158,188, 176,48,0,50,95,189,27,2,180,239,245,253,251,80,207,196, 135,80,141,208,120,21,57,100,244,225,185,104,18,181,215,101, 125,120,242,196,135,117,194,7,107,4,238,210,175,231,215,81, 251,249,73,248,88,2,159,74,226,163,120,253,62,207,135,20, 100,21,197,95,254,59,125,113,254,55,108,205,95,159,201,124, 245,106,18,80,157,109,55,202,232,195,115,205,28,220,67,138, 10,3,32,207,176,103,210,102,119,11,159,12,124,112,226,3, 128,149,34,68,111,117,5,17,95,221,204,196,117,193,151,238, 15,24,247,39,143,159,41,40,18,190,126,126,184,46,248,164, 169,34,1,100,47,221,127,23,76,170,239,62,148,249,234,213, 28,0,41,251,0,55,205,152,15,129,87,144,37,139,62,59, 8,250,240,124,130,76,214,143,95,27,62,177,148,156,100,153, 162,146,126,61,25,52,161,156,126,189,29,31,4,159,198,31, 159,28,248,188,174,46,90,166,40,25,155,118,118,213,94,243, 254,35,203,57,100,122,91,28,62,89,159,15,2,2,122,249, 254,192,200,124,245,114,18,176,125,191,241,166,190,9,163,54, 195,152,189,255,228,208,116,211,163,92,206,76,35,35,23,97, 198,171,221,193,151,94,71,71,237,130,63,62,9,248,192,224, 163,39,62,105,117,132,60,62,151,106,36,145,97,223,134,239, 98,93,32,75,190,128,187,191,252,170,131,46,252,87,230,222, 24,28,153,175,222,205,1,228,22,151,244,22,111,137,1,36, 218,104,16,214,55,20,26,108,253,245,225,121,253,122,98,94, 151,240,209,3,223,69,182,9,202,134,40,143,175,171,226,174, 5,223,22,181,187,238,15,58,175,31,140,61,9,244,254,126, 248,173,77,247,243,193,227,163,27,255,127,230,7,74,230,171, 119,67,128,220,55,144,77,113,83,27,53,194,103,115,109,228, 202,135,192,217,251,239,251,58,42,15,6,24,25,234,50,248, 84,8,31,172,124,7,216,21,124,89,69,177,56,190,253,250, 108,175,23,199,215,205,153,43,219,12,162,249,86,222,123,116, 97,192,100,190,122,57,4,104,135,116,201,180,154,75,71,86, 159,93,143,91,213,88,143,140,141,28,200,169,185,112,26,115, 166,20,136,218,15,46,225,99,1,124,189,102,14,10,225,203, 18,164,101,241,185,215,221,248,252,231,19,35,184,237,251,253, 100,226,249,249,226,115,175,23,127,62,212,112,4,78,204,15, 156,204,87,239,238,2,228,178,58,233,52,64,145,126,110,87, 191,61,177,202,121,100,68,247,232,68,229,243,235,254,248,192, 58,215,190,248,216,117,124,247,245,147,144,77,151,207,71,194, 119,235,56,115,253,252,54,124,240,198,47,117,127,78,205,15, 160,204,87,111,135,0,43,191,239,207,80,134,204,52,33,45, 26,150,133,183,185,76,59,137,50,143,106,5,30,25,143,161, 249,137,174,242,22,23,190,201,103,168,227,155,216,110,124,90, 7,124,208,94,151,106,26,201,3,159,191,63,168,237,201,251, 227,203,185,31,253,252,108,207,7,42,94,66,251,61,167,23, 6,82,230,171,119,147,128,57,79,44,78,96,202,36,216,2, 102,223,26,64,214,135,231,121,116,116,231,25,133,199,36,51, 240,201,89,15,224,143,143,78,124,157,238,194,7,95,237,128, 239,54,62,88,183,250,16,76,50,118,96,75,143,59,59,46, 152,75,195,217,240,129,193,207,88,124,40,128,159,207,91,24, 207,199,185,133,1,149,249,42,51,54,142,20,180,99,232,111, 194,30,169,89,212,159,85,175,72,63,189,234,12,218,244,235, 209,66,61,185,17,248,0,38,119,48,95,150,163,175,112,118, 124,189,253,186,8,62,178,117,144,58,171,158,93,51,65,198, 151,248,30,138,226,251,126,63,112,126,225,95,180,233,111,150, 253,164,195,50,253,55,54,9,8,157,82,32,179,205,195,92, 123,72,41,215,68,230,117,213,181,67,54,75,76,44,161,148, 13,95,127,220,138,225,67,1,124,62,120,1,111,124,180,224, 171,142,23,130,189,227,81,158,52,62,248,122,148,173,174,230, 121,124,206,91,203,152,251,99,226,155,193,136,138,143,6,62, 25,215,15,0,23,107,47,166,3,43,243,213,235,57,128,229, 159,12,38,137,221,29,39,38,99,205,233,191,234,84,145,229, 250,233,65,196,199,130,248,246,126,118,178,224,131,136,79,30, 248,192,230,209,205,130,36,20,170,12,248,140,137,29,159,10, 227,251,240,61,20,227,91,64,79,124,134,111,226,114,237,133, 65,150,249,234,229,16,96,245,25,202,128,178,91,145,33,4, 129,22,125,118,98,20,231,200,145,39,22,72,174,180,90,241, 238,224,115,217,124,95,124,16,36,170,129,117,244,77,124,178, 224,155,247,2,12,55,31,172,45,205,102,93,61,138,180,107, 221,195,215,145,73,235,238,43,141,127,109,105,192,101,190,122, 57,4,200,121,0,201,20,21,210,103,87,31,78,18,40,45, 253,250,233,51,35,202,236,6,62,49,248,102,13,26,135,175, 79,5,18,13,153,138,15,30,248,32,248,15,50,62,228,220, 241,50,124,7,235,137,15,5,249,30,116,124,184,177,244,163, 214,128,203,124,245,174,1,160,246,250,159,65,70,183,212,252, 119,145,126,122,16,242,228,228,217,79,239,215,79,206,225,131, 5,159,227,27,0,246,19,145,21,177,4,225,221,50,62,24, 177,184,44,32,166,230,198,169,192,253,177,241,29,0,243,253, 216,180,143,186,141,239,243,124,228,142,154,110,252,160,53,240, 50,95,189,105,0,72,203,3,100,181,91,32,68,131,182,126, 110,169,2,77,126,228,136,73,117,21,99,199,179,183,1,149, 195,199,18,253,236,124,113,16,177,117,253,126,248,50,223,129, 207,245,219,191,159,140,77,168,114,25,12,110,13,247,233,231, 151,249,22,4,252,187,141,161,144,249,42,51,42,27,130,210, 209,7,64,136,226,116,203,27,81,4,95,134,17,115,227,9, 45,250,240,196,212,148,73,250,240,29,102,125,117,215,220,174, 15,15,214,142,57,59,62,247,94,244,192,71,15,124,46,99, 193,115,249,21,193,199,146,248,224,192,87,4,54,45,42,13, 166,230,178,235,251,41,250,124,172,232,21,220,107,60,221,252, 98,24,100,190,122,213,0,96,206,4,32,68,128,139,179,243, 191,106,253,108,211,84,180,155,30,145,39,17,0,71,192,5, 162,176,133,180,23,142,134,246,139,172,15,239,143,15,78,124, 48,82,103,197,240,213,215,237,248,100,109,120,46,138,207,189, 142,80,68,113,8,152,196,229,218,240,193,137,207,223,31,156, 111,28,106,222,29,14,153,175,222,53,0,168,120,1,17,32, 68,73,178,112,121,254,181,209,115,213,10,140,115,129,136,202, 134,111,235,103,39,102,45,145,213,111,92,175,75,159,234,194, 167,46,226,147,178,198,185,21,16,208,200,66,172,245,250,245, 106,66,249,174,3,251,253,116,15,223,245,253,128,229,249,64, 192,90,124,168,49,195,52,252,196,185,125,255,33,158,254,27, 103,0,58,63,144,251,55,44,221,157,63,155,28,217,116,55, 218,7,95,50,107,192,120,237,60,83,24,202,38,5,198,235, 215,219,30,42,115,141,130,117,198,215,107,224,244,60,248,131, 192,7,54,181,134,160,150,238,218,241,245,215,139,232,32,154, 66,36,18,190,229,251,108,180,14,213,135,72,230,171,151,67, 0,48,38,127,251,91,108,197,11,151,151,38,70,63,196,205, 248,20,34,128,94,183,134,236,250,128,90,132,97,123,164,209, 169,136,167,102,161,121,124,85,151,198,23,95,85,206,67,203, 13,50,203,103,164,137,239,139,79,57,251,219,125,124,178,124, 166,122,126,46,229,64,245,94,201,248,170,70,144,19,63,110, 29,106,220,28,38,153,175,222,78,2,170,197,123,218,38,113, 150,213,102,22,78,103,199,55,205,227,126,120,200,230,18,23, 213,135,71,65,31,222,222,105,224,143,175,103,233,93,248,156, 254,173,27,31,0,140,213,89,207,141,163,55,190,26,46,248, 222,31,27,126,249,239,167,8,62,22,193,79,210,195,245,235, 195,37,243,213,235,187,0,102,253,238,234,179,187,92,127,149, 181,150,22,46,213,38,54,125,92,217,6,79,130,182,42,112, 156,52,182,220,55,128,91,251,92,77,20,202,94,129,11,223, 212,234,117,173,118,220,228,180,225,163,195,35,2,205,57,118, 91,99,240,192,207,155,17,20,20,126,212,251,211,51,248,89, 250,204,210,167,195,38,243,213,203,6,64,158,179,212,41,17, 130,12,50,74,106,183,22,222,132,55,171,141,104,156,70,229, 96,128,44,250,241,54,125,120,119,54,89,231,220,43,142,47, 79,229,181,225,243,202,200,118,124,223,251,99,195,151,66,27, 51,88,42,143,159,79,181,162,32,183,230,141,79,233,115,75, 191,31,62,153,175,222,53,0,160,5,161,168,77,255,182,15, 176,154,149,141,231,23,63,108,30,217,116,29,119,193,46,62, 13,164,243,244,161,152,38,211,35,101,123,226,200,158,45,120, 208,248,80,10,31,149,214,37,151,255,228,131,207,243,36,202, 248,32,224,155,247,7,13,190,3,55,190,62,146,231,235,23, 135,81,230,171,215,13,0,178,146,176,171,235,127,231,247,242, 215,147,166,173,218,103,11,63,175,158,29,201,240,0,85,80, 43,4,49,215,7,50,36,42,77,193,11,176,196,216,62,89, 0,127,124,179,230,174,60,190,46,121,242,160,240,193,195,56, 154,185,124,112,236,222,119,27,63,123,97,233,252,112,202,124, 245,178,1,144,250,119,212,245,223,252,73,27,247,22,222,75, 38,70,167,163,39,113,27,177,43,9,25,250,241,8,224,153, 243,55,87,80,100,50,233,250,202,232,131,111,95,25,55,6, 31,10,224,131,144,115,39,205,122,251,225,99,151,240,201,88, 61,16,36,118,161,149,224,225,197,218,185,97,149,249,234,109, 3,0,2,137,61,57,140,64,10,89,210,172,125,186,116,172, 250,193,200,8,236,55,159,22,190,98,192,93,41,232,126,80, 125,92,118,179,84,104,109,248,100,76,228,110,224,147,67,26, 133,243,117,220,233,188,238,226,171,85,24,182,239,135,15,153, 8,16,232,165,197,179,204,218,63,36,50,95,189,110,0,204, 167,130,216,60,0,107,6,40,171,207,44,156,161,215,71,238, 225,62,24,211,235,210,209,194,234,159,143,51,253,31,107,51, 19,205,125,178,217,207,111,195,7,207,44,185,15,62,176,133, 207,104,205,88,216,107,22,36,124,40,129,47,243,61,216,240, 253,246,110,76,252,182,17,120,121,241,151,195,44,243,213,251, 6,64,215,149,80,141,64,150,203,5,228,18,130,249,159,86, 189,246,81,253,200,200,165,234,195,176,199,116,61,165,181,132, 196,42,52,18,42,218,80,72,172,169,2,147,118,167,216,196, 7,47,124,126,42,112,38,15,45,190,134,63,62,58,253,39, 149,172,131,199,39,131,102,84,151,42,69,33,73,232,131,143, 214,235,95,249,235,149,197,19,195,45,243,213,15,6,0,88, 217,90,61,20,32,205,20,116,204,65,10,25,165,245,169,197, 95,226,201,145,26,140,195,38,105,189,243,105,95,225,42,253, 165,21,202,116,140,109,61,115,54,163,227,194,183,191,211,21, 225,151,197,151,82,138,190,248,168,25,68,27,190,79,123,149, 185,225,199,221,255,220,185,188,90,63,74,67,46,243,213,31, 6,64,95,88,242,1,129,110,10,44,121,129,120,177,118,33, 62,82,253,52,218,137,143,233,143,189,43,194,213,59,208,208, 242,232,185,246,239,185,105,247,32,241,193,146,86,147,206,15, 153,181,22,157,237,209,27,131,15,30,247,23,129,142,54,94, 77,91,195,46,243,213,111,6,0,89,63,0,114,172,108,170, 17,72,117,131,144,38,245,207,107,39,43,167,43,73,101,124, 153,221,208,167,223,31,11,244,147,131,163,138,190,88,63,187, 137,15,37,241,201,64,244,235,156,115,5,14,114,77,31,106, 57,252,242,248,80,8,95,186,191,202,241,39,26,63,203,201, 124,53,135,85,230,171,223,12,128,110,4,244,128,32,211,140, 0,113,158,0,100,205,185,218,111,226,35,35,147,209,19,176, 67,94,109,125,28,78,233,117,158,175,158,231,27,176,225,115, 70,130,74,241,13,232,248,32,184,238,28,190,107,5,183,9, 152,75,124,11,221,199,71,35,207,47,142,83,245,255,82,100, 190,226,97,149,249,234,71,3,192,5,4,164,165,6,237,70, 32,131,20,178,52,94,186,218,56,94,121,175,90,129,3,203, 236,2,82,111,25,26,92,183,124,63,187,45,114,5,111,71, 31,156,248,60,223,128,187,147,222,117,150,190,189,125,18,223, 129,57,101,125,240,169,20,62,10,91,159,94,94,197,233,250, 127,164,205,92,234,111,136,101,190,250,219,0,152,130,125,121, 67,144,89,115,2,203,93,4,89,227,110,237,157,236,88,245, 110,180,143,30,246,239,39,247,235,103,183,9,88,19,112,60, 182,254,248,224,129,15,78,63,163,108,63,61,26,95,128,116, 127,138,225,3,64,193,251,79,214,140,49,119,124,116,174,254, 82,78,231,103,213,8,12,169,204,87,127,27,0,62,57,168, 87,10,216,54,10,83,200,32,75,26,75,191,111,28,29,185, 80,221,66,251,204,143,229,54,14,221,253,236,114,236,170,171, 210,32,211,162,34,225,83,33,124,123,46,31,161,27,253,244, 164,197,224,190,248,190,189,154,242,253,55,191,13,244,201,100, 156,175,255,51,35,243,213,26,86,153,175,65,49,0,200,78, 126,18,58,7,152,128,128,146,198,116,237,109,56,49,178,128, 251,97,51,31,183,250,244,179,163,48,37,245,13,71,91,116, 15,32,225,155,204,62,62,248,234,62,251,90,42,237,77,124, 219,166,164,15,223,0,88,119,51,80,216,116,117,237,134,72, 247,7,47,54,126,154,46,5,153,175,193,51,0,188,47,224, 191,81,184,226,23,180,106,75,191,107,76,140,94,169,236,128, 199,237,69,191,82,238,27,69,103,180,88,145,174,84,212,138, 78,124,213,65,55,249,14,186,131,15,90,237,4,191,234,150, 229,91,64,175,251,91,236,120,4,188,92,255,73,26,100,190, 6,220,0,240,190,128,180,81,152,42,33,66,10,25,100,212, 170,223,172,189,81,121,171,218,196,241,14,13,185,182,146,8, 89,127,46,15,224,179,31,111,235,103,231,222,105,39,22,247, 193,183,179,40,162,152,85,0,75,126,94,223,121,135,194,248, 28,159,130,31,165,139,171,223,31,129,174,197,63,78,106,65, 230,171,123,83,172,247,207,17,53,122,241,21,149,129,220,79, 5,42,43,191,151,127,170,249,223,163,91,190,244,173,232,219, 244,85,4,189,97,216,116,143,37,231,211,30,171,231,39,183, 172,21,92,14,223,69,167,169,198,217,196,132,25,27,133,207, 243,5,20,61,222,129,127,35,126,54,167,243,147,119,255,135, 92,231,103,208,60,0,213,8,152,181,2,192,214,11,176,1, 65,26,215,175,47,157,168,190,91,1,24,199,200,213,79,79, 138,3,74,150,21,220,22,101,115,185,114,190,159,159,186,134, 207,217,78,91,77,159,63,62,9,245,16,62,159,111,183,237, 124,107,145,168,154,48,21,63,219,186,31,100,190,134,203,0, 152,1,129,158,21,200,216,202,65,45,60,104,126,177,244,235, 100,98,244,54,238,129,173,102,38,91,239,103,71,199,137,216, 218,127,165,126,118,48,242,236,157,10,56,87,63,253,250,227, 251,87,251,3,248,245,235,187,246,4,120,190,1,139,98,192, 221,248,251,173,123,130,204,87,107,184,101,190,6,221,0,240, 201,193,34,69,67,41,100,144,165,141,250,39,205,163,213,223, 86,54,193,83,128,82,63,59,0,88,51,1,114,191,30,42, 194,100,146,211,139,70,170,203,165,88,176,62,248,84,10,223, 191,95,159,247,130,208,72,101,34,43,131,110,76,255,217,230, 211,45,89,230,43,29,118,157,159,97,49,0,254,69,67,66, 225,16,165,205,219,75,103,178,227,213,185,232,41,218,194,245, 179,155,106,124,18,159,0,89,187,237,101,167,215,54,253,125, 249,14,214,142,15,98,90,207,228,19,144,249,20,208,146,235, 32,99,109,71,241,250,209,154,33,192,249,214,161,56,200,124, 5,3,32,248,2,92,99,177,26,18,168,193,65,154,44,213, 47,53,39,70,62,142,114,52,228,8,102,65,171,220,90,236, 226,27,48,179,228,224,217,201,175,23,235,242,147,172,24,223, 65,113,124,123,191,62,122,156,185,121,188,233,1,200,198,74, 57,147,90,114,168,25,100,190,214,105,45,237,239,243,207,83, 202,174,238,15,168,59,4,250,30,65,85,253,189,101,247,230, 191,195,127,128,49,61,239,92,164,204,133,44,239,115,201,141, 129,97,118,124,156,114,0,63,194,79,155,84,7,199,96,204, 37,24,221,228,231,100,33,240,38,145,56,204,125,127,87,238, 74,163,245,221,120,82,140,253,131,208,199,144,122,0,114,94, 64,237,40,228,247,8,218,36,35,173,249,250,135,241,107,163, 215,225,17,124,84,173,129,35,102,31,221,79,98,140,172,73, 59,83,116,155,175,193,83,215,212,181,225,115,83,203,175,223, 222,110,176,212,21,91,230,59,176,19,143,168,166,71,75,73, 198,201,161,56,200,124,5,3,224,153,23,40,182,81,184,202, 58,152,52,62,171,159,172,156,137,50,28,239,220,23,4,153, 1,208,108,20,6,0,7,93,87,254,177,207,63,232,82,109, 159,29,159,159,138,118,124,61,174,55,251,237,253,206,95,55, 31,58,65,39,0,56,85,9,129,201,53,48,124,0,73,118, 184,25,100,190,130,1,40,156,28,180,177,11,176,156,131,144, 198,247,26,239,165,19,213,41,220,77,219,196,157,104,109,181, 197,194,253,252,38,217,6,151,47,176,227,23,229,59,48,249, 4,220,215,103,207,103,216,240,209,43,69,232,117,124,150,61, 211,8,50,95,193,0,148,12,8,252,217,5,218,1,65,218, 108,124,26,31,171,252,166,194,210,144,131,230,64,251,147,102, 169,253,112,62,93,255,224,48,37,190,248,122,202,205,29,72, 184,146,46,38,190,47,137,24,40,137,85,20,248,24,218,231, 71,217,115,141,32,243,21,12,192,26,125,129,162,236,2,41, 101,241,157,250,89,124,189,58,11,79,193,152,58,149,243,174, 43,89,146,97,46,190,1,0,147,109,151,60,18,98,249,64, 131,44,161,0,151,125,183,241,5,216,206,95,191,94,147,109, 24,29,30,131,148,16,117,220,159,231,27,65,230,43,24,128, 46,37,7,193,232,37,116,208,144,39,245,198,199,173,35,35, 151,162,49,216,235,203,113,99,239,119,215,167,116,71,185,79, 158,4,186,160,120,25,124,116,242,5,152,81,57,122,241,29, 184,171,22,245,243,55,123,2,69,95,231,133,122,144,249,10, 6,160,139,190,128,63,187,64,142,134,188,57,85,127,11,78, 86,23,163,113,218,36,217,24,96,250,229,213,215,249,85,85, 95,147,77,62,0,95,190,1,117,159,95,250,124,159,85,154, 20,115,193,29,47,155,31,50,116,19,184,162,31,254,147,140, 50,167,23,235,54,153,175,176,250,7,3,208,37,95,192,131, 134,60,89,108,92,136,143,140,124,18,237,132,199,204,36,32, 90,57,113,76,178,45,159,21,19,28,82,99,246,126,121,112, 36,226,244,51,178,243,13,32,248,234,25,153,231,95,166,83, 0,0,128,94,106,216,101,190,210,32,243,21,12,64,89,95, 160,20,13,57,37,205,27,141,147,209,233,74,139,14,66,149, 171,16,52,203,106,200,163,132,6,180,210,31,255,158,4,177, 95,30,236,169,203,34,253,254,110,81,113,189,204,71,13,15, 208,233,129,152,249,1,2,124,185,30,100,190,54,112,82,12, 215,245,234,149,131,38,187,64,165,253,15,207,46,48,246,208, 95,225,119,104,92,126,140,245,137,109,55,19,0,96,173,59, 44,246,249,69,142,71,177,13,24,188,205,136,249,249,246,240, 197,227,248,87,234,175,67,12,173,246,218,223,89,255,121,157, 159,48,253,131,7,80,58,32,144,54,10,45,187,4,105,220, 188,218,58,30,189,23,69,112,0,34,142,245,206,180,176,92, 46,220,62,209,212,64,195,187,95,222,178,78,115,220,197,174, 64,195,118,254,82,148,15,206,235,231,178,24,237,223,175,198, 69,101,190,194,8,6,96,77,201,65,190,118,208,66,60,10, 25,101,173,187,205,119,233,88,245,14,238,131,135,81,236,167, 231,248,6,124,166,155,173,223,30,189,236,155,158,187,183,241, 29,200,249,2,219,249,251,240,1,240,87,109,185,190,163,113, 144,249,10,6,224,1,37,7,57,193,114,43,13,121,218,104, 94,78,142,85,46,224,67,240,148,100,105,248,54,24,126,149, 54,251,237,249,13,55,55,81,55,87,158,107,235,231,147,45, 37,215,208,83,228,120,251,245,105,198,228,68,28,100,190,130, 1,120,128,190,64,41,26,242,214,116,243,109,60,81,153,199, 3,176,89,118,218,193,193,128,135,204,218,174,215,234,219,142, 231,214,87,27,190,59,87,160,135,54,107,225,3,224,143,87, 247,27,162,83,205,32,243,21,12,64,79,248,2,133,105,200, 147,90,243,98,50,81,189,28,237,160,39,208,144,203,230,167, 7,223,47,175,151,237,218,214,102,185,223,222,63,224,224,249, 2,212,98,93,40,204,7,80,226,250,78,55,131,204,87,48, 0,61,231,11,20,162,33,143,39,155,191,136,222,170,52,232, 160,74,67,46,113,236,115,165,59,254,107,180,237,120,155,36, 39,175,125,164,214,249,73,157,6,104,53,70,42,118,161,235, 59,23,7,153,175,96,0,122,200,23,176,119,20,230,119,11, 244,2,226,251,205,223,166,71,42,159,69,143,193,35,84,170, 223,222,205,71,224,219,111,239,99,58,138,157,31,49,77,208, 126,199,219,248,0,240,124,28,100,190,130,1,232,41,95,96, 77,52,228,20,183,174,55,79,84,222,169,0,140,83,36,247, 219,23,237,151,39,197,41,215,143,247,217,198,99,250,237,189, 76,8,31,82,152,199,243,124,8,246,235,139,46,54,131,204, 87,48,0,61,29,16,232,89,1,47,26,242,100,54,62,7, 19,149,219,176,7,182,250,113,231,119,163,223,94,74,199,153, 230,167,24,31,128,141,79,192,214,154,204,139,141,229,142,191, 28,7,153,175,96,0,250,36,57,88,130,134,60,254,36,61, 26,157,175,108,162,253,128,174,78,124,212,98,104,103,191,188, 199,122,111,238,225,163,209,91,232,54,38,246,227,73,51,18, 62,86,117,217,131,161,107,241,143,179,32,243,21,12,64,31, 249,2,37,104,200,147,153,248,12,28,143,230,240,41,216,2, 236,138,95,178,95,94,224,15,228,142,39,75,174,65,63,30, 64,230,3,40,194,228,47,95,223,202,255,191,145,62,151,46, 48,177,191,94,244,27,166,127,48,0,61,230,11,128,163,90, 192,160,33,79,151,90,151,210,137,202,71,209,86,218,109,118, 207,149,233,151,87,211,105,230,122,207,127,154,59,198,215,181, 6,202,242,1,144,227,250,112,42,9,50,95,193,0,244,173, 47,64,90,31,1,41,59,3,196,81,140,80,210,186,21,159, 170,188,137,75,112,16,71,1,124,251,237,229,181,95,173,174, 179,243,13,128,37,26,47,194,7,96,95,229,85,146,79,149, 67,40,255,73,209,221,36,200,124,5,3,48,32,121,129,66, 52,228,201,124,235,66,246,90,245,26,238,162,71,203,246,203, 219,248,0,220,107,51,199,0,64,74,155,164,36,66,134,236, 10,159,127,93,226,3,80,67,25,156,77,130,204,87,48,0, 3,225,11,148,164,33,111,125,22,159,140,206,84,82,88,161, 33,119,175,176,190,124,0,126,94,195,90,248,0,212,157,127, 52,132,201,157,225,203,124,122,168,21,100,190,130,1,24,168, 228,96,9,26,242,244,94,252,126,54,81,189,133,187,97,27, 239,156,235,245,125,166,123,95,196,111,80,85,1,242,66,28, 96,108,14,218,204,8,50,231,103,59,94,243,27,106,201,161, 36,200,124,5,3,48,128,1,65,9,26,114,106,182,174,166, 199,224,253,168,10,7,0,249,126,123,185,6,192,221,207,175, 211,124,20,231,3,176,237,85,128,245,120,174,166,17,27,217, 161,214,20,27,251,39,108,213,127,152,254,193,0,244,153,47, 80,130,134,60,189,211,58,139,175,71,95,68,109,26,114,87, 191,189,175,64,24,26,107,180,127,221,96,94,87,192,135,15, 64,78,54,182,143,143,179,32,243,21,12,192,80,36,7,139, 208,144,47,23,13,213,91,31,167,71,240,98,101,12,246,250, 17,127,232,171,116,103,71,192,135,15,64,158,248,104,164,26, 57,101,35,95,62,128,92,166,32,161,195,113,144,249,10,6, 96,72,124,129,50,236,2,105,50,29,191,5,39,163,5,108, 211,144,163,241,225,156,24,183,158,189,47,195,7,192,5,29, 88,56,219,64,140,230,31,0,2,102,244,76,28,100,190,130, 1,24,114,95,192,131,134,60,91,76,126,151,77,84,63,193, 157,248,152,188,74,251,242,1,160,115,162,114,20,32,122,89, 114,145,41,207,242,1,16,61,23,7,153,175,96,0,134,208, 23,40,73,67,222,186,209,58,25,189,29,197,112,16,170,110, 62,1,44,192,7,0,138,177,128,146,199,155,159,148,47,72, 210,253,15,122,62,14,50,95,193,0,12,117,114,208,182,81, 72,220,14,1,100,233,92,235,131,236,72,229,38,62,9,59, 138,243,1,144,67,150,12,60,250,249,165,227,11,242,1,188, 16,7,153,175,96,0,66,64,80,134,134,156,226,228,106,118, 28,207,69,8,227,24,201,124,0,114,10,174,40,31,128,61, 61,168,210,130,18,200,124,7,237,241,98,51,200,124,5,3, 16,124,129,181,208,144,167,119,91,239,102,199,170,51,176,15, 30,230,74,111,205,9,235,195,39,208,29,62,0,253,93,218, 165,255,107,243,76,144,249,10,6,32,12,61,57,200,209,144, 235,20,35,170,25,168,183,174,100,71,43,31,194,102,120,202, 167,15,143,231,232,241,119,244,117,11,166,31,175,115,253,177, 130,233,47,199,167,130,204,87,48,0,97,112,190,64,209,141, 194,101,118,129,233,228,116,244,127,209,10,13,57,23,149,251, 241,1,112,147,222,118,188,174,53,236,83,133,24,189,210,60, 177,178,222,235,177,191,89,245,23,166,127,48,0,67,234,11, 20,165,33,79,211,165,214,197,108,34,186,28,109,135,39,242, 73,61,27,31,64,81,206,192,188,250,177,196,7,96,251,44, 2,124,53,9,50,95,193,0,132,81,192,23,48,55,10,51, 134,134,124,217,23,104,37,147,173,95,224,47,177,1,7,113, 132,39,225,150,250,249,77,62,1,0,23,159,128,63,31,192, 138,185,152,72,130,204,87,48,0,97,120,249,2,242,70,33, 217,105,200,179,251,201,111,233,72,116,29,30,199,71,252,249, 0,108,124,2,190,133,190,38,159,64,190,219,0,79,36,65, 230,43,24,128,48,60,125,129,53,210,144,39,215,147,19,149, 119,34,162,131,24,217,38,44,177,27,129,249,21,94,230,3, 48,27,149,77,134,130,246,127,157,74,130,204,87,48,0,97, 148,12,8,244,172,128,15,13,121,154,206,38,231,104,2,167, 163,189,176,85,157,176,29,16,84,250,249,245,44,1,56,252, 7,23,159,192,106,182,32,58,157,252,123,26,7,153,175,96, 0,194,40,23,16,148,161,33,95,246,5,26,233,39,116,52, 58,143,163,176,31,81,141,242,185,54,161,34,124,0,58,159, 128,152,37,56,151,188,148,54,131,204,87,48,0,97,116,195, 23,240,167,33,79,219,236,2,51,201,217,232,56,220,195,253, 180,37,191,50,235,220,2,174,248,62,159,37,48,165,199,77, 15,2,1,0,207,167,65,230,43,24,128,48,186,236,11,128, 99,139,80,111,38,74,211,165,244,35,154,192,75,184,21,118, 251,177,248,235,132,224,28,159,128,147,15,224,98,26,100,190, 130,1,8,99,29,124,1,158,134,220,218,73,64,73,58,149, 156,138,222,140,106,112,16,70,209,58,229,59,128,106,115,176, 155,125,48,183,243,112,57,13,50,95,193,0,132,177,238,121, 129,66,52,228,217,124,114,1,94,195,171,176,11,30,213,39, 63,178,124,0,249,98,98,159,52,225,138,25,185,150,4,153, 175,96,0,194,88,103,95,160,36,13,121,250,121,250,243,232, 12,38,112,16,42,118,62,1,157,100,196,231,244,8,162,27, 201,115,89,144,249,10,6,32,140,13,9,8,120,95,192,78, 67,158,101,115,233,251,48,17,77,70,187,105,187,225,190,23, 144,251,98,104,191,166,146,103,179,32,243,21,12,64,24,27, 26,16,148,162,33,79,175,210,49,124,63,170,226,1,196,60, 91,96,145,94,1,77,5,224,78,242,253,44,200,124,5,3, 16,198,3,241,5,74,208,144,103,119,210,179,240,122,116,55, 218,191,74,67,110,155,246,0,86,62,128,217,228,112,22,100, 190,130,1,8,227,1,250,2,106,72,224,69,67,78,245,244, 247,116,4,47,194,24,236,149,215,123,48,124,4,141,79,96, 30,14,165,65,230,43,24,128,48,30,184,47,80,138,134,60, 157,78,223,138,78,226,60,141,227,166,162,124,0,0,80,163, 67,201,109,145,234,59,200,124,5,3,16,198,3,246,5,188, 104,200,211,223,225,68,116,5,118,194,227,58,159,0,42,202, 132,249,112,0,0,26,244,189,228,150,65,247,17,100,190,130, 1,8,227,1,250,2,190,52,228,122,209,208,141,244,141,202, 219,216,196,131,84,245,226,19,136,233,123,201,205,149,245,190, 25,100,190,250,247,161,9,99,144,190,207,124,107,222,234,79, 4,8,81,251,167,210,254,103,245,167,154,255,93,25,171,252, 37,252,35,140,59,102,107,66,223,75,62,133,196,104,249,137, 195,244,15,30,64,24,189,18,16,148,162,33,79,175,193,113, 60,135,0,227,16,241,31,143,25,61,157,92,89,153,238,171, 211,191,21,100,190,130,7,16,70,47,251,2,145,230,13,116, 252,128,104,101,253,95,245,4,170,80,129,74,101,123,244,215, 248,29,122,2,116,231,159,232,112,114,1,146,21,103,223,76, 253,5,153,175,224,1,132,209,99,190,0,104,173,68,153,43, 53,8,25,213,179,43,48,1,31,226,102,218,159,39,1,129, 31,36,239,231,166,126,75,216,248,11,211,63,120,0,97,244, 180,47,176,252,187,162,121,3,102,94,160,82,121,52,250,91, 248,54,108,39,64,192,31,198,191,130,20,82,72,218,62,64, 43,87,244,27,100,190,130,1,8,163,135,205,128,156,28,52, 141,192,170,9,136,160,2,81,101,20,255,12,191,67,167,146, 215,129,32,107,27,128,68,97,250,213,119,254,195,244,15,6, 32,140,30,246,5,162,149,223,170,25,224,12,65,212,46,10, 160,21,3,144,55,1,171,147,63,9,58,63,193,0,132,209, 251,102,192,190,81,168,250,2,171,65,66,100,24,128,180,45, 238,157,172,252,87,152,254,193,0,132,209,87,1,1,8,59, 4,29,35,176,252,55,106,6,32,107,111,246,173,54,252,228, 197,75,194,244,15,6,32,140,190,11,8,48,151,26,236,24, 129,40,183,254,175,110,6,100,138,9,200,152,233,31,162,255, 96,0,194,232,67,95,32,98,67,130,168,109,32,32,231,3, 100,109,146,207,44,76,255,96,0,194,24,36,95,32,210,54, 11,49,199,16,14,44,45,57,133,233,31,12,64,24,131,224, 11,232,233,193,78,252,223,241,0,72,227,31,162,118,234,47, 76,255,96,0,194,24,168,188,0,42,1,128,106,2,200,168, 248,15,211,63,24,128,48,6,200,23,128,220,191,59,6,192, 212,42,8,211,63,24,128,48,6,212,23,0,198,0,128,49, 249,195,244,15,6,32,140,1,123,58,16,100,218,96,117,213, 15,147,63,24,128,48,6,216,12,116,254,34,205,8,132,233, 31,12,64,24,67,251,164,132,169,31,70,24,97,132,17,70, 24,97,132,17,70,24,97,132,17,70,24,97,132,17,70,24, 97,132,17,70,24,97,132,17,70,24,97,132,17,70,24,97, 132,17,70,24,97,132,17,70,24,97,132,17,70,24,97,132, 17,70,24,97,132,17,70,24,97,132,177,158,227,255,1,240, 190,117,10,245,58,9,76,0,0,0,0,73,69,78,68,174, 66,96,130, }; /* label-md.png */ static unsigned char label_md_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,0,128,0,0,0,128,8,4,0,0,0,105,55,169, 64,0,0,4,25,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,187,115,103,35, 36,206,83,108,52,133,116,168,63,13,37,13,147,86,52,161, 180,186,127,221,221,54,110,150,73,54,218,34,232,100,246,238, 206,152,201,206,56,51,187,253,161,79,69,80,124,49,234,155, 20,196,191,183,128,32,40,245,15,219,62,180,47,149,10,37, 218,212,32,40,62,180,248,131,80,232,139,166,235,153,59,51, 153,105,186,177,222,101,238,124,243,157,239,158,123,238,185,103, 239,5,232,185,170,88,150,145,20,1,22,154,174,45,23,50, 226,115,135,143,136,61,43,144,132,135,160,23,6,161,87,81, 29,43,93,169,76,2,54,79,11,119,181,91,223,67,194,123, 95,217,213,221,254,159,173,183,70,29,21,32,113,31,98,179, 230,168,11,136,143,1,240,167,85,203,118,1,122,250,145,31, 63,234,90,30,246,98,232,183,49,64,196,47,122,184,225,99, 215,195,115,62,126,141,105,102,228,44,226,211,136,5,85,83, 106,136,151,16,143,204,197,248,70,12,251,49,176,214,95,160, 77,106,235,170,232,229,162,98,155,117,221,160,177,112,239,97, 254,159,109,193,104,133,243,109,195,167,207,153,159,62,132,239, 97,92,251,43,53,37,231,225,81,196,75,170,146,159,70,252, 8,226,107,109,125,182,28,224,219,150,155,145,17,63,6,144, 220,222,154,175,166,17,239,68,92,172,219,7,170,190,159,164, 173,181,138,33,126,231,132,54,243,44,226,45,136,207,55,231, 202,83,193,216,171,170,147,197,156,193,118,196,183,53,90,242, 242,59,4,192,137,186,91,154,241,199,114,251,109,83,158,242, 231,229,234,53,154,203,123,121,68,252,250,188,121,72,246,125, 114,159,57,237,233,124,232,243,132,150,45,7,252,165,151,148, 131,21,196,131,136,127,161,70,65,246,231,226,254,177,220,74, 16,3,25,106,26,229,73,127,46,146,163,14,91,47,227,93, 109,166,232,207,75,12,23,55,212,31,75,22,235,250,129,82, 160,255,68,179,139,114,128,175,89,6,171,81,140,141,79,218, 45,185,234,235,249,81,197,206,23,124,159,124,133,54,171,129, 127,190,13,179,9,5,40,152,48,135,189,10,77,88,3,17, 100,40,64,6,223,22,216,104,169,131,14,6,50,20,173,20, 25,138,95,161,102,23,27,231,192,60,242,58,180,153,205,193, 190,194,148,254,200,200,95,131,249,184,206,180,42,100,135,62, 130,22,178,26,252,142,172,22,211,101,241,171,133,92,99,19, 63,126,44,55,2,63,38,25,32,18,217,131,207,94,50,73, 246,145,113,50,1,34,121,138,60,77,246,147,28,178,19,100, 239,250,216,74,108,69,94,60,55,214,253,188,140,51,82,166, 155,69,221,57,180,187,160,96,255,51,42,76,92,83,215,172, 44,14,182,134,35,203,41,251,5,93,189,252,198,95,177,92, 233,44,55,81,182,226,25,157,186,87,206,249,95,249,235,252, 50,246,43,252,106,164,224,127,228,87,241,183,114,199,90,204, 187,178,76,195,236,108,88,115,119,85,26,109,6,227,22,240, 209,153,197,137,197,29,243,113,241,228,87,15,70,126,150,201, 153,231,175,244,93,60,89,111,46,14,70,172,151,5,250,106, 249,86,25,78,141,68,172,244,131,244,135,180,44,189,39,125, 40,253,198,189,205,125,202,125,205,125,206,125,193,93,2,145, 59,203,157,227,190,225,46,112,31,115,95,198,246,106,243,26, 90,223,123,22,121,24,183,103,233,150,107,172,74,33,35,108, 21,30,22,114,194,54,225,81,97,50,242,39,12,8,99,66, 81,216,129,150,173,235,251,22,159,47,158,61,29,14,99,31, 230,167,251,92,190,46,86,1,137,251,177,2,244,77,254,85, 85,84,233,112,148,41,29,86,111,77,56,190,65,19,140,36, 67,100,140,148,54,84,247,184,87,243,161,34,149,79,229,82, 105,16,83,59,83,19,169,177,212,65,15,135,179,166,118,160, 109,2,251,252,29,213,169,110,178,82,234,210,99,222,125,2, 89,211,58,110,235,13,205,21,119,75,210,147,98,26,175,54, 42,150,154,234,232,136,168,24,134,200,76,142,104,83,135,218, 109,90,27,5,239,222,244,143,244,155,50,187,15,19,91,46, 71,156,251,12,192,190,63,241,236,251,46,226,142,180,0,150, 28,128,129,199,35,110,24,207,202,7,222,5,56,243,132,218, 178,219,193,29,145,72,124,11,224,212,247,236,246,191,250,50, 120,126,253,212,233,220,196,115,172,231,45,128,181,55,59,157, 191,223,239,116,214,62,64,255,171,0,103,141,127,1,160,159, 124,85,3,92,11,239,0,0,0,56,101,88,73,102,77,77, 0,42,0,0,0,8,0,1,135,105,0,4,0,0,0,1, 0,0,0,26,0,0,0,0,0,2,160,2,0,4,0,0, 0,1,0,0,0,128,160,3,0,4,0,0,0,1,0,0, 0,128,0,0,0,0,107,70,38,77,0,0,3,99,105,84, 88,116,88,77,76,58,99,111,109,46,97,100,111,98,101,46, 120,109,112,0,0,0,0,0,60,120,58,120,109,112,109,101, 116,97,32,120,109,108,110,115,58,120,61,34,97,100,111,98, 101,58,110,115,58,109,101,116,97,47,34,32,120,58,120,109, 112,116,107,61,34,88,77,80,32,67,111,114,101,32,53,46, 52,46,48,34,62,10,32,32,32,60,114,100,102,58,82,68, 70,32,120,109,108,110,115,58,114,100,102,61,34,104,116,116, 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49, 57,57,57,47,48,50,47,50,50,45,114,100,102,45,115,121, 110,116,97,120,45,110,115,35,34,62,10,32,32,32,32,32, 32,60,114,100,102,58,68,101,115,99,114,105,112,116,105,111, 110,32,114,100,102,58,97,98,111,117,116,61,34,34,10,32, 32,32,32,32,32,32,32,32,32,32,32,120,109,108,110,115, 58,100,99,61,34,104,116,116,112,58,47,47,112,117,114,108, 46,111,114,103,47,100,99,47,101,108,101,109,101,110,116,115, 47,49,46,49,47,34,10,32,32,32,32,32,32,32,32,32, 32,32,32,120,109,108,110,115,58,73,112,116,99,52,120,109, 112,69,120,116,61,34,104,116,116,112,58,47,47,105,112,116, 99,46,111,114,103,47,115,116,100,47,73,112,116,99,52,120, 109,112,69,120,116,47,50,48,48,56,45,48,50,45,50,57, 47,34,10,32,32,32,32,32,32,32,32,32,32,32,32,120, 109,108,110,115,58,112,104,111,116,111,115,104,111,112,61,34, 104,116,116,112,58,47,47,110,115,46,97,100,111,98,101,46, 99,111,109,47,112,104,111,116,111,115,104,111,112,47,49,46, 48,47,34,62,10,32,32,32,32,32,32,32,32,32,60,100, 99,58,99,114,101,97,116,111,114,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,62,77,105,99,104,97,101,108,32, 83,119,101,101,116,60,47,114,100,102,58,108,105,62,10,32, 32,32,32,32,32,32,32,32,32,32,32,60,47,114,100,102, 58,83,101,113,62,10,32,32,32,32,32,32,32,32,32,60, 47,100,99,58,99,114,101,97,116,111,114,62,10,32,32,32, 32,32,32,32,32,32,60,100,99,58,114,105,103,104,116,115, 62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114, 100,102,58,65,108,116,62,10,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,108,105,32,120, 109,108,58,108,97,110,103,61,34,120,45,100,101,102,97,117, 108,116,34,62,67,111,112,121,114,105,103,104,116,32,50,48, 49,57,32,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,114, 105,103,104,116,115,62,10,32,32,32,32,32,32,32,32,32, 60,73,112,116,99,52,120,109,112,69,120,116,58,72,101,97, 100,108,105,110,101,62,78,101,119,32,73,99,111,110,60,47, 73,112,116,99,52,120,109,112,69,120,116,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 112,104,111,116,111,115,104,111,112,58,72,101,97,100,108,105, 110,101,62,78,101,119,32,73,99,111,110,60,47,112,104,111, 116,111,115,104,111,112,58,72,101,97,100,108,105,110,101,62, 10,32,32,32,32,32,32,60,47,114,100,102,58,68,101,115, 99,114,105,112,116,105,111,110,62,10,32,32,32,60,47,114, 100,102,58,82,68,70,62,10,60,47,120,58,120,109,112,109, 101,116,97,62,10,221,242,56,27,0,0,21,107,73,68,65, 84,120,218,237,93,9,116,83,215,153,190,88,150,100,73,239, 73,178,44,91,222,100,89,146,45,25,99,27,140,177,241,138, 9,73,147,144,182,89,200,116,154,134,66,104,39,91,83,90, 38,33,13,157,38,109,40,217,90,114,210,180,205,100,50,39, 211,54,237,180,51,157,78,50,233,153,78,82,206,36,167,211, 14,167,7,3,3,33,33,11,148,132,18,6,74,10,12,1, 18,54,227,229,206,127,223,114,223,189,239,93,201,218,76,216, 222,61,54,70,207,177,248,190,255,255,191,127,185,247,57,8, 93,188,46,94,23,175,139,215,197,235,12,95,83,80,145,178, 166,92,168,224,29,200,133,60,200,141,74,144,29,217,224,149, 11,138,8,27,42,145,159,150,183,203,223,113,207,119,87,163, 50,228,5,50,28,240,234,5,226,15,54,228,242,126,83,198, 218,218,39,255,80,186,161,36,130,130,200,7,254,224,64,197, 231,59,13,69,96,253,175,73,88,82,224,235,127,122,143,202, 207,201,183,58,147,168,2,249,33,48,156,231,47,13,4,254, 93,212,250,218,146,180,15,121,88,122,73,190,219,51,3,133, 80,41,146,168,58,156,95,240,189,75,229,113,137,194,214,63, 115,107,92,94,239,93,85,50,128,42,81,0,201,231,147,72, 2,124,233,54,29,62,79,129,144,146,109,210,227,238,171,206, 31,145,36,206,127,179,60,38,115,32,205,100,152,255,38,105, 34,233,170,59,215,69,178,8,57,229,37,210,168,25,186,36, 214,2,203,125,239,145,115,91,36,1,190,103,145,60,154,206, 218,146,192,254,150,251,195,222,115,82,36,1,190,119,161,52, 162,39,61,54,242,121,21,200,240,254,152,119,189,180,210,213, 171,136,228,57,64,3,129,127,163,60,34,11,99,60,213,202, 232,254,27,242,163,158,43,80,21,136,164,124,246,138,36,113, 254,207,200,167,101,220,137,95,198,219,241,183,113,143,37,226, 83,169,66,102,247,189,187,165,167,164,5,174,48,136,164,154, 43,206,42,117,80,173,127,58,136,191,139,71,177,126,253,17, 63,142,231,9,108,42,165,181,255,4,247,15,72,63,243,44, 46,137,162,242,179,41,87,40,240,165,211,157,96,121,235,245, 39,252,20,190,18,251,184,184,183,214,4,114,86,247,189,31, 74,191,148,110,87,114,133,239,163,207,21,196,249,23,202,35, 11,241,49,10,186,21,47,192,207,226,19,12,13,7,241,51, 248,90,92,154,34,202,165,9,84,32,197,253,83,222,53,158, 101,142,150,143,54,101,18,235,47,146,71,238,194,227,12,220, 35,248,71,248,99,216,143,23,225,95,227,17,230,245,195,248, 159,240,167,113,80,104,95,217,146,25,50,188,63,34,255,86, 94,225,110,231,82,230,25,35,130,84,125,75,228,209,251,176, 232,218,143,159,192,189,184,28,223,142,255,155,163,231,67,252, 111,120,49,174,76,19,235,82,218,234,81,120,127,28,82,230, 55,92,221,76,95,81,116,102,224,255,149,60,186,148,1,215, 2,241,254,119,120,15,243,202,187,248,91,120,58,174,197,203, 241,38,142,158,147,248,5,124,11,188,158,190,66,148,179,188, 239,221,226,121,88,126,196,85,3,36,56,38,219,11,8,252, 91,165,177,107,24,221,199,248,3,136,253,69,224,228,51,241, 74,252,10,243,250,91,248,235,184,17,214,55,240,54,142,134, 211,144,52,151,226,250,148,218,111,158,39,100,118,223,181,0, 213,64,56,216,38,187,227,187,67,30,107,193,135,4,210,55, 10,78,191,28,39,192,190,119,224,53,248,20,253,142,255,193, 119,225,26,60,3,170,132,221,28,13,163,120,45,190,27,190, 95,20,229,98,15,72,127,223,243,21,52,21,202,166,73,244, 1,152,245,121,151,65,220,225,13,105,165,111,59,94,141,251, 33,5,94,143,127,130,255,79,251,174,113,252,59,124,27,248, 72,31,254,91,80,9,246,26,135,159,118,47,208,40,142,117, 41,101,29,41,232,49,30,68,179,160,114,44,153,44,2,200, 168,115,57,121,203,149,25,73,223,65,252,99,240,13,31,30, 192,143,226,63,80,215,127,17,127,22,200,186,28,210,227,17, 211,79,120,13,175,194,29,2,17,76,57,79,176,220,247,124, 27,245,162,90,168,23,167,76,14,124,151,252,55,228,109,218, 24,231,54,103,126,171,244,157,130,96,248,2,188,146,0,103, 95,171,233,198,9,252,175,248,58,248,111,205,215,171,248,106, 156,245,60,129,249,10,8,232,71,117,80,41,22,77,10,124, 239,253,42,215,47,78,152,249,69,210,183,25,223,143,219,33, 4,22,227,231,32,33,90,175,163,248,75,105,59,3,121,130, 206,129,44,247,195,147,69,0,192,151,30,84,223,228,242,140, 51,191,72,250,246,224,39,33,97,182,88,126,194,90,156,204, 100,94,48,193,125,247,42,212,135,194,133,39,128,56,255,106, 189,95,95,155,133,251,167,147,62,246,250,158,210,51,228,63, 79,40,185,79,35,160,128,26,48,69,113,254,199,117,182,47, 205,201,253,211,73,223,24,254,114,174,243,2,203,114,173,64, 61,133,21,65,5,190,244,132,241,166,207,229,225,254,34,233, 27,197,75,242,156,23,176,247,93,119,162,110,40,133,10,150, 6,9,124,183,247,41,163,246,138,114,45,14,158,160,240,205, 196,253,191,88,168,121,129,114,223,121,7,154,93,184,58,0, 224,87,187,229,167,217,184,91,145,166,241,205,197,253,31,206, 114,30,48,209,125,251,205,168,19,218,34,103,33,8,80,225, 255,128,103,121,243,132,141,111,54,238,255,98,174,243,128,148, 247,237,55,161,14,104,143,157,5,81,126,21,62,27,103,137, 140,27,223,76,220,255,79,74,71,152,199,60,64,112,223,246, 25,52,19,198,36,142,66,36,62,112,126,51,195,203,178,136, 255,137,221,255,218,194,204,3,184,101,91,128,102,192,240,212, 94,136,170,239,73,171,187,61,143,211,93,169,26,95,177,251, 255,188,192,243,0,242,81,182,14,93,131,90,161,27,180,231, 95,246,60,38,234,183,15,224,137,175,84,141,47,127,125,136, 27,114,234,247,211,221,247,111,74,140,163,79,162,22,152,12, 21,231,217,241,73,15,136,24,158,134,51,189,38,142,255,71, 114,236,247,83,223,247,189,158,56,149,196,232,19,249,18,80, 164,55,188,214,136,187,17,103,119,165,142,255,35,224,35,185, 245,251,169,238,123,119,54,28,73,128,72,231,235,1,100,135, 247,115,169,246,247,31,198,185,92,162,248,127,44,231,126,63, 197,253,63,199,247,37,177,66,192,213,160,1,57,19,48,5, 57,74,63,238,27,246,98,178,172,146,243,47,184,48,215,40, 110,206,185,223,23,221,247,30,141,189,147,192,132,0,8,129, 107,81,27,136,96,113,110,240,237,190,153,165,135,75,161,47, 243,41,20,152,223,118,125,129,8,248,117,30,253,190,224,254, 112,221,214,4,214,87,238,4,76,65,197,129,112,240,157,50, 92,6,187,56,1,160,192,207,208,160,190,213,187,5,34,96, 73,62,231,7,204,247,199,107,54,38,176,106,127,133,128,235, 114,37,192,86,46,85,188,92,14,53,93,25,86,73,32,139, 144,32,107,1,113,11,30,46,8,252,227,184,34,255,243,3, 244,181,138,161,36,181,126,50,15,2,64,251,67,15,86,225, 16,172,114,101,5,53,79,80,73,32,190,112,43,164,180,223, 224,247,242,38,224,197,2,158,31,40,27,210,161,231,231,1, 16,253,213,151,87,143,85,193,166,21,33,161,66,163,129,245, 5,66,194,84,80,243,21,176,13,254,18,254,95,83,221,159, 205,245,215,121,245,251,236,125,255,230,196,24,111,255,100,142, 4,216,66,21,117,59,107,113,53,172,26,172,210,80,65,125, 161,12,188,65,245,5,66,66,0,106,254,27,96,134,255,24, 72,217,31,97,150,147,253,213,145,87,191,207,108,133,189,217, 120,50,201,68,127,34,103,2,192,253,195,143,214,225,58,104, 102,194,184,86,33,161,82,161,161,130,134,132,238,11,1,133, 4,63,124,213,133,111,130,154,127,53,254,21,222,145,114,68, 34,186,14,229,217,239,211,83,35,187,26,14,155,173,159,107, 8,20,215,182,69,79,213,195,46,93,29,214,105,32,36,84, 83,79,48,124,161,76,241,4,53,71,248,225,222,0,72,227, 253,80,214,62,143,223,204,80,34,127,83,152,243,1,7,226, 123,147,38,232,185,106,64,17,114,53,252,42,138,99,48,236, 50,72,32,158,160,134,132,53,32,116,26,124,154,56,214,224, 203,96,172,181,18,63,4,21,223,22,203,132,200,124,61,81, 128,243,1,242,135,209,29,172,237,89,33,204,150,0,200,254, 177,206,198,241,6,76,86,12,86,61,165,33,172,5,132,74, 131,154,33,120,95,8,104,190,64,210,100,12,95,5,93,224, 74,252,0,180,185,27,132,219,30,234,181,52,207,126,31,254, 126,58,252,26,111,117,246,111,217,18,0,246,111,122,38,169, 116,241,13,56,14,43,102,242,133,90,133,8,221,23,42,77, 36,168,186,160,39,74,25,55,41,121,98,37,236,240,253,35, 76,136,222,23,16,112,109,94,253,62,249,170,106,163,14,56, 137,173,42,144,45,1,197,209,200,212,83,77,244,71,53,42, 158,160,210,16,161,52,212,42,171,70,209,5,222,23,12,18, 74,21,85,32,69,147,31,242,196,167,33,79,172,196,223,132, 169,225,75,166,118,120,86,158,251,255,108,225,195,59,127,46, 30,0,205,79,243,237,211,32,191,147,149,84,150,238,11,106, 64,196,56,95,168,85,40,208,117,193,234,11,165,140,47,144, 60,177,24,242,196,74,88,79,65,174,208,79,142,196,242,218, 255,15,172,55,172,157,52,57,191,250,90,118,4,20,33,119, 235,11,173,208,155,77,195,58,13,77,202,143,36,52,16,18, 162,22,95,8,83,26,248,28,17,228,124,193,167,30,105,131, 215,251,149,60,65,104,248,46,254,5,126,7,190,39,247,253, 127,255,150,196,168,53,242,121,143,200,142,0,40,128,218,78, 78,135,94,189,5,171,52,24,190,208,164,5,132,234,11,68, 21,34,38,95,168,97,124,161,66,161,160,156,235,34,252,154, 47,200,240,125,243,64,252,86,42,235,150,220,250,125,229,217, 130,198,227,162,196,199,19,145,29,1,246,228,37,237,48,189, 107,131,168,109,83,104,152,70,125,65,15,136,132,230,11,134, 56,26,186,16,86,104,168,164,1,81,65,43,71,149,134,128, 166,11,178,66,68,20,207,199,119,226,155,115,232,247,149,159, 176,59,113,200,236,240,252,231,236,75,225,41,168,100,198,178, 153,112,168,105,6,236,218,183,41,75,228,11,42,13,113,77, 28,117,95,136,80,26,170,105,237,24,98,124,33,200,117,17, 126,141,4,57,215,253,255,131,177,61,214,170,79,228,13,217, 16,0,10,208,241,131,89,160,203,58,9,134,47,180,78,224, 11,102,113,172,213,124,193,154,35,130,90,209,164,231,8,111, 14,251,255,222,99,245,219,147,130,194,71,84,9,100,71,128, 212,245,159,157,120,22,214,73,32,52,176,36,180,48,226,200, 147,96,78,148,17,205,23,210,21,208,165,154,39,200,116,220, 150,225,60,96,164,118,75,106,167,55,83,146,13,1,54,228, 237,217,210,13,233,138,44,131,134,118,133,6,66,66,139,208, 23,18,52,85,166,247,5,107,209,196,251,130,156,225,60,160, 106,3,159,233,173,214,231,230,1,89,140,196,138,145,191,119, 95,47,158,141,187,225,67,37,161,131,243,133,233,138,55,232, 170,48,77,73,146,83,105,181,160,231,136,168,160,104,170,166, 245,66,136,233,35,130,220,164,201,155,129,42,144,194,199,26, 251,73,97,18,212,68,240,154,204,167,194,197,168,180,255,84, 31,60,222,208,11,31,221,176,58,97,117,81,79,232,80,72, 80,67,162,85,89,205,156,47,52,105,213,66,42,93,8,211, 128,168,18,250,130,159,14,220,82,207,3,2,27,68,202,159, 192,137,20,34,216,184,14,93,5,7,37,253,153,157,20,45, 70,129,1,104,104,251,49,33,161,71,35,161,155,146,160,251, 130,42,142,109,84,28,155,133,186,16,215,138,38,163,94,168, 229,116,65,52,93,224,19,165,117,30,224,219,146,28,17,41, 127,50,5,29,141,184,226,30,52,15,197,225,180,112,102,4, 200,193,65,60,7,19,18,250,96,245,43,158,160,134,132,161, 11,51,105,142,104,167,213,66,171,73,28,85,26,26,82,234, 66,141,54,105,178,234,66,144,6,132,159,201,16,154,246,111, 79,28,179,218,56,105,130,156,208,194,81,233,98,214,161,79, 161,46,56,32,147,225,9,33,240,128,185,152,80,48,168,144, 48,160,144,160,251,194,108,170,11,70,162,228,235,133,102,75, 142,208,235,5,117,186,16,97,26,107,235,116,33,100,10,136, 82,218,69,104,190,176,167,225,160,168,223,103,193,83,224,218, 42,95,129,174,128,0,8,192,222,112,134,4,148,182,108,232, 249,253,37,135,8,13,131,26,13,125,202,226,3,66,165,161, 195,68,131,161,11,70,23,97,110,166,216,2,58,44,108,166, 140,2,58,192,248,130,124,40,190,91,172,250,141,38,224,113, 250,110,241,117,232,47,225,128,84,109,230,103,4,33,11,52, 129,198,54,13,183,111,234,127,117,238,40,239,11,172,46,16, 10,58,181,28,209,161,145,96,46,154,154,53,10,154,184,122, 33,74,3,34,130,205,83,199,202,20,141,53,80,112,34,186, 205,128,109,184,121,130,177,118,92,251,76,130,78,13,188,178, 44,237,175,212,1,141,63,211,157,171,249,207,157,67,131,187, 116,79,152,67,117,129,144,96,36,202,78,45,32,58,152,68, 201,214,11,122,64,52,97,118,200,18,229,38,77,117,52,67, 84,107,163,87,126,224,22,24,173,123,197,108,109,195,222,122, 25,22,167,227,27,77,117,178,182,63,33,64,110,124,128,23, 152,214,55,123,54,12,126,96,4,132,154,35,122,169,46,24, 36,176,5,180,94,52,181,80,95,208,73,72,208,158,50,42, 152,52,169,69,83,21,157,64,171,205,84,205,250,70,205,234, 4,114,35,3,155,181,183,218,156,25,63,53,123,251,147,82, 216,19,251,188,53,153,52,29,111,223,216,255,250,224,248,32, 23,16,253,140,46,16,26,58,76,5,244,116,70,23,120,113, 76,152,6,110,245,41,134,44,106,64,84,15,53,152,28,61, 110,178,118,148,89,245,122,135,154,131,253,73,55,232,170,157, 107,173,169,212,196,51,109,79,215,208,220,189,134,46,244,155, 114,4,235,11,29,90,181,208,78,3,130,111,172,245,33,139, 17,16,186,47,68,184,33,75,21,174,217,104,64,143,153,96, 199,76,176,35,154,182,144,85,154,131,253,9,1,78,127,125, 114,156,239,167,57,229,29,111,219,218,187,113,240,4,239,11, 125,90,229,168,215,11,179,76,245,130,104,186,96,78,148,113, 193,116,1,196,241,181,134,211,102,224,186,163,215,51,192,35, 20,120,68,21,215,156,236,175,12,68,80,48,177,39,93,121, 73,254,108,58,58,115,253,156,109,230,68,217,75,229,177,211, 82,52,25,205,84,139,165,128,78,210,113,91,131,6,141,38, 202,29,13,31,196,82,56,122,68,35,139,131,173,37,215,186, 28,237,175,85,2,201,223,38,44,1,32,170,185,166,237,154, 61,52,103,255,160,169,104,234,133,101,20,77,29,2,95,152, 110,234,34,12,93,72,48,93,4,64,218,27,63,16,165,142, 94,207,89,187,206,2,58,172,0,87,11,172,218,156,237,79, 242,128,175,241,135,201,180,67,38,142,146,209,233,175,244,110, 158,51,204,22,208,106,51,213,77,125,161,211,212,81,234,205, 148,120,210,68,155,169,195,209,93,81,26,20,169,172,93,167, 1,175,213,54,109,212,85,122,15,186,60,55,251,147,60,32, 199,239,21,149,153,201,52,147,247,230,67,29,67,115,222,214, 73,24,160,36,168,57,98,54,87,57,118,8,139,38,182,94, 80,178,252,201,216,155,81,45,178,213,146,201,108,111,35,113, 170,115,72,53,129,146,21,122,26,70,32,179,160,254,207,233, 25,17,146,8,111,204,174,223,214,191,106,217,209,61,52,248, 190,85,23,140,128,232,202,104,210,4,25,98,44,182,153,183, 118,68,139,237,48,93,181,116,233,192,213,46,179,226,25,112, 255,126,232,255,252,185,216,95,73,132,53,61,217,244,219,73, 166,11,35,69,244,140,77,125,91,72,17,109,248,66,47,165, 161,75,208,76,205,80,84,129,207,17,13,67,117,38,39,15, 83,107,135,53,107,179,192,153,221,202,159,162,27,208,92,148, 132,9,144,51,183,103,132,32,17,186,106,72,207,61,81,191, 157,76,211,144,36,247,119,12,13,236,226,19,165,218,86,207, 166,125,68,7,55,100,209,39,77,68,23,18,67,134,154,135, 181,65,74,88,179,181,1,91,183,56,129,173,111,202,132,126, 14,240,47,129,232,47,135,246,55,231,71,101,33,17,38,119, 136,125,32,105,178,185,168,33,137,211,10,175,249,173,238,13, 131,71,205,205,84,175,41,32,204,83,199,230,141,117,227,134, 139,215,88,220,156,181,119,149,54,93,34,21,35,148,206,207, 218,110,4,248,205,112,52,222,149,207,147,194,144,8,19,107, 18,194,189,86,115,215,109,52,186,169,42,243,248,241,233,27, 251,183,14,142,15,8,117,161,147,118,148,186,46,180,109,173, 27,14,11,97,215,80,224,213,12,240,74,109,65,201,252,75, 128,63,79,129,239,206,239,65,105,232,8,19,79,154,230,106, 38,39,87,63,226,76,77,110,174,211,140,110,143,172,198,189, 51,135,230,236,29,52,5,132,222,88,119,210,225,107,251,59, 225,163,86,123,215,104,96,171,181,134,153,131,173,111,189,252, 7,192,191,20,77,131,39,67,220,249,62,39,14,123,3,241, 229,137,20,209,221,56,65,67,18,227,27,18,38,119,215,141, 79,221,218,13,69,180,209,81,246,48,141,181,66,194,190,200, 123,188,155,235,174,94,73,221,156,133,29,210,250,69,128,191, 198,182,144,129,63,37,95,2,220,145,235,18,92,207,221,200, 181,159,34,216,245,12,104,163,37,169,179,36,177,250,163,45, 27,250,223,26,164,149,163,161,11,221,71,234,119,26,144,245, 195,23,86,216,21,218,180,64,157,23,40,237,242,75,182,207, 162,203,224,68,120,101,33,224,43,251,131,229,51,116,216,13, 66,216,230,186,220,128,93,103,169,212,216,52,166,151,44,241, 93,80,56,237,103,197,177,239,84,236,141,106,206,201,173,192, 245,125,198,10,109,71,65,219,89,248,47,219,34,244,177,194, 193,39,151,195,19,106,56,222,64,99,91,212,128,214,51,91, 162,108,165,22,17,230,110,93,205,217,20,86,61,154,220,210, 189,121,112,88,33,97,60,185,169,74,219,59,178,218,219,128, 93,161,129,38,240,213,21,88,107,91,12,240,91,225,185,64, 79,225,126,181,150,29,149,197,95,139,153,96,199,152,168,54, 215,229,17,6,52,15,92,156,196,170,104,26,11,191,223,54, 212,247,118,235,144,213,218,21,218,18,193,14,106,243,194,178, 117,182,155,160,234,111,83,224,23,23,238,209,88,24,141,198, 158,143,113,125,152,24,56,223,137,241,5,139,24,54,43,106, 149,154,163,155,157,92,5,205,58,58,15,156,236,46,43,147, 194,13,182,37,208,244,22,28,190,146,8,163,143,233,227,6, 115,223,205,118,221,214,62,172,38,13,108,54,129,89,237,29, 74,233,230,101,12,236,128,118,24,175,20,151,109,182,125,14, 224,79,71,213,133,134,175,36,194,240,23,69,214,142,112,78, 158,14,182,225,230,149,116,230,47,118,115,29,118,208,2,59, 168,109,145,168,31,234,182,89,64,57,148,11,187,5,175,218, 62,143,174,84,224,75,133,134,79,242,128,187,114,190,145,192, 248,174,91,92,153,87,167,112,116,93,205,67,2,53,47,167, 103,71,172,78,174,218,89,223,23,8,104,59,69,250,73,163, 210,55,224,121,224,43,225,113,200,154,201,128,175,52,68,193, 132,97,111,125,103,183,54,37,236,42,70,214,210,105,185,97, 113,43,236,32,221,20,211,79,31,27,160,85,216,126,109,247, 216,183,205,126,11,154,63,121,240,213,60,80,26,250,100,237, 179,117,167,106,211,56,122,21,167,231,134,168,89,107,181,244, 162,86,166,139,154,5,184,1,218,79,207,27,122,223,182,223, 10,27,222,237,48,240,146,39,11,190,82,13,66,97,49,205, 61,191,234,241,154,221,213,194,232,54,138,22,49,104,125,103, 167,34,165,181,3,154,155,167,181,182,1,92,249,236,219,105, 191,13,224,207,84,224,219,39,239,87,35,193,129,105,112,175, 16,204,85,218,139,231,6,151,87,253,174,102,188,202,34,108, 98,45,55,162,91,172,229,6,240,128,0,184,126,178,212,71, 255,244,210,5,187,196,239,218,111,71,31,7,248,225,201,133, 175,83,80,2,191,160,48,132,162,80,103,245,72,55,84,254, 184,234,176,85,212,172,149,90,102,209,173,238,251,26,160,13, 107,123,41,112,243,169,33,105,143,253,14,128,223,113,38,224, 171,20,20,1,9,78,120,179,32,188,101,19,154,85,124,69, 112,85,232,245,144,182,121,89,97,74,100,34,123,179,192,89, 123,251,45,110,158,26,54,61,25,182,207,190,20,158,2,38, 240,189,103,2,62,251,27,67,28,160,8,165,80,111,53,64, 222,237,247,221,86,241,239,161,225,114,161,168,89,65,235,135, 94,172,209,205,199,182,225,230,28,104,99,237,183,127,9,158, 1,158,5,191,16,233,140,194,55,124,193,14,1,225,133,105, 75,4,186,238,217,142,107,202,190,95,190,215,90,169,5,152, 71,104,82,171,185,95,23,52,33,108,217,12,157,172,131,246, 101,0,191,19,222,221,119,230,225,179,190,224,4,105,12,64, 254,77,160,153,197,115,125,95,9,254,222,234,226,98,216,62, 129,189,83,89,219,67,255,84,151,244,190,243,78,120,0,90, 133,239,248,104,127,107,44,33,193,14,35,71,34,142,49,16, 199,94,207,194,210,159,6,142,6,82,194,54,100,205,107,58, 242,196,158,254,100,193,155,151,116,184,120,57,192,239,66,245, 31,61,124,86,28,75,168,56,118,22,95,225,123,168,116,155, 176,104,161,143,217,90,207,0,179,246,102,224,210,175,220,202, 242,124,80,124,55,28,116,60,139,224,243,226,232,209,196,113, 6,26,144,190,224,127,193,55,226,101,108,157,86,212,52,71, 231,97,187,153,229,34,159,143,57,238,129,131,174,179,33,21, 251,225,221,138,208,89,118,169,226,232,82,196,177,30,196,177, 219,113,157,247,73,239,123,86,71,151,4,22,151,52,200,44, 112,15,5,79,224,187,78,56,190,10,240,187,207,86,248,108, 201,68,196,177,12,202,211,4,234,40,158,231,249,170,60,36, 165,177,55,11,156,183,186,102,119,133,0,215,73,199,215,96, 147,179,27,180,230,172,134,207,138,163,27,254,169,149,240,15, 110,67,189,37,139,165,127,150,143,121,4,178,230,22,44,151, 14,90,89,37,100,13,59,238,3,248,61,240,211,74,207,126, 248,86,113,172,131,253,185,78,219,124,215,183,228,63,184,25, 155,179,22,119,177,214,166,208,85,248,174,211,142,251,209,2, 248,77,160,113,128,239,60,55,224,155,197,49,0,179,26,69, 28,157,75,221,107,220,163,38,247,22,128,214,151,19,151,140, 56,86,161,235,21,248,129,115,13,62,47,142,62,42,142,215, 187,255,222,115,192,236,232,46,43,116,248,112,142,57,30,2, 248,125,64,223,57,10,223,152,41,24,226,152,4,113,188,180, 228,94,215,70,30,180,147,5,174,174,49,199,35,232,47,224, 128,195,57,15,95,44,142,125,246,37,37,191,40,57,238,100, 40,96,151,99,220,177,90,129,223,152,251,1,135,179,89,28, 203,21,113,236,178,125,194,185,186,100,39,192,197,234,7,249, 172,46,251,119,224,116,255,128,2,191,228,124,129,47,18,199, 70,152,51,205,177,127,217,249,178,115,204,0,15,240,191,167, 192,79,156,143,240,205,226,24,2,113,108,65,61,182,79,57, 255,193,126,8,160,147,245,4,192,159,3,240,131,231,43,124, 177,56,206,42,190,172,248,235,246,87,0,254,213,16,251,23, 0,124,126,206,228,135,86,42,14,226,216,5,53,95,59,124, 69,224,219,208,5,114,233,226,232,5,216,213,224,13,149,64, 199,5,4,159,247,5,151,246,191,97,45,66,23,175,139,215, 197,235,226,117,134,174,255,7,18,156,48,32,143,188,77,137, 0,0,0,0,73,69,78,68,174,66,96,130, }; /* label-sm.png */ static unsigned char label_sm_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82, 0,0,0,48,0,0,0,48,8,4,0,0,0,253,11,49, 12,0,0,4,25,105,67,67,80,107,67,71,67,111,108,111, 114,83,112,97,99,101,71,101,110,101,114,105,99,82,71,66, 0,0,56,141,141,85,93,104,28,85,20,62,187,115,103,35, 36,206,83,108,52,133,116,168,63,13,37,13,147,86,52,161, 180,186,127,221,221,54,110,150,73,54,218,34,232,100,246,238, 206,152,201,206,56,51,187,253,161,79,69,80,124,49,234,155, 20,196,191,183,128,32,40,245,15,219,62,180,47,149,10,37, 218,212,32,40,62,180,248,131,80,232,139,166,235,153,59,51, 153,105,186,177,222,101,238,124,243,157,239,158,123,238,185,103, 239,5,232,185,170,88,150,145,20,1,22,154,174,45,23,50, 226,115,135,143,136,61,43,144,132,135,160,23,6,161,87,81, 29,43,93,169,76,2,54,79,11,119,181,91,223,67,194,123, 95,217,213,221,254,159,173,183,70,29,21,32,113,31,98,179, 230,168,11,136,143,1,240,167,85,203,118,1,122,250,145,31, 63,234,90,30,246,98,232,183,49,64,196,47,122,184,225,99, 215,195,115,62,126,141,105,102,228,44,226,211,136,5,85,83, 106,136,151,16,143,204,197,248,70,12,251,49,176,214,95,160, 77,106,235,170,232,229,162,98,155,117,221,160,177,112,239,97, 254,159,109,193,104,133,243,109,195,167,207,153,159,62,132,239, 97,92,251,43,53,37,231,225,81,196,75,170,146,159,70,252, 8,226,107,109,125,182,28,224,219,150,155,145,17,63,6,144, 220,222,154,175,166,17,239,68,92,172,219,7,170,190,159,164, 173,181,138,33,126,231,132,54,243,44,226,45,136,207,55,231, 202,83,193,216,171,170,147,197,156,193,118,196,183,53,90,242, 242,59,4,192,137,186,91,154,241,199,114,251,109,83,158,242, 231,229,234,53,154,203,123,121,68,252,250,188,121,72,246,125, 114,159,57,237,233,124,232,243,132,150,45,7,252,165,151,148, 131,21,196,131,136,127,161,70,65,246,231,226,254,177,220,74, 16,3,25,106,26,229,73,127,46,146,163,14,91,47,227,93, 109,166,232,207,75,12,23,55,212,31,75,22,235,250,129,82, 160,255,68,179,139,114,128,175,89,6,171,81,140,141,79,218, 45,185,234,235,249,81,197,206,23,124,159,124,133,54,171,129, 127,190,13,179,9,5,40,152,48,135,189,10,77,88,3,17, 100,40,64,6,223,22,216,104,169,131,14,6,50,20,173,20, 25,138,95,161,102,23,27,231,192,60,242,58,180,153,205,193, 190,194,148,254,200,200,95,131,249,184,206,180,42,100,135,62, 130,22,178,26,252,142,172,22,211,101,241,171,133,92,99,19, 63,126,44,55,2,63,38,25,32,18,217,131,207,94,50,73, 246,145,113,50,1,34,121,138,60,77,246,147,28,178,19,100, 239,250,216,74,108,69,94,60,55,214,253,188,140,51,82,166, 155,69,221,57,180,187,160,96,255,51,42,76,92,83,215,172, 44,14,182,134,35,203,41,251,5,93,189,252,198,95,177,92, 233,44,55,81,182,226,25,157,186,87,206,249,95,249,235,252, 50,246,43,252,106,164,224,127,228,87,241,183,114,199,90,204, 187,178,76,195,236,108,88,115,119,85,26,109,6,227,22,240, 209,153,197,137,197,29,243,113,241,228,87,15,70,126,150,201, 153,231,175,244,93,60,89,111,46,14,70,172,151,5,250,106, 249,86,25,78,141,68,172,244,131,244,135,180,44,189,39,125, 40,253,198,189,205,125,202,125,205,125,206,125,193,93,2,145, 59,203,157,227,190,225,46,112,31,115,95,198,246,106,243,26, 90,223,123,22,121,24,183,103,233,150,107,172,74,33,35,108, 21,30,22,114,194,54,225,81,97,50,242,39,12,8,99,66, 81,216,129,150,173,235,251,22,159,47,158,61,29,14,99,31, 230,167,251,92,190,46,86,1,137,251,177,2,244,77,254,85, 85,84,233,112,148,41,29,86,111,77,56,190,65,19,140,36, 67,100,140,148,54,84,247,184,87,243,161,34,149,79,229,82, 105,16,83,59,83,19,169,177,212,65,15,135,179,166,118,160, 109,2,251,252,29,213,169,110,178,82,234,210,99,222,125,2, 89,211,58,110,235,13,205,21,119,75,210,147,98,26,175,54, 42,150,154,234,232,136,168,24,134,200,76,142,104,83,135,218, 109,90,27,5,239,222,244,143,244,155,50,187,15,19,91,46, 71,156,251,12,192,190,63,241,236,251,46,226,142,180,0,150, 28,128,129,199,35,110,24,207,202,7,222,5,56,243,132,218, 178,219,193,29,145,72,124,11,224,212,247,236,246,191,250,50, 120,126,253,212,233,220,196,115,172,231,45,128,181,55,59,157, 191,223,239,116,214,62,64,255,171,0,103,141,127,1,160,159, 124,85,3,92,11,239,0,0,0,56,101,88,73,102,77,77, 0,42,0,0,0,8,0,1,135,105,0,4,0,0,0,1, 0,0,0,26,0,0,0,0,0,2,160,2,0,4,0,0, 0,1,0,0,0,48,160,3,0,4,0,0,0,1,0,0, 0,48,0,0,0,0,248,255,78,54,0,0,3,99,105,84, 88,116,88,77,76,58,99,111,109,46,97,100,111,98,101,46, 120,109,112,0,0,0,0,0,60,120,58,120,109,112,109,101, 116,97,32,120,109,108,110,115,58,120,61,34,97,100,111,98, 101,58,110,115,58,109,101,116,97,47,34,32,120,58,120,109, 112,116,107,61,34,88,77,80,32,67,111,114,101,32,53,46, 52,46,48,34,62,10,32,32,32,60,114,100,102,58,82,68, 70,32,120,109,108,110,115,58,114,100,102,61,34,104,116,116, 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49, 57,57,57,47,48,50,47,50,50,45,114,100,102,45,115,121, 110,116,97,120,45,110,115,35,34,62,10,32,32,32,32,32, 32,60,114,100,102,58,68,101,115,99,114,105,112,116,105,111, 110,32,114,100,102,58,97,98,111,117,116,61,34,34,10,32, 32,32,32,32,32,32,32,32,32,32,32,120,109,108,110,115, 58,100,99,61,34,104,116,116,112,58,47,47,112,117,114,108, 46,111,114,103,47,100,99,47,101,108,101,109,101,110,116,115, 47,49,46,49,47,34,10,32,32,32,32,32,32,32,32,32, 32,32,32,120,109,108,110,115,58,73,112,116,99,52,120,109, 112,69,120,116,61,34,104,116,116,112,58,47,47,105,112,116, 99,46,111,114,103,47,115,116,100,47,73,112,116,99,52,120, 109,112,69,120,116,47,50,48,48,56,45,48,50,45,50,57, 47,34,10,32,32,32,32,32,32,32,32,32,32,32,32,120, 109,108,110,115,58,112,104,111,116,111,115,104,111,112,61,34, 104,116,116,112,58,47,47,110,115,46,97,100,111,98,101,46, 99,111,109,47,112,104,111,116,111,115,104,111,112,47,49,46, 48,47,34,62,10,32,32,32,32,32,32,32,32,32,60,100, 99,58,99,114,101,97,116,111,114,62,10,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,83,101,113,62, 10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 60,114,100,102,58,108,105,62,77,105,99,104,97,101,108,32, 83,119,101,101,116,60,47,114,100,102,58,108,105,62,10,32, 32,32,32,32,32,32,32,32,32,32,32,60,47,114,100,102, 58,83,101,113,62,10,32,32,32,32,32,32,32,32,32,60, 47,100,99,58,99,114,101,97,116,111,114,62,10,32,32,32, 32,32,32,32,32,32,60,100,99,58,114,105,103,104,116,115, 62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114, 100,102,58,65,108,116,62,10,32,32,32,32,32,32,32,32, 32,32,32,32,32,32,32,60,114,100,102,58,108,105,32,120, 109,108,58,108,97,110,103,61,34,120,45,100,101,102,97,117, 108,116,34,62,67,111,112,121,114,105,103,104,116,32,50,48, 49,57,32,77,105,99,104,97,101,108,32,83,119,101,101,116, 60,47,114,100,102,58,108,105,62,10,32,32,32,32,32,32, 32,32,32,32,32,32,60,47,114,100,102,58,65,108,116,62, 10,32,32,32,32,32,32,32,32,32,60,47,100,99,58,114, 105,103,104,116,115,62,10,32,32,32,32,32,32,32,32,32, 60,73,112,116,99,52,120,109,112,69,120,116,58,72,101,97, 100,108,105,110,101,62,78,101,119,32,73,99,111,110,60,47, 73,112,116,99,52,120,109,112,69,120,116,58,72,101,97,100, 108,105,110,101,62,10,32,32,32,32,32,32,32,32,32,60, 112,104,111,116,111,115,104,111,112,58,72,101,97,100,108,105, 110,101,62,78,101,119,32,73,99,111,110,60,47,112,104,111, 116,111,115,104,111,112,58,72,101,97,100,108,105,110,101,62, 10,32,32,32,32,32,32,60,47,114,100,102,58,68,101,115, 99,114,105,112,116,105,111,110,62,10,32,32,32,60,47,114, 100,102,58,82,68,70,62,10,60,47,120,58,120,109,112,109, 101,116,97,62,10,221,242,56,27,0,0,6,18,73,68,65, 84,88,195,205,88,107,108,83,101,24,254,214,181,167,235,118, 206,217,122,218,173,235,117,237,186,118,184,139,12,54,29,101, 23,131,65,162,81,103,32,138,9,94,98,212,95,4,141,18, 19,209,24,35,9,248,151,63,38,70,163,36,42,137,127,192, 72,212,31,234,140,63,20,52,138,36,154,152,200,85,2,136, 147,31,178,49,86,217,70,251,250,124,223,185,245,180,29,56, 24,137,223,147,179,45,237,250,60,239,251,62,239,119,43,99, 255,155,81,195,106,153,27,112,225,175,155,48,92,172,78,110, 97,17,214,202,252,172,129,73,16,115,45,45,125,61,139,43, 7,149,121,229,152,242,142,123,45,75,178,16,107,100,62,230, 89,154,124,56,125,155,252,173,66,10,201,128,66,234,140,242, 163,188,93,234,97,49,22,96,242,141,230,35,232,149,111,56, 189,9,89,60,106,81,57,87,191,215,183,158,165,144,143,202, 234,174,207,31,23,42,158,148,15,152,180,230,79,7,242,202, 15,245,47,75,203,224,144,31,193,240,124,106,22,67,159,26, 252,229,19,58,66,187,104,173,35,254,10,201,130,250,123,253, 110,247,40,75,176,102,148,205,243,95,68,56,125,251,189,199, 206,18,81,15,141,209,7,116,130,222,163,135,169,185,74,38, 178,253,251,130,252,69,221,227,172,133,121,175,37,33,232,87, 28,253,3,244,221,180,146,214,81,63,62,206,101,38,232,83, 218,76,41,71,46,21,5,60,192,52,148,234,170,244,178,183, 67,249,237,43,65,223,79,15,210,38,186,155,66,212,72,97, 242,210,16,189,75,23,232,59,122,5,194,213,179,81,207,195, 17,247,194,244,181,160,207,170,39,55,17,9,129,59,233,41, 90,15,234,48,68,30,161,7,168,13,20,61,120,231,20,61, 228,136,93,182,254,86,167,225,133,103,97,122,69,234,82,206, 40,116,24,36,189,160,222,66,183,83,132,94,164,113,250,144, 158,165,219,32,201,199,1,74,84,120,96,225,50,154,87,90, 152,190,71,57,167,208,106,97,238,61,244,4,74,20,65,14, 79,227,231,32,189,137,226,240,241,19,5,203,168,229,82,87, 174,176,246,234,2,46,65,63,193,255,109,39,104,166,96,234, 24,169,180,134,238,163,86,228,177,5,249,244,226,245,11,212, 81,70,93,142,234,2,176,86,186,69,249,83,255,200,56,153, 67,151,81,16,255,32,117,137,87,158,89,96,78,152,62,104, 127,99,189,242,84,89,20,188,105,245,148,25,195,89,114,14, 93,134,155,123,2,221,84,30,113,105,203,250,167,59,103,43, 77,174,193,106,18,215,14,169,196,193,255,245,31,90,104,60, 239,232,156,178,137,70,141,51,157,212,57,201,226,229,2,30, 214,28,216,221,74,1,1,21,213,126,141,62,171,42,50,103, 117,143,92,197,102,117,54,91,204,82,230,12,139,58,231,1, 204,13,141,197,139,113,88,25,2,2,120,250,105,35,109,167, 189,116,174,76,96,188,202,12,182,48,223,81,200,82,39,165, 127,198,214,228,118,198,31,77,158,76,97,1,136,9,180,2, 26,100,130,232,249,49,122,155,126,165,130,37,240,106,21,106, 99,138,21,218,231,59,73,8,140,99,201,171,45,173,191,28, 219,192,223,202,82,169,136,158,139,134,130,181,211,99,244,57, 93,18,2,247,151,213,222,20,82,139,169,217,44,233,72,191, 143,181,200,85,58,185,130,189,95,118,161,5,187,41,99,136, 112,153,56,4,184,140,102,248,146,164,29,232,160,109,85,59, 72,161,120,94,39,231,129,182,237,192,22,84,178,154,186,89, 180,255,175,62,90,14,116,67,38,107,201,216,5,11,24,185, 112,84,219,15,34,211,58,181,142,200,147,88,139,75,4,36, 150,204,205,13,16,7,23,233,50,100,236,92,116,17,221,23, 187,145,109,180,76,153,212,157,66,70,201,161,233,89,169,64, 122,148,86,81,14,157,99,138,84,207,37,68,118,35,171,150, 3,205,83,102,105,12,145,153,242,105,6,129,53,52,10,228, 128,85,150,72,31,85,250,162,139,148,230,226,159,214,233,51, 70,56,105,74,126,204,130,206,237,70,98,169,158,124,110,114, 180,48,34,100,120,46,3,37,185,152,34,25,33,18,183,100, 52,32,152,215,169,59,4,218,65,159,46,42,67,78,7,248, 44,72,118,206,241,20,251,242,171,167,121,46,35,142,92,250, 22,240,37,68,225,217,76,17,148,32,110,55,94,111,163,248, 81,236,102,21,203,68,34,59,105,214,112,25,173,188,56,156, 231,34,35,150,200,128,229,10,207,69,47,89,146,98,243,237, 133,180,69,204,17,199,50,210,242,2,90,180,236,32,134,54, 205,124,100,119,49,71,215,196,192,193,59,142,143,26,34,185, 18,95,186,1,94,174,76,33,53,111,210,198,141,194,69,41, 114,24,241,87,236,4,110,214,154,121,203,110,52,83,38,67, 61,199,7,15,14,79,112,25,167,47,200,4,243,150,199,155, 0,169,65,13,180,30,193,62,80,95,121,96,169,101,205,233, 157,102,23,103,4,210,134,105,64,161,59,159,155,30,17,230, 155,50,43,40,149,231,180,17,129,48,12,15,243,133,229,180, 55,11,123,93,213,118,50,45,241,28,143,184,67,16,139,94, 64,141,83,162,210,73,81,134,4,221,122,113,40,63,98,244, 88,118,58,42,72,5,173,64,51,181,156,151,186,112,166,115, 85,191,92,168,225,71,59,140,110,72,10,106,219,180,184,49, 201,34,40,67,162,176,124,106,104,174,119,42,108,211,226,9, 2,129,73,79,63,83,22,58,108,213,176,6,237,46,155,54, 97,153,230,44,67,171,65,203,73,117,218,160,88,161,48,233, 102,220,195,184,49,92,229,44,231,149,187,18,100,155,22,53, 77,19,196,78,218,128,120,116,226,38,242,227,105,188,220,176, 142,53,93,253,168,88,203,252,45,235,99,251,162,179,122,180, 54,109,105,25,130,130,84,3,169,160,21,192,218,58,239,219, 128,131,187,251,90,87,60,15,166,71,76,25,14,237,10,77, 148,210,6,172,50,52,149,208,242,83,133,190,108,203,87,112, 150,214,174,69,111,246,146,132,46,8,73,221,218,214,224,161, 128,88,206,204,104,253,118,188,214,62,214,192,233,139,222,205, 88,216,60,139,185,172,186,49,81,2,44,37,111,108,218,215, 52,91,22,173,129,6,160,158,63,69,105,27,246,94,207,98, 47,78,252,70,236,133,105,49,223,176,186,75,158,176,227,213, 137,57,124,226,169,123,29,183,51,233,122,239,153,86,193,124, 91,125,151,120,188,58,41,104,13,120,223,192,209,196,123,99, 215,88,171,96,13,47,249,78,215,217,212,128,180,7,139,154, 119,41,110,201,122,193,26,89,172,118,76,250,190,174,32,145, 135,36,146,246,227,228,86,183,148,95,42,24,5,243,244,121, 246,120,46,185,191,198,21,220,183,244,223,89,232,5,211,96, 172,134,232,93,236,166,140,26,16,215,46,230,170,253,47,120, 125,171,15,164,64,176,74,0,0,0,0,73,69,78,68,174, 66,96,130, }; pappl-1.4.9/testsuite/label-sm.png000066400000000000000000000036141476704353100171120ustar00rootroot00000000000000PNG  IHDR00 1 gAMA abKGD̿+IDATX͘[$gVU=]=tuu&;cf';ӲC$:2A#D b| h"b u_Q4%Ƀ*sypw2mf'?&#X}+gNxd IIL"W< vN;^ԾMJbJTB?z<[  G!%9nHXo4 CRSt 3<z;)7IFbE7N㑈3?A~ז$Ex$";_|hiC>ArJ%ི Qx$"_;()0oIY-ƭ@Vp#"ϒV]y[* <)-mGC`lsN"c1#4k3D_R#@U>6M 8Ot"ᖍ'MgtttT4ͬK#3Ј^S$q$㏦'ISIݣNY߷z$;<[^&&qLVx cg`7u(_˔ɑ#Gq4{K)VXԩV1'j:$v-:>Ϲ Gƴ1|y%q 49$er1Iab8x<84EaчwSdWK4i`4N-: gCۑD )_]eUX jIl_<>t:ں-V문$k14:K\_fTOЦ:sI&%gלt~*Fr~ݤ]P-}e]Ddž^dE*TTZbs lԲ<~WJ{ & ֥7q͍NM6]Uו&5GJ)—E|ds퐬ҤEZ|Ї;e<'ɓ'w֧ziN1_4{< ddH=/% O,^IVwq5i*fg}o6\)wrȐ!CiLWDͩ1 _H (SD"E MǬ,)6,&&IPNDOj"ː]=~nzK +$b|p[pM!.t`10_mHZ\@mFz6N 1O2Q+}; b6,Qh$vA/ 3 we9۶v^1%ET1@8q7 _Kb:%.e'Dzu"B0=AIecFyɅ6S _8LaB%( z t9L t"mI]sEz58&d-`Qy ~'%+|_?$t,l 1Őᾫ&jx}vW@8eXIfMM*i00N6%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ExifOffset26SetEXtexif:PixelXDimension48'8tEXtexif:PixelYDimension48KIENDB`pappl-1.4.9/testsuite/landscape-color.jpg000066400000000000000000006051761476704353100204730ustar00rootroot00000000000000JFIF,,ExifMM*V^(ifUUUU+8Photoshop 3.08BIM8BIM%ُ B~C  C +"  :SAvqo]Avqo]Avqo]Avqo]Avqo]Avqo]ɏe{}Mqq#qӷ˰_LWeSm7QW۠U{Q9gaGL)D ͖as6dsޡʇ1o6$n:vv lmr*tڊj'4,((!9۬.x̐{;yP&={}5čNc.!}2_-M[\E_nT[QUD慝2d'6[uْzo*dDzoX8یv/@+岩q˛ j*г@ln2@9PCWAk7;qܻ|U6n9su}QmEWvtMmɏe{}Mq Jp&^h;,Fn1ۗ`} s,G;FQh9srN[m_(J@pyc]HkfTeUV9R_>OEmo7:!/@욀2q*Ade%сT[QUD慝2sYK!+[[1Vln2@Bé#0W;xㄕ_N9l=}=m`$g=3MvXčNc.!}2`__?#J,wuA!v)<CIhWeSm7QW۠}|* *TGRQmEWvt~P5Z\Pπډ ; :dt̴Z7:ј>і 2+[[1Vln2@H 5PN}']|QmEWvtOoJ!G@zT,[wJD8[?d'6[uْ? }x>͍˺~5unY{Gfyڎ~Cc^q\m&P`D/4q#qӷ˰_L A>%.W]4^_zTeUVҋhR>jѨQmEWvt@ "Qԕ f&tqR-lqOl-O_fi{sޡʇ1o6B\(q 8یv/@2=n_ B۬ɷY&d78u8il lmr*tVu(_=*?)+;WH ^'M@x8#c}My*ډ ; :d4TuK4nG[Q[^/Z)Ŗ7 n)D ͖as6dWXkgEj; pu{yȷҌ74a^ T?˪Ur&+̰{;yP&={}5Rk64BA`7;qܻMCo8D?mx= v/+岩q˛ s cmFxEU}T[QUD慝2VFZvَjd'6[uْSngu6-=T>ɏe{}MqW@[P6{0$n:vv #^Y+ /~,2 "+Ȱ,4'~;0ހWeSm7QW۠ %{TǬo_i`ڊj'4,(wg׵oAߨhR-lb+WvÞލ7<6=A WvL{+ kn]Bd[*lډ ; :dJ&Nl 9$T>ɏe{}Mqq#qӷ˰_LWeSm7QW۠U{Q9gaGL)D ͖as6dsޡʇ1o6$n:vv lmr*tڊj'4,((!9۬.x̐{;yP&={}5čNc.!}2_-M[\E_nT[QUD慝2d'6[uْzo*dDzoX8یv/@+岩q˛ j*г@ln2@9PCWAk7;qܻ|U6n9su}QmEWvtMm2"jjBP) jBP) jBP) jBP) jBP) jBP) 7MS)mTF.X)hb.X)hb.X)hb.X)hb.X)hb.X)hb{ C*W1 k) f`k) f`k) f`k) f`k) f`k) f`YͲ['V6!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!B9KwiLY$R4mB=H-z5O7|/k66\N_=):K!BVڮ}e{v]ބŒE/ZᄊZpZpZpZpZpZv~sF+{{HSjFs1 Nf|ڎw^10@XZaokj ?/JM('/eK{<?SC,K͍=V~KG3w0A񾽈NQcէd~*)r2['V}(]8>ΙUQӠA+/D2&,)zF\i`F9ъ# "捽Vo⧡+սLdnɵOwߗOXZaokj A9\Ng=69R@59za %l<4=Ľs>|dT~u0$}㣗^jfww\ Hf>/yOP u\mr VIպ_} NT4S$bLFyMU>Y#x:U6REwzIj#I/'BWugBG= t$sqiԿ~͗RT@hڅooi*z+G,}.Ak|[zm^![پ[+ VX[vչatߥ{g?y tWC4y5ٵ}0V!\qb)%f˞ie&4sΔP}㣗^j5q Y*sj=R]*["?\x:V6|W|/؅ Gt?HK})ФUv]ބŒE/ZRJW^wh`sF+{{HSm%<;Xœ4.QzXըgD͚nuT/2FH-z53Pz\VP&ϾUyiBUyo}JT.DF)P yh{{Y =`۾eg] +CZXS}㣗^j~Ϟ'Z= 7Ewb6N_=):K!B9lfމa?:WL[֖9׬#:Nj\[HBb"@7ʳ~{٫RzoW≬捽Vo⧡bw~tM/"OVJ Df>^eCVX[vt{{Q(b;y^)=H :\ ?x=pU/o[ty);nV'f}؎bpƉ*8`:?롼K"zVX[v{?qڍ1`ށ,O7|/k66\Az::elYs =@ZM {U/o[tuÔ Sc??2SڛuA܄U-_1h-ݤWw1dK֠"FKw雍kvA?4xhڅooi*zilЭ:9⣑)bd: _SZM$H-z5 9l݀WmS"5Mؾ9% L>|SC,K͍=u4{Ρ-/pҼtK=QU}ޅm'<׫>5&}q@>)r2['V}(]8YwW'Mc٢&,)z +&tEGQUUР6[E_F4iCvtPde5m#OPZ EakՅGh00weBs@[,pO7|/k66\Az:|P懾X.{4h>ԼUe6t{f-*<(.v޼Pi@W+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{+վRunlBӀr+ИHPhڅooi*zXZaokj ob^llW+\{!o~G3^6T/(8b/(8b/(8b/(8b/(8b/(8cy n"gcYXpV5gcYXpV5gcYXpV5gcYXpV5gcYXpV5gcYXpV57HS]*$************************7%|i%o////////////~^ْYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYlYl=lzqW|ҋ :s.V[5MZ!bif"A_?_5E^r Ru.LezgΙY/Pe٪fI B2M,o]Ѐ+樴c5[9] Pj[nɑ̯LϿ{~0x|9f-&- _=<[~~{>HF=ܟ!bif"|~z~?zV!d+a Ɏd^/߁|{d1~ odNpnB畐|1_^=>x { 1Dz/ Ru.LezgΙY/Px5op6jf'6496'p O5S$2]kOԛ*~xꫡnaOߡYon `|Za_\ʹ;023TϦ[v ` C,&Ev#8~xCGSBm7ً-l-Gn+(~?eی]o BTZy1@z+KGzژЛBz@. =);1ܙ;AYy9{hm,Iu6TZy1@7Vv)ú O) 'tb \GQ;48;= Zk{'8K!yl;D-"g9F?Wyt7]- 3< ۫=iB֐Uue_m?K ~癘ol5-RW|=uQkXt-7frm^|w#T+5YjeJ*%=e# Hm&G23gL,k^fUB٪;L0jf'64Ϟx5:Qv}߼w7Cm\BΖt)RsPs.V[5MZ4߄> \l%JXh%VmÛ}j;uOIHtlN=<ך2M,o]Ѐ,MonQ8YO<فp)HU6Ѐ2}K[͇[HcWvBD-PWQiGl.ufv>  2ЛBz@. 3ަi{HZ_`>/nPM'=Giր^r&,u+.{<::P+<.ޅx x+O*^'OF%ft :!z׶CK&Vjx3c@+n7)Jd&\˳UivBVRk( Ͱxspo/|CfIZdkR7 C,&E-  ?*Лh@4K|p>UeSzZ  -< Z}y~]17ڄ΀,\GmxZiqi#ɭ.܅(,7C9hi^yt,/E+#aǥU (@ԶK#^3xxK0 ֽr[5BU_5#wV!(O5S$2]kOԛ*B\)GthVmÛ}>>WQ:_C(z O%Sp\48IՀRf&a7.@hm@i'}W!VB):X4 O&|ެ}=^0yVӡ~jO&:?օ_^F߅uLhM=s W]r CQLJ]o$xkuwք[5%ېg< 0+<.ޅVfv :N>:?Yj?MTkcbyAioAb%j[nɑ̯Lft :s.V[5MZ!bif"A_?_5E^r Ru.LezgΙY/Pe٪fI B2M,o]Ѐ+樴c5[9] Pj[nɑ̯LS; B &; bS =Д$qc`y!ǟ\xYm߸]v(uQ1ݰ[JI'+H5>2>spP d+}c`/ = ImO}W>kZ+y} Gyǀ`)۝bW[![|TJKh{1Z[0Z<Ϯ<@ O. ??a01cdc~1kw31]loLwl?ϡy~{Ϸ}}}~TJKh{?O@ǟnE?#pA֊FAlj}~m<ʼn#MdbCbB}q"7BX,ZNk`$(E2>spP{gbPbg: loHus6? &4[+Vo  d(-m Fpk4Ա !#}KvY`i逘O*TOt%% =Exc0ÏL-4z6oC7sa@H+ul2N/26+H5>sXYv{qQ_" 2<EQ/+]n@S; /ȖީbsE%\"ᎩC{fbNVQW u@e;r4^)8V!Dvl_5]rܖ('b':BG-TaUaUU^WaEze1p7Eod*{'Z:-r ^iS|-fwov]]5 uDm|}ٽ@+H5>uWk; {qQcO?_\V?&R\̸ \=?>2{ϡZ Gyǀe{{uDN;gJOP#%ӑEvZ91ɳt rwPƐV}nw]trBcs}Dbh\Cvz[B!꛴71n~F??Ҽ{§R]A]loLwl&7]t] is9ㆆ3=K<нR9hP|f}ىTzPR{)-Ia'QU ' l:Wai{TqYq{/Pxk֡V|b3%Gߠ kEo#.I(AO/_:W˔2C]e儱5 p}r2*Ou:;]~pi$ y!ǟ\xV]hbTYҢ.d\ d!5TmqiYm߸]v(`_s U{^hX4: LTݡ٧>Ŵs4@fLcٖ57"ZEuüreM`8 d+}c`/!= Pj&K=RO,t/TZҔWFs`B͊ra4S =Д$Gi: Y M0CQZi0mGpblt"n^y L 5k kEo#v>ah"IJW[yl=+-Gΰ,%#r,Z<,Ҁ'y$=ZsiVf(vn *tWnQsu7@eg }~uؠ k(D13SvfבIsU#1PnD?4 Gw5&ߘ= d(-"^(UNz"ycz$rzhAocnAn_@TJKh{yrj 2 M3ަ ֱa.׼Q?YS2 Tqc`"}Yj=uya%ȏkz6&c'An<9f?8 `!hC> l[h TV QUq*M."Zy/I`)۝bffnVE uMݛ\UBd \7:9'W#9zW,R-5۩+Bؾ(zPDb':BG-<i -b,x*TOt%% =D d5^iS|?>uJWܠ>ߝFMYۨwD=Sz=nlv>@ kEo# 7mE{qQU\:y XR}K=u^$8C1?h*v kq enV.Oueg }~uؠ k(D13SvfT£ suB@j$QWCYW5 ӺaNܡ)݀W[![|$Q+ʡRO,t/TZYak1-ᓘ*{'"x^h\ 4Lo>h{ICB䄳Y ͋ O Ķ4u)AsCm;2 } ִV0 vޤ[y8=-Gΰ, dq /Qf-6}qڊ+=$87s? DjH!_|:V ݨeg }~uؠ k(D13Svfݴ?;1r}ֶV7'JMhֿ|b_5U/~z  d(-"^(UNz"ycz$rUyʱ4UɷAo JI'!x,+0=`ϑ?6n45h۽}^A֊FAnԋo'e}hUCڜ}jQ<'.Z<Ϯ<@}fp*y0ƉV}nw]Y!Q۶o@ɬ2`Z`_Ls=͸zc +BؾIh*,HT2G;[_ WͦZd儲pR{)-IHᬏd#g3hv85׏|J쨄$^A֊FA KERǺ 2>spP d+}c`/ = ImO}W>kZ+y} Gyǀ`)۝bW[![|TJKh{1Z[0Z<Ϯ<@ O. d(-Op$BR[@`A֊FAB}q"eg }~uؠV!Dvl_*{'2 } ִV0 $8+>S; B &; bS =Д$qc`y!ǟ\xYm߸]v(uQ1ݰ[JI'+H5>ZKm%ۢ[nm! c `֡Q=,NPq&[uuxyZ^LR4qg)H"Fч/C\㈿I{=n}Km,S/kw!p,z2_0}LJX{T_5{ZDC!5TBba9"׺xߚz+K{Xo؋q.?ڑַh r*~?!'p^SQɐ|p1*?O~G9=Bzj$a&p=g=>IE'#·{ZݢYm6O&Nա~K~?_rJ|.ED.8aY]|*kxC3RYV5{ZDߣ/o^Qv˼OL"lS3.D^YC[Kt+8 %]>|ʉQ\ÿ1}yJ;bUp1*?M/vD[5{ZD¸ߚz+K{ &֎$E#PEJi:#[jם.߻~U\ÿܫSbʼn( $xHhI\p1*?LOcuQu7=Bz\p=g=tJP {:LַhM'Q%\YiD+gaߏQbÁ ʹyK7]+%VpsG[gG 2J96 -va>w ) QkP"W;OYizXJF­]hD'{ZݢN+VIВrއj-׽7MsoE(P\p1*?R!Bt)|2"#qDP)_kP"W;OYizT#*&[M]H"ŋ/{ZݢM5chZ>kvlQH:V)m1.U+zo[:kw1GQ(c~?XF^-c!1o*XY+ Hr  >לѸO5tzxXTO_|+A(w'{ZݢM(T#c ̔EB =,H;%/t0KqĪh,_܋';YeqQцQQB¡nXW]6 {ZJܜD]k7'[!MbEH֤R'74B¡nXW]6 {ZJܜD]k7'[!MbEH֤R'74B¡nXW]6 {ZJܜD]k7'[!MbEH֤R'74B¡nXW]6 {ZJ-؆Ղ/brf)98kzqڙvn._ w9emd atu|5w,Fe_Ow=A-;RM@dn7zEr@4&/YeڄJr?᮵ @8n)\Sʪ]Co]r27^ʝĄ♍8E.߹~) 1OkC.yv?NWU.ŋ<^%SϞa-Zts*@"K<y㈑!‡Ț7(\y%$[Il %$[IlB a#!+-n^; Ŭq]J۷.z"B0O -U7^!-EDS& h!vā_ t#5P1ՇFQh -H o)ZĊ=HzKʗQ"D'f@h{No"hxߴV+qcr_M]k='Ϲ/]Zv?%Ϲkx : fWSqp\XL8NZEs:ou$6mx]zNTuԴn.dָлxRKTZH"!no"hx߲u!./nڰeYg᮵L}[v nN ,8=֡/ŀJ۰}7^C 5},q -#fJzXW]7mE<5(ǁROGl X2x)bIo83"kR)^!͹6آ(Hvxn(*XI&8"IJ&8äQ]k=7=OCrEI̎vϥ_@ud O)|B.3 Qޗ|[1-b_ t" )͵EP8_v-,_ш8m{ {ZJLa #9^؟mބC&o8^Ț7(Dј O%DR5ֽB¡zNdUm۶-: AqF!YC>$TjE+_ta:x[Ҹ>Ț7"XVy_pZJlc}Z7)~3:q:7uhSϗS+|B Xo&U6"]$9tKk1ۿs{^/?/}X7~o*@"x˗a]+a0/XȚ7^eۮKVJ'᮵V2[ U:8D Z:=Y(o!aPEbzZ+ą1pHSXJH"]c ^gN8sXEH֤Rlv<+`G=.lg;syCg/GJ^נzO#Y.^})>Y1!܋qēԸYmZk:<|B +-WZN+!Mb #z1(8v"kR)^ԎAźueaR5P n\IMkd}w u@o}\>Ӷ[ޓXT/it~,KzxW]748_X'Tv/7p./_)o"kR)^*%}nqb:z1 ,9}7742!_ tކ 8.ppCO~K b1" EH֤R%T ljGN9 䴁v-Yrbč"ZX&nb Ҿ۞ÆנzO;)`uN? NqK {ZJ+--5Qj`/syCG 7 j:ii= u@a+8L=o^@%7^imou|5z@rR6? {ZJ 8S_I&?ҳ*>ˆנzkh$ ( uN2PEXT/M\LBTV"ou|5z@Ed#{1$vl$TjE+PKOU3.(6m×UIJo%[zo"hxߩ ~<$4e]k=Kn߰A1 E e/ :Ik`^ tTOd8n1,e8+l:ZDElgu|5znzCf?Y3*ѕ7.}m5- vKĊ=HnNo"hx᮵XT-kܱ"kR)[Ț78kz r:,HԊV&N^<|Bܱm*@"9{נnO!aP,CᮛrĊ=HnNo"hx᮵XT-kܱ"kR)[Ț78kz r:,HԊV&N^<|Bܱm*@"9{נnO!aP,CᮛrĊ=HnNo"hx᮵XT-kܱ"kR)[Ț78kz r:,HԊV&N^<|Bܱm*@"9{נnO!aP,CᮛrĊ=HnNo"hx᮵XT-kܱ"kR)[Ț78kz r:,HԊV&N^<|Bܱm*@ݶ5qƿ3L!383L!383L!383L!383L!383L!383L!383L!383L!383L!383L!383L!383E[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[lsϖ>[M9|6L `\&0. pL `\&0. pL `\&0. pL `\&0. pL `\&0. pL `\&0. pL `\;x֧۱HI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'{hI'EK\E(D%Q."qK\E(D%Q."qK\E(D%Q."qK\E(D%Q."qK\E(D%Q."qK\E(D%Q."qK\E pAQNN%*ODrWj]3rqW]bOܖ%>-ȑnJ0=KnN*r,UDŹ?_t^nQw%U?rZ#"G+.8.VJKUsH7%֥7'yEܖ*TjS܎|Ժf7(Y*-TJ|[ϑ#ܕ`{ZLܜUrX%S%Or9$kR雓ܢKd~Q)nG>DrWj]3rqW]bOܖ%>-ȑnJ0=KnN*r,UDŹ?_tG4Xf avv˶f a,,wUl/oć ehbj% 8~KU?ѻ=2FXȿ ,>dec%XrZ/\AQ~wUtrgL4.ҦY82g ]sH=#ij(he #ó*he 42PCC(he o\Ժg|ɒ:z5PQ&Y8_ǻ*r߽z˫z.% vx(1ot6hǕ-}ՊU?k/G.\s&zSϪKkXE6Γd D]PM:Q)z 4dC Ǣ1C ;>Di0,K|k>ù^UWj]3A ~vRVky^nQ{!ieVC#EmYb۷މ{"4B,UŌeI/Ca8BeH@쫣Z(eqjS&i@7ʡXs ._?8q"ia8])*i]֥;Wy4+)`x[,1nwUQ"8,C;l+lX%S  @/Eסj]]M UӉŪOn) Ir8ǢakSBrtȑwS,k3ntotWi]֥;t?.މ{]1"Cqkܢ]Ѣljtr8&5lD; #ܼg6?X%S&/K}f2sM@Yz$Z^;iT4\86N-TJ|]ƃ bYrXǢܪ.\sӟ"GmqPӐJubotaWWÜn'#~pNXq_tۭqJ' 9!, :21Î4)+Z=qW^ۑbȼaB"7(/őhjeO6 'p{m{~=U?iTvۗx^vԷD58ꆺ;o/2}ŪORk0\ ׮ܺtq=`3 (i",Xpa3tN_?!h q tqè{,`{ZLϮAo@-\X5kooO#$E(sqky^nQ{nT>eLK\|őǽe޶߲mbO1PA drp/(# ,㉺^h,EZl\fsMO,8Ln㰂beƛӟ"GooU$"D/ott?kRǻ_m4. M0;\X5ȷ'꠹x mWwUBCJJ@OFv)|PfջdqV!^q_0q7K۲mҏ7#ŪO>U}Ę&v ӎ1M[\jYeTtS+jPn9|ssH;UɄ]/3+ 8otD?2ҳ:Y`Ju֥;A3 ː X5`spmx{7(lB[ő:UP7Ŗ,U tm(.b\@ÄXa=..״8W;Utgo?q=Ry*[e\1-!Dϑ#6j<>gg|k a,Ŷ_m7LwU`{ZLKŁ]?ky^nQ}#Et/eqLOre*TC /C5qEДiaA  g MusC x|ssH= 2^8]H5t+_.s9f[m: wq:9{Ժg^,9_ǻ*r=Y.$QE1۷n.X%S 2/q:.qv\J\TJ|^k8 ?5x\#~sNXR9G8:R!"GaYmmi,^\Bݵ֥=`xiڿkR鞃xgmbO0StiRLZ q=l;>D/%㉾53{GԺg^,9_ǻ*r=Y.uUjxn †4l.g{U8Ǣrtȑzeq7ƺ!pCs:Wj]3sZ֫l$EH,0V?Z֫F'9+7(⹙%TI*IU ԓ $Q$%TI*IUJUD$Q$%T7P$GU=IJ?dJsy0 bn[.Po \V g`Tc'bw%>/ANkGCh?in7h~m͠m=ӟ"G3 7j7FS#-y]~* cj8k9[֋\3խ6*bjsQ{0=KnN*r,UDŹ?_t^nQw%U?rZ#"G+.8.VJKUsH7%֥7'yEܖ*TjS܎|Ժf7(Y*-TJ|[ϑ#ܕ`{ZLܜUrX%S%Or9$kR雓ܢKd~Q)nG>DrWj]3rqW]bOܖ%>-ȑnJ0=KnN*r,UDŹ?_t^nQw%U?rZ#"G+.8.VJKUsH7%֥7'yEܖ*TjS܎|Ժf7(Y*-TJ|[ϑ#ܕ`{ZLܜUrX%S%Or9$kR雓ܢKd~Q)nG>DrWyOg$S۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠On=۠OndSf 8U@Ը&5. pMKj\RԸ&5. pMKj\RԸ&5. pMKj\RԸ&5. pMKj\RԸ&5. pMKj\RԸ&5. pMKj\RԸ#Fb,%C!ΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔG:QDsΔDh D%31f03fc a31f03fc a31f03fc a31f03fc a31f03fc a31f03fc a31f0~K`s'189Nbps'189Nbps'189Nbps'189Nbps'189Nbps'189Nbpsŏh=J.@Dr#G "9@Dr#G "9@Dr#G "9@Dr#G "9@Dr#G "9@Dr#G "9@Dr ;L7#+ ]0JWL`%t+ ]0JWL`%t+ ]0JWL`%t+ ]0JWL`%t+ ]0JWL`%t+ ]0JWL`%t+ ]0v"&KIZNp%-' i8KIZNp%-' i8KIZNp%-' i8KIZNp%-' i8KIZNp%-' i8KIZNp%-' i8KIZN ۷ހ]1e5E  xzE _G}Y*g RXHe xpFc֖r3a+䝄55pNRSp׻tnخ'CKIЭS4]J-/UpY [zjQ"Cp5oD(^$1Ơ_ez8r;1+K\sqN"wYz6b"U$>Y yP{^ -6M"]pacif띜ԏuG@Af7zQV9+m{絥tCfP[ ?ƾv wP]FFCKIЭS4]J-/,87Wbj1C/ IN2NCF"vz,Z9͖dJ$a@}Q]b]wr&b*c7) J)~24Tz0чc=۷n]?{Z[OmM^ Q0K:[E UR"8k:WuMXmç(Eii:}ƔmRK>\%3 7Z/Kv Ų#}N!ą{|u!ل&=8c!X@EgMou!r5Y##fRͤ0-4h*(_k<.,[ړb7qɬa#T( tVfW5x~ŢژJ<ЌAiS\0QϷ]bha$:g c{Z[Ojɦ|T­xGzۗ]Q3:Wmur=8Ç~5DYKI\;!źK6T"k1J޶o[-i7'qj',M!t/}9v}kV?iSvۗx^v458ÂߑO ^*Kb7lYJ#bjmɬ{{btN6gkqۖXZ|q v;_i-L-/L֖خ d/8ë>_IОRС܃!+M??Cvג3пJ9% muZZNh,qRK&Q~w(Q#IDH:mū -n-=~S0w8 ,kX+쇆6"a7+0l<ZJ81$”BD KIS9aVmJ'=T"Y?=0t0j."6-ęb<!uIV:-a/[)͐EqZ^5 \F%B5W ت~_4F2̞1qrwt4Ro߿ /$(x㉫>im?/$Ca8zfVۥD_gZJ--'aw.K!,ꇠREWu[,JRv;kV?]OJ |Z|$JwS+d2IIq&K6_{~bQ?WG(^p͑ 7qK^&:]k!ČODm58ⳃǵ f:# v-˶<\p;u|ZZN -B_KI:.-_a:=,[C uZJܕ*H~ާNMf{Z[O֡ҷ%J-/r_Y֖GtRKܗ~nj+rT"%z95im>ZJܕ*H~ާNMf{Z[O֡ҷ%J-/r_Y֖GtRKܗ~nj+rT"%z95im>ZJܕ*H~ާNMf{Z[O֡ҷ%J-/r_Y֖GtRKܗ~nj+rT"%z95im>ZJܕ*H~ާNMf{Z[O֡ҷ%J-/r_Y֖GtRKܗ~nC1111111111111111111111111%q&Zm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&bm6&`kLG*0PhM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&hM&W$șLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșLșL篟ݸ r>N !015@QSq 3AR"246BTar#c$%bCd?t4a|< P$?z{T=ǽć_Cj!C{ڡH~=P$?z{T=ǽć_Cj!C{ڡH~=P$?z{T=ǽć_Cj!C{ڡH~=P$?s>=q=|3T\pfj+ Rq\83wKnr.Wڥ7{T\pfj+ Rq\83wKnr.Wڥ7{T\pfj+ Rq\83wKnr.Wڥ7{T\pfdgúnm|fqyhm|fqyhm|fqyhm|fqyhm|fqyhm|fqyhmq.(Oi8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8[ɣ8YT&t*Ԋ_vv^2~'tU?/vke7]t}=}N_R*=}ӭxn{W Uz[w= A;A}Hk_Ne){wE_Wa־nSuO@7G"ݭ}:ݗ뾟茶0o ~ f{!9XTm Ϋ[HkXޟ@'X\xY+ c^BQGȪ9k:ݗ벜PyY(6=Fkm0L-0L-Ɇ A;AbKB;љD>A7Pd Ta@Q=R(W8(0 /&K_vW73!r`eV:g`-%{0sbu/Me1YʼnӲt ? ^X'tU?,TOCf:!*LaPQctgLkCD:.wec*Ō ECAEn_v]ICäy4 qb,C`*#`ϔ1wAAJ;,d JD ԄܕwXnSu#q@vJp#8ғN]؟cITɣ8X{7Gt5pmP  4Ǘ=:/|;igdGƱHkYM>taƾz'[v5) '5h@*>*6iI]'OP߮Q)CBݙwE_WVEږ?Ȣe ' &ⓠ{ME]ZÀ1șmhU1w.~c]T08I)udl5e7]TEwfrZ lP-=t˂t 4)$bz-abD A;AdYb&AQA.WYBy3U>-XUztQ=1`t6Z/^L hcu/MbEq:,Ne)+T'5h  €JwL:+(w:dJ D^JFQBqX թCMl,O|`t*%) '8DGAvP~r/~_.\&Ivk5/H *'[vϪ ]5 cb{W Q&_C8VH!JNw<,ւyaj?ZO֑4EJ~YE]ZylۢtNw7J( ag&;?ӐL?:(Kuҡ,Qu2v^2²%PCӟ3HE-:uZPWb,T ñ01?]؞ E+1"\o(&ljQA04ܒwE_~PN-vE]Z(\IQPz( &d| 0rζ!-xn,w'=t=Cc~?ws=wE_Ĥc;qm7b` V й4qQ (j)vk8N #2![Co4sR[dY&du/MeU"f#,Sfݐ gTǑA61)mwE_Wa־nSuO@7G"ݭ}:ݗ뾟茶0o ~ E]Zu/M}?]O|`t*Ԋ_vv^2~'tU?/vke7]t}=}N_R*=}ӭxn{W Uz[w= . o)yHDR&07L "`o)yHDR&07L "`o)yHDR&07L "`o)>Jfygj~ygj~ygj~ygj~ygj~ygj~ygj~ygj~ygj~ygj~ygj~ygj~yghܰ,1u` UgV5[lGsUgV5[lGsUgV5[lGsUgV5[lGsUgV5[lGsUgV5[lGsUgI9&p4Ǜ/_ Uךku橣5ZyhMV^j?SUךku橣5ZyhMV^j?SUךku橣5ZyhMV^j?SUךku橣5ZyhMV^j?SUךku橣5ZyhMV^j?SUךku橣5ZyhMV^j?SUךR0f\fkqşF֫[,6Zqgѵ>VYmjϣkU}Zn8kqşF֫[,6Zqgѵ>VYmjϣkU}Zn8kqşF֫[,6Zqgѵ>VYmjϣkU}Zn8kqşFփEG±N_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hN_RS7ZCTocöDo]k'hNYJ7p9eMn`o[9f5Mn`o[9D_HXrdt"a "_ş!.zb\5X0=[#.2 +#b ٧e:f(Yd\ְR(~Uȏ~"˻(*@~u f+:x9[f^@ =d P; u!-5/UO/`aPoW&^Q:塔5F] rp(t|#ق8N +n3<&77r` !5X0=[ ]¸I (t8{0SB HfrZK.BX$zH& [7 mI2 G;(ZT^hvӓO%vCprA0)$E?I|ZWIE/>>áw-'dwfPD1" !c^^, EA6W^immMkoךmZ#t+rWZCTlT$UGstRagb~Y{!DM0 4)ĝ9a!iQWxKFb>;dOVB]=eLlTNhe QP PƜk& +0Ԅ36~]l9lRهlءxGdP9g Gw\)l5*ʾynzg5*0F`آ!urfOpc&FtYWEeͺ0C~Em),;e+BMuS"@TXGs1GCZ'h,% 'P \ H5Yzy{=`h;;.^\O2e992Xrb{&"\8:}@d>G9UIwDp/,}vȞqCJnM4sŸ>g* [Y'tʊ!(Z T`?>E.BXhEr~Em)u.nCN,X~7 'hNXIn,Ӎ(jahlRS6I';ZzT\wtI^P4ú,}vȞ !j @ʅsJ1@y hnkzgE.BXhEr~Em'u5 mvv\UIhBv~v:#vY#C[ R]&ksOW/|S2rf"a܃i!r?|"%ܢ!a"z(,wyNP0Q]8mgjF&lZNЙ4 ZV)@`ic) s2(|lQc\{)Qz}N{">ru96tRT2Yϐ5گ2򴙡3ٗ)! rO8ʵf4~.G5M,9<*\g|;AbIA x)· XrS69).۱jCv;zNhe QHYg+F8vO tQA݌.Xa6)cöDlT)h%$r@p4~>x r|qc\{)Qz}NJEao`p XA]ӆM4H**iCSPwaóCZ'h,`31VG d^^~ h Ps-ZCTlnGSnɝ LcɘWsIS?nEY[M,cc>;dOV_&-ba0VQCZ@DeQ&Qq[8 aK8^]m(U69'hi_mѭZ8DuS»J?&t]0Se 2_&(2^Q?jZP; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P; Yzy{uC(j,}vȞ8 }P;Bm E ğ1vYᘓ.֫<3|gbOZIkU>bj1']Vxf$ ğ1vYᘓ.֫<3|gbOZIkU>bj1']Vxf$ ğ1vYᘓ.֫<3|gbOZIkU>bj1']Vxf$ ğ1vbP:')P]T(n skU B1vP]T(n skU B1vP]T(n skU B1vP]T(n skU B1vP]T(n skU B1vP]T(n skU B1vP]w*URNQ;v#A[pF؍o-ñ [b4h+ynV;v#A[pF؍o-ñ [b4h+ynV;v#A[pF؍o-ñ [b4h+ynV;c"wrkV$3x7,HfnX ܱ!bC07rĆ`o $3x7,HfnX ܱ!bC07rĆ`o $3x7,HfnX ܱ!bC07rĆ`o $3;-npr6]ez W|Ysޫ,coU\.`wŗ0lm˘66]ez W|Ysޫ,coU\.`wŗ0lm˘66]ez W|Ysޫ,coU\.`wŗ0lm˘66]e/&;e7e-;۫}Gz=W~@꾠 QÈvn[\w_V\z:I<}AݗԶnu_Iy{-G!)/mq~[=s꾓$Uo0ZCSv_Rz}'I O`8l쾥uuoGOԓWݾ8j8qM}KkQ랏GU':7}>qpRmxXCc&` mq~[Fx#`a`dODMYX s"lX#=n8LƬP`<1LJ._I1aOԓV)X ~ ;NӴ70ZCSvX$dyv>j\ =@X=wu,R=}f8CzTw.æxz\?jTm~Kk$^ 69GfhD$rҖWMlϞipru> ^{tG̹+ҚLRaA?^z`Bz4ĵԝNtuRAPB򳄖E:áH S{"LZ53\4I<`Å L:!/ΔJpe@Yw(5Cq1x0Lxo`8ljya19 9pE&P"a09guuӓ2Q*w ܣ %d{%-9ٹGN6 mq~^yw;@L&,{)BO6|DDk ?Đu'\g&fI16N"0DmeǮz=\84:Vz@ tuSE|a)>d+?&4槧ҕ%wQ2cOԓ\7g1=sZb& o`\ƜJp X-&Ɯ;8)&s7g7Sӛ QÈvn ^ߢ#h VDuHWx6J])D"R g-qFQGn H:&Q|,ɀҔy+? m4}Q53)etNOUN'kDbkW4H؂35nz„W(ɢqdK9hC©lDiJo\7GU41}'76=*L@I ]A1wCI3҉[,͑@ ]8RL,O`8lEPmC ZEЗ_TzNEKaA(4qewk E j J6 mq~^xAh~]܌T⢃8HlG'hҖWMl)#3K>tLL\TSezp"| PsgJSz:7H  I06˥R`8(!JRƊ`t/ ?RO up}r0,Ņ'0i3ۂt4VÇxkͺb DxP.Ti 8{0N70ZCSvXdmu JYg| zOhRov [\w_V#nb9;iK+^ 6!8@ I8 opRxp= 2Ҕ޸n4׵b+[{qUnU iyŅ'0i;,Ӵ3Jp#RqtJ>DiMMpo ݖr]~RwY7_^(]`հۘNR魗ʠ!8I6=W0#~wGA9Gw^K|8G&L=t7yH1eS` mIȋ))':.qp#nK^R=}fKW{B}ElsJY]5RrsQRNai3&Rl{JUA/@*yFqYd&q-S'y3j?sɜKF!*9..za^^R JUx"g,$9P6vVO=`1htPLxf-y˝L<$Iqpվ=?RO u_Pov|;e7e-;۫}Gz=W~@꾠 QÈvn[\w_V\z:I<}AݗԶnu_Iy{-G!)/mq~[=s꾓$Uo0ZCSv_Rz}'I O`8l쾥uuoGOԓWݾ8dq_5D}8'j;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lj;|*_lhd̄(9j՚jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱ!-jbѱR1XsL&U5D1i:o Q7ZΆ-?CTM&O|ŧjbt5D1i:o Q7ZΆ-?CTM&O|ŧjbt5D1i:o Q7ZΆ-?CTM&O|ŧjbt5D1i:#_ HtIyQ<&~O35Fx 5LQgjD?sTj'Q<&~O35Fx 5LQgjD?sTj'Q<&~O35Fx 5LQgjD?sTj'Q<r/v?\ 70~sx70~sx70~sx70~sx70~sx70~sx0qi}P/uzm`_/9T־y}MN7Q| Ck"yʦ/n[Cjt_T1`gv^X/KU5{vrrS_ C;}Hj^r}K۰ nX/ݗ ERMk^݇܇辨cu:}Pd6_R/ڗk_R "^ī"")\.zr#S'7Q| Q+ݡmnhu x6JBܔ2v*.z?Wg$GC;`ұah>m(e+Io 5)P%k 9a,Q%Pmh5*"lX3SJ'nrf*\/P7*&lȿj^r`ah>m(;Qo 5?iPk 9g-7unU?D ;ʃ6Lb۴`u4 :way}MNvU'I9ú5poTK SqH.y)8Öx6Hs?&3C@cn矇CA"nya 3ʋTTg!nJ;Ftvpj0;T)ڥL/`.v]-ăJHElr~ CkY ' ݼt/坟_yTV\Әi%k 9Y3Ae` R q reP&q8cQ4$g7I ERMnB0|t/坟yTV\ۣ-:TaDR2Z(N= wm@rCNZ(iǦLҞ3xBtR49az:۰)N_R@{6kƋTNBZD# g]c*nVb^VssM4µ7Q|)j|IY Rdٶ|X$QT)H[NKbjӰ)H/D 4pid6pc'+?_0 c[i/$bR G iP%k 8ۨF0 R<ΏiVHg(URs {*k.KF0qgWs,R% إ&Hj^r•Ϫ(XyS km%dU]A1ٹh^pWpRҡmKTHyˈr)PW{E٭i  KH9\bK;ўp5Z$" Aq% a—a-!5:8g( 7%ѡVQD)DrPz3ґBEԴPh8ŭ[}/ᥜ" <$<:EpT6ux .쟕ݓDA0Kv_(u) rP<*$.Yd (r5\ T-}JnMɹ T,~*1rfDo1u+A0f Ԟ `uy}MN g4ި@,3HRг5u-RRDp?'+cu:aWY|JBܔ2vTFAG^LiaZMB7nA@(nCC;aeW T2}MdgLPiRЩOr^NFa;XG+9$*(_/9TְF-*Ta۪AE@P00BʺiݎL-((O<㞴RI"n9oaڹF40zxjزiܔ+1 ɭ4]NZ PEwnppcu:aWY|JBܔ2vq W2 b[; `Npj-Pd6XhvUuB 2_v1qii*ԉ2!۔Xv* Ćo*^ #&x6ґXZtJk ERMk nnRmKrPt(rC7ģ'H F!r8!q"#ݚu0wr3y}MN g4ި@*ݹ^\0ݴAǛJNg$T1`˫^!nJ;GGu2 qGy\'l3C܈NBk Cke_T)P%k )t(^\giPPOp5:E(2nA0(ҡٕ%3 ERMk nnRmK1v,%t |(RLalk^Gy\0ggd eH&K۰ϭiAQ,ItAB hYȪdl546V;O!*ݒ/tfUSs[E(p!m;" TÓCA R䡓xWN$p ݛsRLvߎX2vݗ .ʿnRKR-_ }+ӅPM+y3?7bX_5ʏ1d avCp_/9TְF-*TaP5]ɦm¦Ɖ?&qۡ~-,Hn9vR(15BV.^Q9{vrrSr(7%)8K ,F!' ğ.w `/u.{(dodA#,*[0&4nܡo/-we!D˲۪eq*(gBΐ׭pd5zPO {"yʦ7ioT)Pk :1B}ng%v3;;&`A1Bpy}MN ėtP⡀goAgt 21gedS&bH=8]Zl1`Ĥ =s<*7ͪa 9M薜Z8hy wX9k۱Pd6Xc /++6vqwd=Ed$-wJ%0 ̭GTc%A 0Й siN8FERMk f=<炳T7h:.uwCU`xTMZimQg\y;nZ(q ;l2/F|^_:0taz5|j!чCѫFW>/F|^_:0taz5|j!чCѫFW>/F|^_:0taz5|j!ч?RЦ&\7TIa T(3]R]S;<딛pRӁ%3]RУuJ?uLһ`Ro%uKNuK+Bs5(3JnI -8XC5, =T@;WT+1&\7TIa T(3]R]S;<딛pRӁ%3]RУuJ?uLһ`Ro%uKNuK+Bs5(3JnI # %ۄoqs2J-8XC5UFEGǔE?کY%GʒFPBG6!g$D 69GwtNTADTl[-QnFź)"I &3һ`Ro%b}iaC"|9iRnK(^j<\LE R(=$XP>Aa CbVk,)}m˯T}jV @;V)%Ov#%IXwi]y)7A"=YUJ@83Ĥ(m&Z,5PrN ` Ia )%:A Z))~ r//W0gYxLESҩ~PoYZ{>N A!vͫ@(K:_Z4(dSF@6a9WHJjav ^nl` ;,qgvry.L 4ATXh3Δb ,!#`q-ҡ~PC+(3X]NI "vH{P.F@;Pީԭ٤9GwtSJ*crstW]SCfݥv7\Kʊ&PB$&LcgǏjKNc}BCAqu3LEsLPq#E$F0YZ{s8>ȟoX>#|9{sag2ʍC"D#<)˵[H,rX"Z(eIP>C3V BFdC4SvO|ݻ+1&\6BDhBa`iND'mZp$k}K9t1 9ehQfH61'wW4/S(]ޱρUC}jV @;V)''V#Dj( pcQF uys˲k&d %ii'F;.Lһ`Ro%c)DF4"9lӢg$sY%Kf,bjX% ,,SiѡR>#I:YBʂ7 , =7CQOtM&Wtzţbc|c3CI v~Iu@)@ygJrppz1R2(P(QJ?c W:f49f2H4TOty@wtjv)WlcuMl@vdO4fHeKfH"PTgK<6)ehQf+d ن(a;J px GdPLһ`Ro%b0ݜ%) Ac2zL~fOV(Gb ,!Y,R 8vhcg9 l䛺@A((3X]AR05pb܅_rSW-}]M&%E$VRDyT]U  2&fIEv(x,RXĠRm)sx0yRcqp Q|T _;cAܮŠP4_fcDC-gvry.!vRz.Ia (+j;'Hj43lhmGezi4M#bVk,a/JݚAcHwJ2FœvlXNiy52 6cݥv7\KG^9W{{x緽^9Zp$k1FF#)_T{vK7Pǖv=DN#dVk+҈ 4 V1;~xLRYQQ +jLQ,4˸P#Y& ӇyP  M>> DG3JnI -8XC5, =T@;WT+1&\7TIa T(3]R]S;<딛pRӁ%3]RУuJ?uLһ`Ro%uKNuK+Bs5(3JnI -8XC5, =T@;WT+1&\7TIa T(3]R]S;<딛pRӁ%3]RУuJ?uLһ`QHe#Mp&5x/Gɭz>Mm^ kj8^[W|ڼp&5x/Gɭz>Mm^ kj8^[W|ڼp&5x/Gɭz>Mm^ kj8^[W|ڼp&GwGdV 'Qjï&]m\u؋urדb.\:lEˇ^Mڹpɱ[W.y6"jï&]m\u؋urדb.\:lEˇ^Mڹpɱ[W.y6"jï&]m\u؋urדb.\:lEˇ^Mڹpɱ[W.y6"jï&]m;uDExEu "ju]Coڮ]mWP.mq[U68xEu "ju]Coڮ]mWP.mq[U68xEu "ju]Coڮ]mWP.mq[U68xE>gR,bQ(ox8r{7q 7o9y @ox8r{7q 7o9y @ox8r{7q 7o9y @ox8r"DVD* gKq{\@t7/% gKq{\@t7/% gKq{\@t7/% gKq{\@t7/% gKq{\@t7/% gKq{\@t7/% gKq&H c]/CwDnij4nZ05 Ǽ+_ZnRջhF(`.ku͏yw>WTwѺjP\T'|}j#uKKV٣uԡO%6=]R;wtFꖖ߳F5Cs]PKl{˾v--[fkR溡<\|#uKPZZ~֥ uBx9..G}_mLl,&-R^"D `P J"4{6!ov<͈[ݏ7bc؅{6!ov<͈YgES *C--[f i0h,;0֥ dMc|45>ై 4 Ǽ+1CS˜}\pdrvODlr;wtF~S'--[fU`A 7W0L~QrҒCra@ܜC,F(`.k=!!3w"@EG'crX|RJO$T>釩SA2P(n3.Ɋ˚Ii]u#l~[=M]ewUChyB]_Zna kpZnp&05t9ɠ1 @(5(l|v)ij4lS8r(" ST#{2R SQ044G=B(uΖn`@kR@])PJRmed)L]9Jf}v*v(O%6T,Sc]e0E^D6sܨeb=;L:"@tT Wb~+H7؜ SmS)6zջhؠn9LYc(qP3 }CprH@58hcKJ FtsU9ѵ'3|S*baZK ks q̢=)(yQm8c MNHS&aKǫ/CwDlr* )v3<_NG_p0$n6)< $rfa -(&w-12aj:/?7rNCPI7w|kR;:SRqyrx 4 'A:n>&Bx9,#86TlSc] Y(ei5+bi$4 ^0{ o/r!ME]^lcKP fq:iяhW2lpe߳F$GM'[;=&DD6J_hV2ʎ؍jP\)?;6DF{{:ǧ=apMyw>V4:fh3Ң(MhXf&˸R vI}j#c,Piu5_ߴ(eT&,n678D t@p 3D~gcX( kՌa63Z05Ț~@cJh5pPj).G֡ۻ7Tn7QJ r]sc]/CwDnij4nZ05 Ǽ+_ZnRջhF(`.ku͏yw>WTwѺjP\T'|}j#uKKV٣uԡO%6=]R;wtFꖖ߳F5Cs]PKl{˾v--[fkR溡<[FP Ѫ>a1z5B&/FT 0ST*|bjOL^P Ѫ>a1z5B&/FT 0ST*|bjOL^P Ѫ>a1z5B&/FT 0ST*|bjOL^P ѡszr5l:ѫaL^[bjuVèDհ&/FQ1z5l:ѫaL^[bjuVèDհ&/FQ1z5l:ѫaL^[bjuVèDհ&/FQ1z5l:ѠHZ_s6jͭxk~^/Fߗѫ6jͭxk~^/Fߗѫ6jͭxk~^/Fߗѫ6jͭxk~^/Fߗѫ6jͭxk~^/Fߗѫ6jͭxk~^/Fߗѫ6hS n{m0ITTmH.C4Om^w>@g="j=3h @P+%0Fꗶ4uHuL/t?T<JtL&Ѻx &~cR/sS9 Һ>S n{m0ITTmH.C4Om^w>@g="j=3h @P+%0Fꗶ4aj`QHaoh^Ve"Υ2 ]ETl9 7[ڗhl\ A)ax/뒃@{6 C4&0{rrsdcn'+;7Omu9X <olNVolNVbQ|{F*DꚘ:UJBv'26:Mo`|5\_l܍TgI|nY!ncϑ5<:(I` mH,S;ÓTh8ӭ \pNO8|z* cF]~˼0υƋ\XHE8PP8zg ~xfUKHJT xPu/qUqygLѣ "B|Eۚt8+ 7OmԽoQ5i \ZO*?Wc=_9{m0I8p #0'&h\M>Mo`|5\g(%iPٹxՕXNq#>LstL -pQQIMsqUsR"Z" q *+Edñ= 1gA_䊇n mH6r]EL=*Ƣa3Tnq M}0:4C?8dO~V1X(n)7:x'@P-Z0.Ο ?jcZ4{Cܱ)~#|Aۛ pWnY);9a/į'a(ja2U)aW1S (R[V-\mZ!qϤc5<Р%=a4&!: 2DvV1K:* I m0G&`Hϲh;ytᶶ-(HL6`&x_9O>Ї98$OfP (( 6se3h AG3@ZNIy=ZYCs|:!yj3vMJh۞iZ+<&xg ~xfX?+Pҩ9 m֒r5,*A@n =M4:;RLѣœp?|{QS,1ŞfB}9'LC~ͳtL&JsPFS9N`WvLh snsX(]5i1 ;Ub#b441ZP φt;x& (y^ Ca@ җz.k|6 7^ڍ[$S(@@&x_=N8 ź8g3h jgF]]l HA?U;3NO89QAe(:S+4XYw#>tRI iJ;;{$N[9E2W{8Qg]JPi\ *hzh4˽hZEs_J ViDa@3l>S vrghD^u6@hksQj>ijSFJ]5wtݐL tGs[H=^D}J6ngGėLDJ<{9{m0I|30le.\3l U92+t x/ϩ*;@ш{C#QO%Ll[9EXfmTyj; qmWԠ: Qhv}'v=VŻ!:eVϚ챥u;EE#(`!Hi*XS$?9=|զ:1 6%0F5{k9(]47%UUH ‰(O!Flx &~cb;·opΓ[X$_ Wng%=b@T;E %DzrzL/t4;jf`3TnqD$L=c.~!Rf֍LɐTs=5! ,.^q{+$\ ;)C43UwtBtʭ=!-%A!NB^gPhvŦ^Hj /SUMv:g(MFvt% zT "!WU@'Om t@g=# vLK 5Ep{ &x_9oihuG(CpjKx9=l39 ک٘'L'ۜvrnSy0h@P+ m2F{HgMu󳘇 x!dMaZlʥ:ZZ9<$ iJm"$18>>|V@P+ m2F{HvSr{ΘxAfMaZN6PHDx[;nLǰ@{ݒLP(ql^܈P;{ݝ! 4I`|5\%PUPE6st" I"<$(-Qn<-ǐqE6A8ڢy88&$g6|q|\^3q*N4UD(f^e `ũR~2L>=V=<_&V 7d!uwCoe({TH/`? 5hxNgHY G@;7Om nD8D4ۛZO4 Bwwgd=m `#l1{CSVul@γ%hcP4.sݰKnLǺ_ W约sm:AuH?٥u:}dhRۼa?1U9E]Rꇏi]NY)7T|{Ep{g6|TWSJa6/m i3|5\ʹ_ ~xfMuKnLǺ_ W约sm:AuH?٥u:}dhRۼa?1U9E]Rꇏi]NY)7T|{Ep{g6|TWSJa6/m i;{}1hP۠Z7 Tf!j-Pqx3|Ao8j[UDO:ڪ"}$!Q'I?uTDIC'OmU>j[UDO:ڪ"}$!Q'I?uTDIC'OmU>j[<<(EMDGZevJpջsQ GYo;EG+VuD7fQ<m;tg [=τF]xҺ5nTC>VevJpջsQ GYo;EG+VuD7fQ<m;tg [=τFK;%(CpA%wV0{B -Evpn{  .8c7fQ<X- |JrkhUwEgQ1kHfJi"S5JQ>e<%l{9m;tJ~-Eb)IF#t82x|rC8jݹ Z&gӮjc΁bψĊ^zUog*Ȩ/ͳo61*eg+fThq0rFUSsb;>hr]46Pz΅AOHJ9U%^$iҘ9(l]xijGz(:ퟗ=YuΡ F#t T C1@9T C1@9*!8]\Hۼ}(g [>'*_6ʪc÷>> 9O-dhQHvBгšp7h 2|粗8 +#IJGd~U$@hNi((ۀhN-Ca" ,R. YIҨb&jd V1ʀu `LcA6Q F?L}_yՙé߅Gݥ$R@Ҥ/gI\C4jak8†=4Ug3PTL%r-_Gd.AA`:44wg"nC;4 ;ȠDL(4 $mr8 YpQ øp7Go; /sΓiMR6)q^T4{73>yZ!']B!:JLU~ V[lV:Hpyc@su:|XX"(h.<lR8jݹ1i> YRu(|5tS=KEP b!cAOfQ<2ؼ~:LZMD?agI ?84€*NQ!ˆ JH`9;Xl'IgVǚ6R.<VxATw-C>S(WvOl^?P&-s ӞFH p;wStL@`CH| 59nv<.eT2gWcROtvDpe"nVN6{ E\#:gpuLo=VapNbΉNP;"De_R Q1&Ԧ Єio61*e)Ůw!|o/C| &]qM@!<F~ruȻhۥal>SG>4A s#@ GR!LJ v8I@1gaLtͱA̠Ө}C>e aeaնr6st"  6H PyN|l\4Hs!dVaЙ.嶂{|`vJ#2 g";TS zoI * T ?qqEB@!bpջs^a(zsܩ()%cIĸ,Y6H'D7,7"n v红(WwTWT3۞o?̣}_yR.$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$H9>$K4ILSDTlFg+TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTrY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvJɏ{{L6j!nu7$>rY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvJɏ{{L6j!nu7$>rY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvK|_O(Ifܮ\P\(3#`_Z|$7msoGW)`nT~cI7?mH{P5.dyu}@.nڳ[|e%,KL9WDz"Եl;HEbf#rLŲhΎ29s &*P+BEeMKInkx-% 'vc柎K454IR蝡\/&\/&\/&\/&\/&\/&\/&\/&\/& +7_Q%%TO>܈+8։ssZe)fa_r3h5(=|=c0ͮhP +fWJe2 &RRxyLR¢r3ޝ2M A2:d|g:2 kU" NI5k13[O YAvu`8xL, 9z̳~R?Qd_w5o1Hf!\?5}ǹ|Vq#ݭˏO 7MGL*\,z]응W>o&=3 ~l5 `[&XLL%I$~q+.}g:҂DJhT6΃+4L(˿?!󗫜GW|aUӲK}ZJN$k>ӎ+ Eџ>܈+8։s_OSeo&=3 B*Rр˰6q;ܞaNZDέs̍|g:sηЦr/?!󗫛CWpqB}m( %=Q%kx-% 'vc憟s8p'>܈+8։s54IhYJ2:FF?Fr6(Y@HMܤ}*&Iq#h8XJrE_D3kL2qݫ8#N/(9iLϋ?!󗫛.1t\=ip}縈f4IIwnGD"&Q3_+Pwm>i}p6֘"8Dwxr"GZ%AlR 9!PzFt⪎ݹ%'9"|L{fJr4^j'BnG4hڳ[|QQ S J XrnU'ZrϚ?!󗫚e))fgD Їkzwvw&2]*AN$=ഔ$yIE݃yU9YH]Q#4H[#UmdjOkn1Ӫ:SgCϛ>܈+8։s+{-"W>o&=3 D ? )IM-ף8]c9nlD^ho/z{UySkY3>=IJfD]&aVvanB߾Ӝ_+Pwm>hڌܑ:)-=)0̓?VR:i>;\EYďvKI[i䊾y1oif8D&^.QqΕÑp ۅQm'j!nufnŴN}< $t[*hjD^fTRϠ*&(޴=idZv_w5o19GsҧªG iLiQJ0G}$HK/ X?BZz/ԕSJe¦9$ 孾Tpnixr"GZ%$촊rE_D3k )h.oqwN$!Y2=D5g,g՜Bm3Rx?#P5C2QA㺕t|gxr"GZ%$촊rE_D3k" )^%ʣp7}Ogx-% 'vcqR5—d} +i \EYďvKI[i䊾y1oif5D$"=#!H*j.HdAJU3gVq sí4Ov-?3C/W2+3 ?$|&c+ G}%oqD_HwkDĕNH7msDBB uÔDCȧ /QwN.Eȅ~S gDϜv_;hQMص#uy 9z_h?֮gx-% 'vcqrIg+Р{,"Y 3$ IJ/3}ǹ|Vq#ݭVZE9"|L{f qQ g)ȷ ~E8䈑 Ko;~Y-ξgi'Te f~!LL8JIn,b*?'Wj J|\$ߒʗHrd9@Y?P,(OÔ 'an%Q$\ĩ}93?3՚5/(O$qJ4.gx-% 'vcpr-aS*r3'OHQ WG: Xi=e(8)h윲MjQNCM=z_W4}ǹ|Vq#ݭVZE9"|L{fَN"-K>QK.>Qs7՜Bp:&bZKX3e Ζ CC6ҶJ0%)֏|w=\_w5o18Oz-ntM BRPi(J0L%,hNcǾ;VTS**>RuK_4}ǹ|Vq#ݭVZE9"|L{fw\,}ޢoݫ8nusK<";4>hD^u ~NrI| IBIݷ'4I.ɠ嶃M~kxr"GZ%$촊rE_D3kwkDXE߻Vq s뾉VaI9d| .9D ^~KhS 5T 9z-9%kx-% 'vcmC92g*YLPl4s+aꬥi;T@Dw 0!]MV%%(>܈+8։s%DU9t%3bo1!$DR݇9i%RAsy1oif3f X40R${B *ث *ث *ث *ث *ث *ثȉǎYoݫ8?,۴t ]CBKW7y Oa1 ML2_uN9|\ыZڦ`Ȏ].1WGxd~WG~ n/GŗEa$|ưv-$\!C $%ضacUua1IwMB\d؆\b2m%˪$7}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvJɏ{{L6j!nu7$>rY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvJɏ{{L6j!nu7$>rY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vNEYďvJɏ{{L6j!nu7$>rY8{i(I;}ǹ|Vq#ݭrc0ͫ&ڳ[vMVNZJNdoqD_HwkD3jɿv]C/Uo18{g?+'&=3 ڲoݫ8dhd$vN2-jRZ)(AJ"'(#"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,"9b/,q 7pJRYI:tU׌bcu]x*1W^1U׌bcu]x*1W^1U׌bcu]x*1W^1U׌bcu]x*1W^1U׌bcu]x*1W^1U׌bcu]x*1W^1U׌`ԣf \BHFD+qW㘯1^;bwx9s+qW㘯1^;bwx9s+qW㘯1^;bwx9s+qW㘯1^;bwx9s+qW㘯1^;bwx9s+qW㘯1^;bwx9s+qW7_Y:&= $[,ȇ(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?Pc}dRW)2:-b_Ѭ/XU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hXU+hKB%ȕ$Q|w"/!^r ZAU3+cх[G' OFm*9=Urz0haV­х[G' OFm*9=Urz0haV­х[G' OFm*9=Urz0haV­х[G' OFm*9=Urz0haV­х[G' OFm*9=Urz0haV­х[G' OFm*9=Urz0haV­х[G' ht6%%D q4N"F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=F+a=6̶JK4DD2VD8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8Ohӄ8OhӄQL̢'\)g.8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Oh8Ohe)QvT{I.] bN+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=N+=fE/r" މY9'. 5ZPFcpr" މY9'. 5ZPFcpr" މY9'. 5ZPFcpr" މY9'.neL%<%'9i;e `NE-I6?-. Rr˛4|jQ]?XW-'i>^)N-cqt ^ IB:1miDWc a 뒥I>މq- TrL>_!;rhA^"NV.,bj!\s[ݹ|VqyoDydDԣDĆkK/*Qq>7Z-A\I˺F n9(._34γZ'.f xO~ 2R,%KB著5hMz`&)&Ϩ sI9F@gg(zh5.2|ًi(G]#1 f!-T k9ft~Rp 2|)gN5<]+4-4'(ad׭nЗQ- )deHh[ݹ|VqyoDc(%%Q:xo kW5~|:䴋!s` J9ftρ&9G~@AJY4h?+K- J9f|bGH-PFc6)BAf]ߔS!z8uUAT%pN!ʉ z"/ -4v>1S 4R`TdIAPmOӝeobj%G 5Zi-v>9f}I5 j #JGn)ۤJ/4bZJH|7V.29l{RO=|dj[Ϊik9f}s(u*Lq'Rs&dX'NF>r݄pr" މsBsOa 5ZjbouNC+~]Ҩ7t[D݅v\S ыi(G]#1T^% J9f{"RJHHO^s)z"2+/)hiRi]ҨL2 Srr>T!3D­ z"/ -3(:r)۷jKI?ywH >tyAoKGH)iJ9f}An\O`T u3uEoU@u*+z yвF];Tnw'9!? |'CW3YYߴ,"QNƲT!}vYS GPa)|͋i(G]#1AE&Zz(] Ona7]" Qqrz9v"+-x \$)uڗFv0RrDɯ!o_vEYo _~g)SjNpۉ{>_o|A|AR]^~U`$!܅>~@`KJOI?ywH >tԈhݝ,q*oNe y u48"N]90[t=](jd.oL*CeO-p攪&g1KZv4Ri!Uģqe۞ʈOEA`AN@ECx-%f>}. z54rR z8bq\wq}"s/TrQ3dSV;ҰNFCmO!o_vEYq_y| [י:Ò"A2q3N,ΔLyL)L Wzyt@s/G=e&}S-Tj;g fഔ#k{5>RN^ڐ^rzT~ˈ=Smc!o_vEYN;$_h9עI9\QuI;: O\I˺F n9d3GO9ǤåAVݳm$/i;gU qt'R]6 |WˠU@&ў6hڍ">RRSK-1Ϫ l'?,jCE;J>fഔ#FϔSF;Vgb-HJpr" މs(v0$:F3xeY$Tgki2ꬦ  huҩ$C)ݣisI'.<x[i&qݦ.[lEb4NTt u4S3:D "eKc&rɈq݇M+5ha7.4prKOdxh6/t~j5|+s㷅i&v&zE8xH[ݹ|VqyoDgu=$6eH>4BdTӳr 6\iԙˣ$b8DhTUp9 A׌y u3U!hcgz=f⼊ىħ̭z֍gs9IТT/ aH\rZFh΋;>8DRBKČN)Gќ`PFc?5>RNNvSgA-H[ݹ|VqyoDj=\/!`(RE;+O,Ժ3~|ԣDERe )O=m]B搃|0M"<3;|u.Pm^v1qۨ~!nŸOJm(7EJ=\'CW5SUe3 fp%ʟ Vfe&`**z4JQl%_vSPFc?5>RNtU9reδm>B?5 z"/ -24*0mӃvm2)B4I˺F n9sl;uN2[Mz.S>q$/i;gL$s=B(G(Pm |}96M%E(H.%o۹=ʁu 3|>jsd\9?̭tn[t1g^ IB:kK; TidV̧ ]:RX'`aKGDAy𐷯r" މs8ȷ+җg.2)weA^sqg)))f}&4׌rP82"4Rt@s-}[vsz×*[yĐ u3?{3T3zS*z϶r_b4|j!^~|sN9PO/1x-%f>cQs/TTCn(G-4 4C XgBNZa98t>\$-܈+8\M6\_RtTiJ$蟰kh%葖,"D6t'9UzUZn~i$#7AyVgL8?'؞E2qs!sHA>gpՍGu.),n1t-r#>mTё|>jsf"̟;ByF噟I7atnȒV1x-%f>cQs/TRE%LG8r)r\eNQQ4l 9(hJن`ⲂFnD_A^[.fjZ*Vœ\p)7j\H_w:ϚLu*mnഔ#FϔSiԒdt$RMzfm)6}'MY;}ۑgWK~H-2r.)Pe6Gz2w*V5ipttuKq_g2 knYK?ywH >jCRinԣ=')q_"zIFfJ4gΤ!sE,*CiWr+4A(Um6-%6C1 _ZP5D} M0mВ\'CW4(E(I2:RK-bb/6ݵl##>NYt ))D\i(G]#1oA%MLR/9KRߌLϣ>uDq1.)ci?)czWii+I_1G[Lz\{ʊ?d ViIJo_vEYrO]1py BY8VMi(G]#18[ݹ|VqyoDt@srB搃vN'CUbZJHvNnD_A^[+'$#7윐 uhdؼu3}ۑgWJ?ywH ;'$/i;gd|>jY6/tdo_vEYrO]1py BY8VMi(G]#18[ݹ|VqyoDt@srB搃vN'CUbZJHvNnD_A^[+'$#7윐 uhdؼu3}ۑgWJ?ywH ;'$/i;gd|>jY6/tdo_vEYrO]1py BY8VMi(G]#18[ݹ|VqyoDt@srB搃vN'CUbZJHvNnD_A^[+'$#7윐 uhdؼu3}ۑgWJ?ywH ;'$/i;gd|>jY6/tdo_vEYrO]1py BY8VMi(G]#18[ݹ|VqyoDt@srB搃vN'CUbZJHvNnD_A^[+'$#7윐 uhdؼu3}ۏ(T8&ے1 JJQ8rNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)UrNU[G)U)kqg-J:&fa,CƼiȈrEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(9A(?PQC(rEP(]Qk9fgD,EHfDB{(_=P(We+粊E 종|QB{(_=P(We+粊E 종|QB{(_=P(We+粊E 종|QB{(_=P(We+粊E 종|QB{(_=P(We+粊E 종|QB{(_=P(We+粊E 종|QB{(_=P7n,G,ǢqS(W+E ~QB(_P(W+E ~QB(_P(W+E ~QB(_P(W+E ~QB(_P(W+E ~QB(_P(W+E ~QB(_P(W ȷKYˠPq0J0L+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h9AP(+h q-&՟r" j[h39gLجQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOhQOha3-Ғ"1䵬ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV|j1ZV,S(C".0ӎ4F!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q mJU8888888888888888888888888RTJ22222222222222222222222222222222222222222222222222 &fYnD_B^[ѲrG:ey6drY4Z܈+8d䏼9!nu8mY7|9ɕ岲h|Vq yoFxsHBq ڲns+Aedkr"ލ>搅d/d&VɢEY%'$}! s_W3jɻ>6L-EȋⳈKz6NHÚB]8fՓwØ|lZ[+&[gl4-λ'}^pͫ&02VM"/!/-9#i[vN2VMaeh9l-nD_B^[ѲrG:ey6drY4Z܈+8d䏼9!nu8mY7|9ɕ岲h|Vq yoFxsHBq ڲns+Aedkr"ލ>搅d/d&VɢEY%'$}! s_W3jɻ>6L-EȋⳈKz6NHÚB]8fՓwØ|lZ[+&[gl4-λ'}^pͫ&02VM"/!/-*1UQBbH9 1UQBbI9d|<4-ξeNTNTN2;\ Ӫ$ixwم E)%u&d> SImFVIX TǬAp?u>A+9 B)*ӈ%SZ2ˉ4t0wØ|yRHTbS"_iJf̏/Ax&ȋ V˙M6ڔ]*+1Q^)RK+1Q^)LTWbS☨Ex*+1Q^)."/!/-D,iMF# HϬfy%E8M>r؃*HWz$}<<4-ξ`kY̤BHGK'jr" a4T&a%C# Tr}$+lRQ2A/2ZHˆ8f1L|LtIvZi$4nݯ1OzMtʤVϠa`uKV=XCE,~ag-@6hg|9ǘIhj!)W}I$!(썾9DÜg~Oeel)"D[W_>-1D|2*KsawB6M4JinkA-TpRBKEȋⳈKzߜs{n$.DTZ܈+8;2:HOzEƸn8.fy@OE5SK{L*"%f㋢j:s>HÚB_ 7OzhK.ڞjWEQ%L":Fc/~  ⤻9M;L -2# KYen{/[r@s Y|DyR /X]6b9•GОz;_u@b\2`{FEg@\L&{#\Gג9!vZ%¢EY%Y@H5M.+ֳR7k<]Q! ft$* S$}<<4-ξP2>?Qjg?|=D]gDٺNvOToӫ{) Hm%ܒ/C"CPk>ib$T]2\)D=-2hL$dig?vU˨"d&&[jϸJ[R C|"LTꊒk:N4.aJ*"\4*ntB dsDH.9|s1pDKpOmRRd|1Z[.ԗI:E] iGYkfx3\ [RR!M!QWlU~QWlU~QWlU~$¢EY% JITGAkvZD&_1E$K7k:D5JM9]/SGAN$nt]jC$'f3G:G$l!34K,mjDBM TSi!e(1u~*SJmN 2T'ԗ }^pͮzIR/o`$ REjQ"aFmSI*Ӑ7kSҚR!.}ŵeD eӺ~\+&ME%FIe'Li$4ns)M3HF +{kIP9#of.(DM). Hh3ٸTFbRآ%}rptRO~]ЭM6R"ON"Z3̧L>r5C+Kk{)qX[9-nD_B^[&P^%"[-"q|TxP45%37k<5R.he2^<$ڥ #. ,i%%EH2e-JU ##}mwvC霑31H[ŚH8u~b6߲ ݒh9lDGCQ*KGBTN}uft.FH5: z=!.hFC->jW4EȋⳈKz ʚUܝ0Mmϼ'^y4fd}$biL?II)lS"6L<2 @T#$}<<4-ξRV4?%7h:EA ]ҫ{* O)4TiFeryTdēDӺ=Sʖ$gnt]_?VxXmpĸ餉%4rqg^bx}Q'5._ć(aQ?-^wDY *Pk'FqR6B4[I=.F̏LϪe$f(^ΙG\H3u NI_u@b\3Lꖆ Rg,]۶^ϜsMip:?M,F"[j8\U=2-nD_B^[/\#FqS>HÚB_1뜈jGB++e.skICRJ.2\:ry'4ϺPSFßl0'ps3~j->f"GF{Pj/q9%}rsS9]"\kdNS#R]\*-nD_B^[/\#FqS>HÚB_1뜈j rh5=ԴM)G(}+=\4ey6u3 |Ni8DϬ⼂$ZQmwØ|yo9H㙊{qidkjNu#L]q|gNt%= +[]E)ZW;>ĦQN"h/!ui>ԩFe?%z>r5Β{A"\({'^-2YL0L0 -Ht̴I).✌}"Ui"/!/-8rBzO$}! sD_5NM:AtP0MtqG5ӠGs`~ҝSW?Jv N\)n1HYP".2\:ryv.nB$}do?'ȗdz]bW?=kVTS0Z<IeL/m$ԣ { K]wØ|yo9H㙋j9$|1Z[.cWs#\mz;D2c?*W!.Hb/̌Wʭ5%Kyq*i ZiSE)|*-nD_B^[/\#FqS>HÚB_1뜈jo {F_W3k\#9@ݯ1N޾,\UQups1w 9|s1p]pȵ|Vq yoG )mDTܓxleW_xle%N%J=*'+e ,SJT>W_xleW_/A$ipG:OC- $&VϷUY¯*WVpZRTkTSR覥G*WVp8UEU*~Ug h_UY¯*WVp8UEU*bV+zg8f1r1,$z2#lT"1QB#T"1Q3pmeJ3ENќ%q9/:"T|{j{GS#ZsAHr>U;F9s-Y'_>/P4tCjCG>a1p/DDtӖd+hD~[E#/B5#yaJ5zRIS씣I/VxⶋG,ē fR֓*;-1|bV)#9g+VXⷊGV*?xO!HKpE((禤tJ.IN$849rǮ7a/FXIZs N*ʧh̵f mؕZ/:>@A 7t<qTԣ|:-nD_B^[ѲrG:ey6drY4Z܈+8d䏼9!nu8mY7|9ɕ岲h|Vq yoFxsHBq ڲns+Aedkr"ލ>搅d/d&VɢEY%'$}! s_W3jɻ>6L-EȋⳈKz6NHÚB]8fՓwØ|lZ[+&[gl4-λ'}^pͫ&02VM"/!/-9#i[vN2VMaeh9l-nD_B^[ѲrG:ey6drY4Z܈+8d䏼9!nu8mY7|9ɕ岲h|Vq yoFxsHBq ڲns+Aedkr"ލ>搅d/d&VɢEY%'$}! s_W3jɻ>6L-EȋⳈKz6NHÚB]8fՓwØ|lZ[+&[gl4-λ'}^pͫ&02VMYtGqDHAKբ|vY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰWeF]MvY4ldѰ98J> aHSWBv N\} +;q'`>НWBv N\} +;q'`>НWBv N\} +;q'`>НWBv N\} +;q'`>НWBv N\} +;q'`>НWBv N\} +;q'`>НWBv N9kpGl4ے_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W!UHU~_W nrbRLS1LS1LS1LS1LS1LS1LS1LS1LS1LS1LS1LS1LSĵ&T!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Jt܈+8BjZal#u:G[al#u:G[al#u:G[al#u:G[al#u:G[al#u:G[al!֓I 2 D;54(_|#u:G_|#u:G_|#u:G_|#u:G_|#u:G_|#u:G_0*d_MM,|#u:G_|#u:G_|#u:G_|#u:G_|#u:G_|#u:G_|#92MMMP1:G[al#u:G[al#u:G[al#u:G[al#u:G[al#u:G[al#u:B[f\L6Z"᫒d߻Vqk]+8ɽ!;&Ƴg \k&ڳ{ZUY=vM65+8jY7՜Cd⯊!koxtHxɷqEYW%ɿvֻ'|Vqk]{âCvMge/,Mg8Ⳉ{Z#mk;-|Vpfoݫ8_CdnYhⳆK5~Y=vN*ֻ&DwD_5rYj!kqWg7:$֏(+ib_5L:_n÷kҤM/.XPn_iǔ&a8U(0wNTA ӛALQSkM42+8jsBqt $$e=LvMdTI%*e~@ta:3B ڳ{ZG(49I_IڜzTMk"!k'rҾ@ԣghTIItp Q qNͲALazDK1LtLtIvZdIJh"݁^bL<2 HisJ[dINL4gO*CҸ^];wφLaQ.PR&#K0_f{09K.*YΚI)'LSN>\O)`&$sL([2 #e]k:>NTODQ+GL!R*'.S&U@˘D_5rY"gIw mq:g]FnBL)v%tmRR4W՜CÛ I =s]ꝉ>|$UY=|9R65NZ)<̥4ĵo[.*xy}%`o]½!>07]" !)辂| ppqÔBevBi*daRNF't{ݛnYm^}EB{L~E31/ sD%@n@QegU^s?9ާ. )tp3r)OS/;|"᫒b ] 6|yۄf)1$Q-A=4r1Ȗie$/ipݫ8:H!bh yS7g¾VQ'E_CzGt$EL i'|s()f}%9*щRhQt2g{{^ x4P.2ϊ,taO@ݯ1OR}?*4hΚSIU# o֟ Ƴv9~+#qs& (%tJ$S –ڽ y3.4JʁȈz T?e4 H43BJdCl"f`䄵WN8xⳆK7 (cfQM,HAL4}ۄfnI8}--6S(AJ".-q$4LΑfD7AcUy *(Ә)kZY3>g {uM)T޻:S,lwpw lwpw lwpw lwpw l7 fm ֦gE_C4o 4S ?le#2ǫwѺ[H)89GNX# O-2hL,di37kS'q[뒢~Bdn9`T4W.qհyf⏥G,Bڴt0R"j/U'?RE-=cvˣ\+wυ,alIe%TKme42=O% >* i ڐ,& m{?iy'Hd@zHx])uE"F:WG}1yD0[n)**FGH"2PWGu4j g^zWL7T~&KD!]|TM" yn")'( ?.zG]9L>tj9ȸbL/L:>%,xⳆK7ܑ4ĨI2K{m.21s eR} BI)qۄf[c7ZQ0p4@{}稹j!k F+NMҕH4u٩•*zU'sz-Ec|v8XⳈ{ZOC̨`&{LCWE+E|T"sν+)ħG:$g$aZzSXP}'rs]1,luipWg𿌇/Z1{D=lJnΚOqSx-:3] 2[dÎpmvxtHx):{QG#O(0x"{gg^bGbxJr_9N*=$A?I/nYX(70Ҹ_t|QNI_Mg>o鼙NI55%Y|'!ENHcD_5rYTͷDT 5)TLΙ޵vc⏦ag8)Ŭ$c>3T]mTҢAQ&K3Oyv ڳ{ZYGDm$-n5=wLz9F(P+᢯!k4I[9ȋE>q0-S/gsR/k Db\KtD9t v4Bs@ݯ1NDZҢmE/<4Aq=Z4JurA򔸹S%؂9E\#wϚO`JW]4Y3RJ\L2]* ,B+hu_AG-zI?azĶE+8jsnqۄfq~̒Q#*DtWM{J?B'"/aݫ8qq\+ uÖnrYnPR+8TEtH¢`&O%K '<;#1(s7kSR_#o /2r%3MR&i)fEs´Uؒ&ȷR uT]wjSMȧ?6J}eVq]gLܽ֩Ȼˆ+8jsnqۄfg8I *9ɵtBKukq8 3$N.)Ȣ.+Ngn5=w[PJ Y"HIK5P 2zFO|Vqk_1ȋE=)^_qӚRGjJ.9uL#}y*w|gv2΃jJ@NC0EJVqk_1f\z$A EW%9>.a|Vqk_1ȋE:A))f.$~0zhp} )GOq SHCVRG:$lFfy$L3uHg \nb;pӱp'C\,IoT^Vʉk2(/ 8EK G՜CY8ޮ=<=3Bx1+8TEOiT2fA+WN:Du3  2ftfM>=ؗH-h Ƴᚑ=yRRCֻrA&8TOng4Q39d -!*>{CEvD@?TqMŠYJTss[.s:l"᫒Y^ynv0ܪ;' *0(̸[Dێ" HF[Q9SJ Vqk_1f\zGN6s -|%K_Car"Nḭ̈* |+G:ޕIg9.7V}ᓱnq]8ʥ ƾgµѼ))!-RwOvy$qYz!=_Ҏ#~Ges|^rGHEċ#ߞ^:TL,$$-<̡j3"Q_T#:."᫒Y^yny-:r!%!]9GqV\dSn#IKij<&>O8ie:BY3Vqk_1f\zLwzs'tmtBJQ&sⳈ{Z=NDZ)&xN%U2Laz%viF1 B1J@|埑NM|:8G:$R`֟Xit[IǽS>gh,e)^1Fs^bt*-![>TTkgv5 !XN5'-* W̡K|_z6S\ty,05(~i>3]*.a|Vpf-E4I堓*B#T"1QB#.>*KjJKNwK WӉI0M6 U0߼K$?gdD>d\)h}%MǼk"I/ڳ{Zn0%2 XO`5 XO`q&jTdЖ*a=*a=1JBK{3.g|Vqk_1i,J`ό*=*=>5Lz5JhPV]F]#a(C9benQ^P]A(ڪ<;#1+C'$SGJِb F*?pbv QSg2ӜrDd>U;DG9ոti?×[D؃R=ާs5 $#6_iiBPc1+XF 3o c1+XF 3o c1+XF 3o yBM8$Ns**$d$RI;!fXQ4%KiNFLB|A5$RCiRȥn@P,T-qSI \"᫒d߻Vqk]+8ɽ!;&Ƴg \k&ڳ{ZUY=vM65+8jY7՜Cd⯊!koxtHxɷqEYW%ɿvֻ'|Vqk]{âCvMge/,Mg8Ⳉ{Z#mk;-|Vpfoݫ8_CdnYhⳆK5~Y=vN*ֻ&DwD_5rYj!kqWg7:$b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I x^d4$vyb1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b1RO'T*I$|I>b0NIJeRR?ZC, !1QAa 0@Pq`?!'!! >UY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=QFb=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgGIUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgU aƪVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzTma UVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUUzZ$3pIlIo>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟg4&%&_ɯk5M&_ɯk5M&_ɯk5M&_ɯk5M&_ɯk5M&_ɯk5M&@}@e zgUVz*EY=gUVz*EY=gUVz*EY=gUVz*EY=gUVz*EY=gUVz*EY=gA䌄`"wZ!UZ*EUhUUVUZ*EUhUUVUZ*EUhUUVUZ*EUhUUVUZ*EUhUUVUZ*EUhUUVUZ*DO$c0!,H ӧN:tӧN:tӧN:tӧN:tӧN:tӧN:t  @ g fxTq]f~&9bY(;9tWeYIfznJ-N]'Vg꿒c&%RCӗIvUg fxTq]f~&9bY(;9tWeYIfznJ-N]'Vg꿒c&%RCӗIvUg fxTq]f~&9bY(;9tWeYIfznJ-N]'Vg꿒c&%RCӗIvUg fxTq]f~&9bY(;9tWeYIfznJ-N]'Vg; 7CȪEUEV@&$08s 1-q;=(asc_@P$}|\ HT4@ʀ %0Hv@kEٹ6f!@|_ Z0{EOh`!zwJ]&*̔߱݊U*EW_U~3;vU %7X$O6&9"D90_`^ =D f:FTϦ^Ԝ(؁|m՜& W Z̉H"Fppw;.WIʳ?/g%Xf,}!dk)Ify1@LMFxC&g*&%%2 (I }G(t@8S Z̠50xttQ9ʳ?-hܹ'f 6Q:<+.o,# 9 $Ӫ@9~׈hmNZ(((pخʳ?3jRch`iC 6bҰm@&g*&%"9!#O,ªd7Ѽwv@+J-R؂>X`PXŲA#ɱ`p.'ҵmo!LpYC+3_Ԥ3p/FZ, E+GR ==A, TVZS(H>\nZ&;vxFgA~W Zɇ8Qd,->ͬao0]']$F Srx~ ̃&pL@ؠ, $ `wZt^SVg꿣Ifys !dHO,DyDˉf(.MMKGmBfsCD0|T^7]p$W0EܚVPb|݈.; oz6ǔ`h݂ ਃQ@Z.| <OVg꿣Ifyc!ē`abn޸.׸H'͜C[CH| -z- "DrxTH]CVr4vqe R@̀Xm~R Su,٬itEo(d"hx2ye;-ĤcVgP*|vZ[ӉHl`.T7:YB\,ouinN%#Ͳ?SXSJF?ef ṟaե86Oc}NëKwq)m,ʟ2VR1+3X >e;-ĤcVgP*|vZ[ӉHl,jMHYBE*b\&H`y*Qڪ;UGjUTvQڪ;UGjPC>el,!k0}b/5i l̆!CyZ[pcpgxB#M"O=å/i`"x10Q x(cYE %X"{#lˬ*b\9P)q̋ulrt7IЎhܻRN$X!޿0z"]W-ܩoρ=B?}>P%C9)F719&Hi$ēn!D' Mòp} CԕP\C|{X6?ef~Yc*c Efulrt7NRh J2D {HZI6%)f< JS-ܠ]?cIy$xzS@dE  GE% Gfƈ]㶼&Gt6myxDVgV?A2K9iP;JX!)Q4hP\K9:|~ѭ)Ef[>DA{rvq U5|}#9L:rfW0vqKr >(-Q1 a&đ)7C%!MS0 ƳNq\NЁq5/-Z ݙlʬ4FL_H@[@y![[zHA!HɁHhC sZk5k\ֶhM~` ]"~7}f78`Xfln} yL:rh)ipb_0"ǐ'’X! Z7c.c`!) BߘݔaX55٭2ܸsKS­ɂo/\zǸQxcVg3#6Md $zV0 € $r p1w'̱N0ܠpxnYIu0ɌFKnL֛W` 倞' c;٭IH6cB+Va>z4I@ $قǮj7@M167Xێ 1+3 ?$nb 3ëS\nFXy;Npih/(p 9J|_iu! m#`@{;tY _ l aqao#)VLWd8nE$ n%!o 芀S2MD[/і2f-" 2n3)AqA1+3<(@Mh$LpCQY5ň|™ 7\'6<+Oc|PYȱElgs?DE' $vWZ ɉ+)VM m x{P v'r!۠Pc݈٘xS6NN/43~ǃ˸)di Y>?Vg>f0Đ.2Z(N^ Dv;#n_o1<(L iv5M\b+Oc|aa6l!Afh8lfXcuin {nCLig0Xvi!G"RiG*3V#ܮ q1+3kFI%'hm遅@clF19-tQ.#vY8[kJo7o`B/̑wmؖ@<b,LO~[-ܙ^ Ÿer fdhL̓+Ƭ1+{;$6$>2xm5}޷JZ@nobha4ӻd[aA?9!75M8ZTxJT $` ,L/G䏎Z2Hi`dzA $y 80vruin4 al/ߢp\hipUay7([ucVg6;> J2Ćm7f<=4'.Aw"+x,oHi&fKRy6K Nו7hw;̱NxؑٻQ)eA#C]H6/S-ܨ[f5տ 0`HS1ᇐSV 2f DrѐPz1)*wF0.ado=^~Slɬ !qQsfHwq$d -ǬSX'{^ pCLXه W<>S6xE7AëKw. C3chH: %464jK5xĤ@ c&o&q&v&?ef~Qc<4Dn& 9=v"J/khhj`N;t\'a[ܷ>eqXh֢ n 9<:sbOF{Ĥ@' gm{Zی/BgA|L6KO#p!l@( Ah]XEr$-moc8祂`9߆VA =s7{XHb;dcx0|Z[ 5\Cn4$7y;'ph,XL$@7 ADA>ylɴ g$J1YXgeS\yK6f ڠLXƆm2=x& &rf@p*Ɩ90>e ;CA gg5 e>-L Yj,Jf1A`>P99l:r'0["H4yP3P (89܈8=K3oG߮p(w詰m#OQ(Ͳ?SXSJF?ef ṟaե86Oc}NëKwq)m,ʟ2VR1+3X >e;-ĤcVgP*|vZ[ӉHl`.T7:YB\,ouinN%#Ͳ?SXSJF?ef ṟaե86Oc}NëKwq)m,ʟ2VR1+3X >e;-ĤcVgP*|vZ[ӉHl`.T7:$@` @ @ @ @ @ @% $Ĕ( 1pSڪ{UOjU=TSڪ{UOjU=TSڪ{UOjU=TSڪ{UOjU=TSڪ{UOjU=TSڪ{UOjU=TSڪ{Tp?I)ڂTRSUJjMU)5TRSUJjMU)5TRSUJjMU)5TRSUJjMU)5TRSUJjMU)5TRSUJjMU)5T3004{kTPU@j U5TPU@j U5TPU@j U5TPU@j U5TPU@j U5TPU@j U5T1&"cMD P ևSXbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,X{efuYԩRJ*TRJ*TRJ*TRJ*TRJ*TRJ*T@P:[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1=aDii{~~~~~~~~~~~~~a/ iWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuWUuL ƪUUG?UQT~UUG?UQT~UUG?UQT~UUG?UQT~UUG?UQT~UUG?UQT~UR+3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3N2ųu:<Ju: T +3䜌wa\& `p2ųrDq@L pu({ cXBFr9=P uiς?b~@i*D( 0d$% DShmp@@ٯ|PMFI j 'KJF R+@|4 !4TR*CEHh  GrN@"ujl)$4(h +RfXn@xAi IMQ|Tvwv,2y8xU;ʳG1a= x9=$&;)򽍬j`C>,H^@iudnŽ/ctb uE㍂Y@KP}fvװme&? nƜ'<L %Ft7UAFOv|KA\ +3rBdf`ܫIhܴO1騭%nj\zLddܧ%wHy%F?DKHi&%C2Z:dzǏ 0?"B/<A vWg8nSݼJVgU8', !nDh0F+`-9jj\zLjI̯zENn{ ˺ׇmZl7$Xg0h)Й2!="Y7 T^7`d5u*ܠT @yi#ɈGwr/LS @X7]`!0wv۷`pD $>- +3G@L"G!OpXŃDAb3] Lnۺ/b; Pt nBy"Ը-/ѶK9?bA-;f]1 ɖǡ\17 -cR]DcScٞ!HO1F@rHX$A=tN$;3Z5&x3y@ Db\GzO- sU8 @  $ d!̂  {t&lLYp lpUAyP پEL2`lvLpz=쟹VgU8%f;?`cID_VgbŽt7hwl|A`> &+eCܭKIbٸyD #aza2'$18.72 {#$`9=9 eeACjЀ;Zk"L'Y#<  ܑ/٣㋂Y e`?uV0Ye2 '̣>3є9'ȋh\ c A`$"LiLM7p5ܧy5#&r7ΫqZbʑtf+6"V$! 0p09_&+vbɏ)n]d66]r.=&efⷼ\U'syGy[Xf^+|VK@}&qjs{3qu"J1d-FIf>a͝?|N& ad rXEVk M&+3pDR$,sR,!cEA8zj`n8AyQ k*x0MK Qto(B 03@m%:$rbl 'p"Wr8 >9 VgU88,V r|# Kd572Ng璤j߹>;Ot% +3䜍6NLr<dh̬@|!f8To\9, i!gDX!@ x;|Jr-X&GC  |)c"[3DI,i{P<V=ɓMV5n>-i4.j0a2A\q fve Xe>@+Q2H߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߲:I3,[7SαSdSJP߰n e 0` 0` 0` 0` 0` 0` Ķ@vĴ]%vJ+Wd]%vJ+Wd]%vJ+Wd]%vJ+Wd]%vJ+Wd]%vJ+Wd]lJK4(c MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMn brppppppppppppppppppppppppppppppppppppppppppppppppppY n5W_U~ U*W_U~ U*W_U~ U*W_U~ U*W_U~ U*W_U~ U*WV0`plΞ%;*OU?ʧT*SOU?ʧT*SOU?ʧT*SOU?ʧT*SOU?ʧT*SOU?ʧT*SO&ŀ< U*W_UʯU*W_UʯU*W_UʯU*W_UʯU*W_UʯU*W_UʯU*5EHT*R_K~U/ʥT*R_K~U/ʥT*R_K~U/ʥT*R_K~U/ʥT*R_K~U/ʥT*R_K~U/ʥT)4+Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q'״:f~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~nCb9 >Of~Ihn]u c";̰<\2}íL!&!\c yoBj13A!%́̌AJeA3 SDN"cT_}3"-E cb[mw%vqZ3&$w#2'OP?X8U$SbQ6@)lC`pm$IBZvTq(IJ3,ZM;N#AI39hsܑNt&4-۷nݻv8A%%[ i(L$}CCb9L 7Pۍ \@ %] vq#66& >V#؃/($̢I@eG+X(`, @8QW ]o%;Be .z `Eݜ\2\D^a" 0SwiV"a35c8J5`a6"7 x4F4 l$#m.Ɩ PpE!,,bOpn5e,Ė*O?gBD@ g3pyi6?I$lR -9!Q HÔs۸{'0%[Yw0,W:{ϔ-e@bN!-N>nRwVŋh>>[rVa0ӕ b`@ $J@h-R'A[fy #w4DxW?hX Yxý؈q j:J}-k..i{Bt[|vݧ ox X` 4fpaX$\wv/Vg`(+^BG14 7luZrWtv@Ork kZPy#ۍ&^q?$~~ b;q&Đ I!: Z ›Cq;te2*spX!;kwHZLdǡ̱܍JCr3v{4;E5А_;8LCK nnD0{Vbُ ;@w!,&Op yy@Ȅ5Oy/u ͬ\:4i$wb4nRyݩn݉Uj%SujXg!uעNGr7#O{sbQjC!Cb9.gt4pyNc$ [$3x'u h(hOneZu $]㉆B9""qzgjM ~rh;IC'hD n~G bX'OS :.`q-k 'tİ27 7"1=4{5f~Ij{/wp iZ7ELwi nFL$ 7Q̱܍JCr3cx$Yn7 `(2530Q@Q$=WŇ^N%Cbl keq0^9؄I.:אd`CC3b2vI; Í4n 8zWVg䖯-ױr2H]#3'i`7#O{sH5Cq8X9Ԥ7)s;揯v3o-;BGӉBBnOg07uTqp^1IKOkO6p*I&$I0fո2G,8!r>>[Ƭ-_[j^6c7|lUCĚzkc_engr ⹏in`Y8/Ƌ1h&XnF!K)G=&bzw{tad@@@/(]왷q OGwo▅$\r :>6|a(`I&j`ZؗPLaf6h}Bé퉇>Ii'M $5f~Ij"Ȇ܂g\\fs∋$ w0p( $xc{ۘN>r yzL `hs,G7#Rܥ k mà)jiM(cAeE,N5pPl^xd(sr Ņ m/01U# ی1-`Y}l2bMp8j; $x0璜ĞlhE@(Z*k+\V%sfDvKyiN ؠ(2'峹26^9A`v 3hc88f~Ij"Yu 2"= A .>3nF5k7"i鈽s,G7#Rܥax**,pݹg\!0!GۢH`ᙱY] (H5݁7kDE Y8%)[o,mmIYdli F(o[m7#O{sɾ"˽G$vF.P>K*Ԥ7)s;؂x3nE Â|bGùT0. > DG$ G8/2AOhSPLal/iɰP+{Ǭ,f 2DaBb x?r+|<#$ٞeWٲ(7 }ihb1sȵJ@Z[bV c-|# Iw#ǎ>斅s,G7"t)"0jՋhMp P''L;AYa#π3LaG=q  nE@l>_ə oh JQ>Q?aFkZE efzV GIb$9qvlٳf͛6lٰ%47tp$ Sohy]݈LRgD6@$v 7Lꚬ|&sM5cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<cexd(u<Y-X5K~/ҥTJR*_K~/ҥTJR*_K~/ҥTJR*_K~/ҥTJR*_K~/ҥTJR*_K~/ҥTJR*_K~Yhyc=/lңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?Gң@@P-lZ>'ҤTJR}*OI>'ҤTJR}*OI>'ҤTJR}*OI>'ҤTJR}*OI>'ҤTJR}*OI>'ҤTJR}*OI>'4OkңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?GңTJQ*?GңNvɷV`,I s<<<<<<̽}}}}}}qqqqqqw}}}}}}<@P@@>*P @P@@>*cP<  (@@D8@XPP C2*f 0@5,@@ 0>a*"PԈT`D' @@j| @ XaL PPd 0 @@P@ @)P>P*P3<@P=@@ 6X@$  @@+`Xg@Ps<(Ҁ @$D@>*P @P@@>*P @<<<<<`<?X ) @`<?X )8C( 4 @000sN8 X`@U "80Z< d 0?X *RGP0H`)4+0@   H )RŠ @  5 +PHP / @(+@9 ` D@ 8<  J?X* 4(0$ ")4-0*&(` x ) @\ 0+X*,C 09 =@Ġ @(c+lD ` 6 < X~?03X`AA 0 c `0C$ ) @`<?X ) @`<5AAAAAA<<<<<<3qqqqqq 0 0 0 0 0 0>* <) @>* <) 00c pAA$ @< (CI,@ X> )t!0* l@D "0)ȔX@ * `Q$ @  P"<( @0@)$ !AX# @Chq) @ C4p#0(p @  @D> ,* $  P)) *(B, +TP(@< @@ @!A)  @ !F ((@0@0 @`G@( 0  % ,>X Z* (B " @4!D@ 0@ @<) @>* <) @>*,,,,,,, 0 0 0 0 0 0H0 0 0 0 0 0 0AAAAAA?+!1AQa0@q P`?kFk=bCءP({=bCءP({=bCءP({==Z8X{=uaX{=uaX{=uaXѢҳ8u~S2_We:c)Nu~S2_We:c)Nu~S2_We:c)Nu~ÚeJS)R)2ǷS#/O|/{>)2ǷSݫi |$LgF(ebNo>_񾧺_ zwTqJO,МD]Ic:uVޱVywRmJncAU~Ai5sgkfI0zBw}-sڵmԯ?鮾^",M^ FsH@H)Nre٩鈒FLW"ȹ#.څjbwK~">,Yš.*.˻ BAVV ɎDy[UakG!~oZ)¯TD\SoS{Vg$Rx(p{ԉUdU['yU8V.*ՑKw~G 3YYr915%Bl'$ *%]?ElPL\M7kۥA9Ndof6:K_%UU[زbHؕ ;A2 RNSP4C䎒:J abXb%yV'PjW)' A EV_t"sdE(lE2wڎ"ɀUjk۰ $ ct0UYUVh,6^n@ 瑗|XgӳȳS| ֱ)We~WS+V(/j(흑4Y;OkDl?בtJ&2&/ͣ&IˣGq^R9 aW%WO0z/<_I&f^bbtʖ&D(&!RֱK=)KǤ7 _~|./QR#y,>k +59[B@`p鿦ctjTA 0~xUUTǪc?m3i&2#.R !<i7H/Wu06AqӶX b=C?_XW|SeQ}c_OEo~>F_=_XW|SeQ}c_OEn/%g?c9g4柱3~sOi?c9g4柱3~sOi?c9g4柱3~sOi?bx+k&Rac1 }>ac1 }>ac1 }>a SVc+ 2PC+ 2PC+ 2PC+ 2PC+ 2PC+ 2PC+έq}A{=}A{=}A{=}5,kg8a$JK㋀yQZz5y;v c cT/RU*Td%;@kwoNQtomދ<>/KtMB$~c\*\-cbFt$[+0p.K<*ZSjF'Y6*5\c4+Pqc]*Rd]([$c6VCDU,MwJwoA e3HniMދ!UCvpʀ).h&%ye8lEX[ +h!GX?,7mDG;H1d>f,&S,M[@YjLjg$Rf%,FFB$*3XrkלhYhdAVvh}gU~L6. 3)UTHJ x)l4!xHp_*ϤӸpw͌gEބlX%ͽk<^D[")\Aذ%`F{ %b "˵dIӖEI-2!@;j\:n ?_yiI*IKk40"pFhdmexRVND+29rYrG8:4@alX`jv\S`uE7T_w8wNWSpWJQ -䡄Ų*I$!N]`%`Y#bychԬ/JSj4i>%5oXS$ ِBI AڦJͫH Z alX`޳A#b?ͯ5{6?{(hl^[e!w{'FZ}5֝L~Mc!brYǶKrv,/o 1KdI햳Ylv: s[9sc]\sLCLы'"&:$L&c|;ٲcg dD2K(h_g G) s(txk9La+ʲif=TH έ"p'2ԟG(P/9/e8IU^d*R]@Ubԅ+5fw>>[>uڼ=>R4FLi)Y@dxH og9P+0YA LW;ЛR&\>>]֋%Ʉyr*Rb RHC*gF} M. gg"\͚θ WI`}ݵjϏŏviKLѹ0Z:6IG 5 Z^}ĒHZ?\DUmyYC"i&ȬvH0$iM!&8?HV1 vEj͚W,\l;kώnŵm,D (|V-opyM(x1]6)H Wf&? $'ܸoJ$!6e,9Pf$E&+J|<9 ^L b 6{U"ݹ?!V()t-f.y-?NC#oe1vYO~w<ݽm /2d/rk n *L%c23Y&䊒ɪb2  +&aZDmZUlHՠN["J`\-; Db]ZBqO?*`5A ٥vm!NSJ`\26? d1JMZߗD^6"ufb|:Nf5i2eL9me sqH\EUv1/+ K4;|gdZ\#본&F~ vV2m6MI65[Uj-x!m^M6툶HzCTߔds{4=v i' z)qoLw?mC}m e6롒[O?+XD=w`a}ÙJ̃I3pób黨>R٥v|t%[ج­'"j$֦edu͚@mF!`~W`lx;.g=? ,_?+ hf-)jpób黨>R٥v|.J  G)w;4=,(9W?@j>ơ&AcF8#+ﳲ `3;#3RN_݊SNW+ h2&E 'v6;X|߂rXvx_7ug]4ͳƪ;F[\ @1a%6S WMχsl>y3ě;.-}?=+ oX:n;ϹԻi]&2. bR%ˆ ɓ"`C9Osl63Fw\ߣ?>Hg5#(JEaI6&\4˶q2JJ́0|`v1D3ыaNg8**qVl9[0&nX:n;ϹԻi]|sl6?$622žœ]}ofo{"lxaKS H:=TD|R4N}JI%Ix29 lq ͑"Y 2ccccccaA"E xy($'k= +)a-sSYoO)f +-"F p%WHwoWHDn|%wQ)(,)~+V^Sxy*+߂Êx?[{<[XqO?P|g~ )g<ooa< WB-,8UWŹ:Rclsϟ>|ϟ>|ϟ>|gNI HYMCh}4>MCh}4>MCh}4>~ Ɣ)G#D|">G#D|">G#D|"> 1BiN      "\ɚ\uc5ՌV3]Xuc5ՌV3]Xuc5ՌV3]Xuc5ՌV3]Xuc5ՌV3]Xuc5ՌV3]XuaɓcO|DǓr8?sQNG>"cGLy9^'#?1qz~sh1O<,y"=Q@ [;7腛ezdςʬ&~\`^A&p, 7.qAS>l& vE9^I`et vy,ו n SnIr di( ^j?|"HEcc+W5;@6PQh45WIhfV)fR*O_Siqlr1U ^YvhjT,QfP̛H%Q`.N$Ql9baQUU6:LfɸIk`slT`UUG>AM|C ٣:]`SiI?#Gl*IL70YS9 19}oQ +d`i\ ۩$վt tʮAM&ĕĘdh}IDH<˜c7/f`U뚭( m Ԙt m@k"d2HYMKB1fi,@ʁ'Oy9^*H W14-Ŗl4Rg؅dDZLȸ$E W Aͥ}*$Bʆ UoVk^sz;-y(%/zdc&Nb@vLr+.MN,\M"^OR$eJD/+HUhUr >H0'LFo֙+ExXI4 k;g| hf[5U&|W1@'df;lp9ѱC?/'#?6 ]eݐBUvy, ZB,>g(C//̧5-%jJrIЎ@&׾Drp鲚=Dr7giU`@Yzj& S8$YSɤLmjr0idՆ[}=4%]޼;JrVbha{U.A`DJzlS@6i, GOlޕ%БcMjJH툝P]} +&c@!A#Cqz~svy, 5y$0/cA"Ql6c^$ ˚ʽᙚ*Ղh6,Q!Ж慰׾KI5*"՝{p(f "I:K ³+2dVni\olCe|Oso sd+IDި bXe4eӒ&D ,Hj\[[74-o' .9"Րb U E5;Bb6&⍂ƶ)j`#~ƛ`]i+3J@ qz~s5W3r>p9%aifR?;'WgԸd=D fڶ= %0#I2Y5Y3 S*MٵU7ଯ a q͙r&:|ͩZv4V+b_nh3 'ԃB1>r8?sQNG>"cGLy9^'#?1qz~&C!G#?|>C!G#?|>C!G!c $uΑ0|>f3a0|>f3a0|>f3a02t5*':P(|> CP(|> CP(|> C ҔF5_yQiF>k%n`ZEkQxy<֑c^k=F5_yQiF>k%n`ZEkQxy<6$M柲<'E&|WHÚ|@s%,&eެ|WMV+ $idMK<%[h_Q}F )V{ڌ=?b^'^L98[־8jك\TLbEnJ']$-F>-?MUKt<< Sy3?axk =Q*ED 13Ul2i?i/0Sp K(sSX{S5x9O90cd K YӪv1Jݨy%PzbUvA{a`xZEΝt{9vxZ|9[+x_,0 aq (ueWܗ׹{(6!gݨ3QP(ɤZ̸ZE9gT?q,$~YtX P@TZ(qZ,Eb  j Z" \ m}xxSn3as!K6s ƲilD'=EJ5 vh\^ǽ%z{_/>[N,aމ' H~S?1ԗ߻nAEggyq}xxT)4Y3H0H沊i_ =N2]#Xs6ΗmSyQXsZ~1WJ[i2;B]<9X7cxݰ[Vc`ubR+YJI@V :iZЦȡG %"Xt]1HRD@.3SQ)Mp&w =F X ?o6R qK:^&uV)lsxc[%TÊMw6ԿgݨeSu,)%2V- HrٓdƉgROB~ kz3zDتL4 ٜ-F> c!`I%̒L*["fGI0% ,,Dr R,a3aHj\~Bj(:@xY7j0xYc_$dv$U)ECҷ-F>.i%3lеV*APZZW,<"Htc@'xZE'+NP`00ZnV]ˉE4+#ȑ&2$K/*FI FSj8qP87j0y"5d<{ڌkHj1Y/5v/Z|Kgݨ洋֣5Y7j0y"5d<{ڌkHj1Y/5v/Z|Kg}!FLH$?ďG#H$?ďG#H$?ďG#GE5Ç8pÇ8pÇ8p0$BTQ @ @ @Y)(LJ<O C ,X5W=;_xU0&40YWK8Y .`cQm؉΅q.|\3p"*6wo:rp X(z\t  7Ll ($l#ZJ`$?儛v9 _- A6+Kc&(#Id77nRRPO6Hz)O)ҡZؤÑ:=P[.ȡ0QxQ>bhGM>w<ߛ+T7LJr>KF䤆tr:˲t^0"\:΢pfJ; >rI1XJT3qco7F/`weS"O(1j ȭw@~ H@fAFK1T)DHK=x=UfLw~n&<"otUmi(POMP0QI0?b*?6RM.BBfd8j7pDcc@@ BtkK~)b9!zBtH"HX}ٚ)J@*.lU5cJ&Q$& 83rX0$juiphxZԱ.$.@pJHWލ=Qp5!FdU* ܔb19%2Lz^>Y"#Ρ%|6ގp< a'1N'HE[֗bUDɠzНDU1Wׅaƣw KJ7:WQ&$ wvl/خ}"&}.EG`ӻ`Ɏո :RkOm&`5C*fdJ^Nvʨ%%ҭR'!m'=hwxR6S$?($BJ?fa0Lj7pYJBɥ#IBm2OB6l $5*9HXX}h? 7 s5Y\-JM bz %Aw1'o0 wz&]Wvat, C&o1:P#x^ɟ 2[ZCx,\UKU\ߛ0g'ԩHH)'+ <Mxz*.~>  aX|,> aX|,> -B jo6h٣f6h٣f6h٣f6h٣f6h٣f6h٣f6Z-D%}Uw#܎'r8w#܎'r8w#܎'r8w#܎'r8w#܎'r8w#܎'r8y]4Uw4I$I$I$I$I$I$lJXWr?܏G#r?܏G#r?܏G#r2 ,h& FHi9sZk,${洋95A=ZEf|ց "3>k@ed|֑wC5_2GkHσ/Yd#5]Pgh lc@c@ZwZ% 3pDԈ^@MplLN5(Sܓ`@S6g37.AS7E&ǦDԣ ܂&a{F^#"w2G=ya\fMqԠ&i8E;MոdTa`\[ve- ::^ˬ4(? V]JI8i xSbST//ɴEL%EF/I3{1T)dABtR/C+Rݧ?e;@CM Jz%g9Q?~ DUK3)V-aE񒋀W9/+T`]zuҨ76Wkje}<;A=^v/rb'ɼm*l-u|O̅En]ߙ20T[:Rv-L@!,L\L έAv: V!z6tY[FƢ1$j[},. nof hx/L%`M03AVH ^[%i*v99%QЯ|Fկ7"sOMS@3R PXYԁJIҦsspRPW{p4!5ւU+ѵ?fmZ, }i)vd6 OJm;4؜ "ݘm6:P"gPٔ| -k(9ޮ尨 #i*kX%@5KzҴ0.<{3{'`"zaa TfQF2hYe Vσ~cRʑk&urGkVgJ큜Z)U!RIÅ 3 cR T@p@/̑h%gDL]֭K>v6X3=# NA - `f:hw2GmfMwMM.ṛ'ql Q{oI * =h9ٳ{=3cxS%eI4gl9͢b NċR UYx2W FO˂@]O55UYh@DCjr[} B$ yٓx`bp4(nk@/[dGVUr2{6os0V*] Xu aMq%a`^9VRS tT㽙prs`}IkCJjW)f,SleiO~@0Aɢ{@] ? v6NRiL]FTav8YHͼɼnvi8EYٔ|OE-F"k@be4G2{6o~9Z6:of|Ü3>\N9̞ٜ͛Bt<7OTJ'i1 + ,Fgl9/txWkb!$d`z !*5RRiw2G VM{YbGSd3aɳIRρ]֜L>.ӎɚNLGaaaaaaS,g[>9T9 }|2SfҫOWjiuTOp]͜3( JAo< σ&GB> )i*v9R> a $( 9QC4e:6 6੆sgh 8$ ]T22GkHσ/Yd#5]Pgh .s3 YHi9sZk,${洋95A=ZEf|ց "3>k@etFeA)a5Xza5Xza5Xza5Xza5Xza5Xza$Li)iTxQG*4eItJqE?Į=ѯx&Q(9f C[R rAlKOF#t$&G5 d)-k@XNt7~.Y4ڴq$.O5pSFct NyFx7MH&c'K T t'(<؜ OL8ZO͔R"tl⨧&S?1Q?s* Y{ʧw7xP Ǧ7^gGi> 7Ls^{޳45׼7Ls^{޳45׼7Ls^{޳45׼7Ls^{R LcA |H>$ăA |H>$ăA |H>$ă@f%Lٵ3G#?|>g3G#?|>g3G#?|>g3fMlcvQ1F;(ecvQ1F;(ecvQ1F;(e!Y7J%DQ(J%DQ(J%DQ(K-!1AQa q0@P`p?K+?~߿~߿~߿~߿~߿~߿~kŨ=<߿~߿~߿~߿~߿~߿~߭j*O4߿~߿~߿~߿~߿~߿~4Df as߿~߿~߿~߿~߿~߿~|(y߿~߿~߿~߿~߿~߿~ЮS^XF IUnfŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbʼn[YIWYU?u]gWYU?u]gWYU?u]gWYU?u]gWYU?u]gWYU?u]gWYpM V9PfǏTFvD#d8:ξUyBW^t]9*V8԰5'ۆ Y3-9_C ߑ(ąWzwQ,Bk sNgTFp Wv4&.&UG$(d2[0%k=g_*w oץ?ݍQGiCM n}`a]@h,Beb/Bԣ?*Ao leP0 5xLs}@$lmΡ-NĂH/I{ ޚ3) GD0NP*`vʘxn>@ m9W^0fI\a1B ^ X@@2_2Cj*Cl }ep8>jL!gK _T.*^ĹgsO0Vec c.r: <%&Xم߄ "AD8T  b-x kAnNgx+J@RC9(f ]`J]cvec萊eG/#ugʬ~B`WJfc`wl s\J@~Yʶ_0a1+!Ls)Ѷ3*$`s:SUV&6A1!+%FpѤ`? `efM6HxN爩 VrdyO)~!s$$ ]4uU_+F}uv|AQe @9[{ v \w 8An Kl)D?aW+0d X TN8&cf4c|dp^jnbԧ$$e[t,"X (P eQᐊ`CUgTPMU4oQ.v|gu2oۺsHH& 1"S MaW+4 ס*PY'+)=x&I76-M^;8)/Q(}Abb"!L,E,^hv2A1-xη:~;:N1C $7/RĘ%Rsq'zBoh2=LJ S2V̈d-w j_J090 #,˧x۷*6 ]11Le ꚼ>{̈́悚_= =Ҕũ-]@ȁt8<PV簰I6Oe  ;a\uW( ;~;:^hr)Dq@[4Rp` J!wt0GrB<WKߴcrlڲ,~qElWDCUSWz$ eG"cr'ɬ p' `Ȁ"ꪮ\3  )nbŁ3v?*Gbfh]/B2>_ot F=ZRbix. j_{?tXmܺ=_q34Uɹl5&3 UYVꚼfyʎ4nH< %6w7 IaW+3U ߺ,3"\ i|*UnzU0$y G 7GP^_-x`)i=C*UzuHdpfFA]7Ul Q*VR oXYb8Ĺ%VB}5M}_D5M"!<T3_={*%mۀ(t [BɊaeĽj9 9qة+5$Tr%9røRJ*@l&c%gb=3vT8TV j&#'= ҀS5ALG\U%Do>Hg!JX Š0-",1^1y5\ d` =$)ly5xl`!ȱ_`'R-ဳ?80<}?|orqFK%X0EH \[₅Ȓ]# X Pnn }W25xH h 1\Őd[{.&X\QϰfLuM^:'Isڊq pDwȧF6Z-NMRX0>T1 7*^+i"£HE\י"E X0-nݻ@kѕ' 6'ýÇ8pÇ d T@bTsΧR6_ph ϲݺ5Do҂L *HzPUwAUU - `2iF#ذspH;7rm_80AܽKr`hwGIP4uoDzL@$|bg@ꚿ졷wuM_lP݇;6{(m]SW=6a {gTe ~3jg?5ACovꚿ졷wuM_lP݇;6{(m]SW=6a {gTe ~3jg.Y!XP}kgϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|Ϻ$IHh+?utG#]D~?utG#]D~?utG#]D~?utG#]D~?utG#]D~?utG#]D~?uN }A*h$V`ŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbŋrEjV |߿~߿~߿~߿~߿~߿~pPQI&0EDfbp3 @ @ @ @ @ @ O $߀, *[yիVZjիVZjիVZjիVZjիVZjիVZjխQ CB?% f @ @ @ @ @ @l=*]2`3 0` 0` 0` 0` 0` 0`-:Wg0I`H"D$H"D$H"D$H"D$H"D$H"D$H~*R{AC3իVZjիVZjիVZjիVZjիVZjիVZjթ5Uy&`榀ď$1ؑ䟚F7h*)- ҞB6 +2Pwݻv۷nݻv푴nd9!L2cea1ON%{3Z53f.^_:> F7[XA%F>Gn|&HpB\ڧd gVHI"L`Ȓ{m8T^ =2KY:(JB, g<Rm3!G)鰦SM1f"m$cKo`%aPy  ^pd*H7 ;[Pf'΍ #'K!2"4IFM%-^q 0Dh*wϳ@cA`llɑ&H;Q UҲHr2O](]Vۇ~"$7HMq6mr9`y4+0vH'I"̙*U@JI0{Yĭx?h 7 h!u.ԣtǹ4emYK̓Q`F#HGu[+d It77cc1H属` Ql Jlt36bdXqMEãq( ܐ66Yq(~@!($X63H)ʠre: t?:BR5*F}{@oe@M5h &xh#CgLf%m 8''%d-GCWx$Y]ڛO,< "bPxQ٠8 M}X,[1y6}x4oH]%O2>p=PH( k'0$2d4b\ln(7IV5@p_O1AXȴHUWvBRnt@BT3ỠrT{Oq|OHJ-pR hR8dP3"NRJ1io(h;D$2#ƍ4hѣFa' L p"(x,̉ 6 G׋v|^Ku b,`;Hȫ gl Dcx<-8ʼnvVmA"R.Oc\00$RE0V0A"DԆTdx1 Ȓ<#)]5hEV}/0`GEp2ԑzBnŸ`~x8-@ -< ~E814(@$)?5 2h02eR){J3/!oq )VW}N 9Ac^P"V}&⁶j9"yHNiNjeD/xHŐD@5-QtjX="$"b'nn.C>B;Բ5B4:g>V^@UjdQȨK/E%o^ c$f;$l p@/Rn^E' j-"ĀD3?7h OLtʗ;*sUW7cr&@ ?Ȑ݂4V2B&9* &p4ĐvCA;A~l1?$h4ڃ0,`8AI`0;VD <.2)R˱ , $u m,U &'~nd|RVCr9<7;\,AWȤ+>?Nf \9¢хݠG #?5lAUf(# rO1gfdkϨ˂gdʟZq+RAn$EL 46% mH+gB#,-89PVWnS.Bj1:zӵυ.# X*H\5# GK{A,a%Rʼnqx2iA2UEJ\rIhl5yOQ $؀v-*F PT%V+HԙSi:S0^\ C5&VsJ `2 &H]`kV 5PͿ?b|B:$Ì \1% ƀH8FAnWr #a:lh,pCaeЕa`#"[/Ǒ$xc B%Հ9-\}_XXc&8h`~z#֣~OVK:?HRU{f`xr.8QXJ,٨|/\\V yk@YZd,hY[(0h! 쇠K[w]-(IUȒ{mY]i(pxQ'ºBU*e: GmSީ(nW0յL?d@%f߫fQL݇`Uڰ)i[$8D>x`W nw $eB{Vq_YNl9y*HNEPnmAr5,; < 8gS'2~j6@ (d(2ˌCg`U@@F]z |V-SG ;Xm5V,EESf}x !u.7Gn1^aanׂ$$ԑn O*HNEHЈ7K׵2XD^lsf.zxwKz( "UĐC\#"Rp%Qn6Pv '`$DƪeLK{mj{ c4P@|*% P3' yc>_F !&B$V *Q$EPK LxM o@ be+I)25Pv҈ owʒ<Ӈ~#QMrk0xka `{ ؋L9QC5U^ا716wȤՕ I𭑉8!,B; ظ cnJAO|o"7ܔ.* I`E,[@Xdea3\f0?-ʨcv[s8ceaX@^Q0j$=F>$|M1pQ'|j:hF7¹)$ xoӔ{9L~EL󒃲CsͿM D<Q4_'"K.ʒ@0GjZN# jA5B* 3e5~j7qqg<D#w"̘ (2J"4bq-$=(J^ԲTd-ܨ"0ICU]_w"ͅ$ޛՁ]/#%u[P K܂j3#Q]V.2 Zq0V>Hn0LY,m$8b{dόHf, `%PqOΘEkGщ>H}$xlQnEKC5uʚhd0pcA2n$)IZfzSDqoYˀ-lX01&|(oVbHϒP>fRfZ>#H4d|M<5DQ!8JXb-8 ce7)|Ԝ&7=K%7Fv\'">gFuIC4 6d  +h eSzXe?:]ܺ^OQb#d Y{k"fyǕ`yCE :TEU[]b7UGg,)|ECÈҶH8*3(B=b͆6{/Z!IR*ʒ򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(>򏼣(!+&D;>g Cr?h_C0)Q>7Q=G/3:D;>g Cr?h_C0)Q>7Q=G/3:D;>g Cr?h_C0)Q>7Q=G/3:D;>g Cr?h_C0)Q>7xOT @]ZtG#ATɍ;xʀj+?uK>Dǂ"h7PRb\B}PR3~ e/A V">F`U65ߪo b%Lb'Fc,/գ?*p~MJ#)Q0Us#.x(z^ ChҎDC#=>p94i`:nĐbh_g@O=ŋ,XbQ'{E+`%XXP3/(f]2 woSYPCsX _ 0`KOHQ` VIX9UJD,K8@\SNHB-U)hݬ0m$ c (:V(`lжOdljN\LF" (@ cX.C0"p/M,xbƼ^d9Ļ`Ɔ gf$wz^.S.P4F4(G88 mR=Y0Q:}UblbW4U I,bn!o_(!fŤ n DX k8 p=]:e%&s(TI-d W6,$uWs 6y_=uIUKN,zH77ȟ!B6 bQV2ɱR ,Nif^=Y%LT&mI|߄n!k]P^!LPFy $@AB渶1mV2ux-ZK#=`2` jLqevjCo^x7xs*D01F*KbZS`s]T֫X y  o{1{FH=]Kkݐ&bNk {a~0=m vAe0q.)_X.B$B @{T @fųLЀIY۱p  , ݆&w2]ޠ |}CG0˜* ٔ<8C? _W*CY_& V K$ ߥf;K*DVL0 e#.+T/Sh .9-իNQ">>БAN  \dəˈ']k6;p8w* r34ila&R*h:5nԾؓФBv-x,K4dFq(?r?XP 3/pא p"6DĨn&kuo>}jW`ɂ]%=3;aE, wZ?xǂ#D -%$0ݪ . G*vL}>}ag.+/ O0,M˼3p0Ո $v) *(4|}CGZ"604g/f'x"8Tϗ>vn]f8%a0]^#OW2 w+ۖXq+pZLyȰf:":%渮m+:/H04$J؆$Pd00YY[y y[עdR-րG4|/^!uV1U%jC݋|SD{􅷁 sZ /M(nu{F+@P𫀆'G+0*ν:ƀ|j*@n0'g}s\͞k 4얛"',F%!患jF` G4|/^!^ dė] cn =IU7h 䊑,L%.TKd!BS@^#OW2 w+$JmilU =AU~*x vE FQXXU ˻v?ūsWyp"11gk9&f2.p5 M,J6R^>>}bkh>tG4ݩ*c3 I4% i5zVX_/$8Y:J w7xJu=^`ȁz-euZQ`n]0@ `dcCCpX 0 Dx0\-wz^*PD,V ;/u KD+["ѣ8՘kӁ`!X"J =ѧNJHPS#:މC .#q(3$`Ϙ;1׼^#OW2 w+$.kX8|ZQ XhwŰ\ ldj0*7 8 n<9B4|/^NfZ]n>o(z^!tU6pJ=+( v>*.ub1@yTVawaE/P{ޡ9y$+|}CG+I-rNZǽ>o(z^!tfp,ʟ `Glo*!~Ea҆[OpE2N`LBݲb a ӠYzz^*Pj"1 q$H"Q[r0 Oi"Dg6 7:234QIoe`:Bȶq5P M+v0Luݿw}MwG%:0d@WH n`2a).Br `nxA'_< Rm4&ZW MnO(ڤre9Y2yMBS~:=4)J @`+b^fɻ-uVqIzru  z^k2tG2@mMfGU`^#a/QBCQ% 6 We[4gb"u{ϛG%:0d@WH|:|+:#XbC4z^g(GPxGvu~ ."ZAW|SD{~ C,T^ {'!+U q[8ڴQ#>/5l(i0I{@le2١ۑ>/ ~x3@8ND}{ @J߃J mhP!߶ e =8s@AU2d7Q=G/3:D;>g Cr?h_C0)Q>7Q=G/3:D;>g Cr?h_C0)Q>7Q=G/3:D;>g Cr?h_C0)Q>7Q=G/3:!dT(Q` Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,X/ JX2)塒EWJztӧN:tӧN:tӧN:tӧN:tӧN:tӧN:tq H%p4\qExpÇ8pÇ8pÇ8pÇ8pÇ8pÇ8p&!`U%emzVյڶ[V׫jm[^kյmzVյڶ[V׫jm[^kյmzVյڶ[V׫jm[^kյmzVյڶ[V׫jm[^kյmzVյڶ[V׫jm[^kյmzVյڶ[V׫jm[^kյmzVblrv[JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ @&r + ! cjw}UWwڮ]jw}UWwڮ]jw}UWwڮ]jw}UWwڮ]jw}UWwڮ]jw}UWwڮ]jeLK!hN,k[w={5ksٮ]fw={5ksٮ]fw={5ksٮ]fw={5ksٮ]fw={5ksٮ]fw={5ksٮ]fw=26 [%[w}uwۮ]nw}uwۮ]nw}uwۮ]nw}uwۮ]nw}uwۮ]nw}uwۮ]nw}@B[7o{TS{ڦMj7o{TS{ڦMj7o{TS{ڦMj7o{TS{ڦMj7o{TS{ڦMj7o{TS{ڦMj7gق<_}cW#DG_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NxP]mRXVffl=hG0 4tk~NYȷzC`B#d{ޱTAֺ]YR±2Rȯ+"ȯ+"ȯ+""8$ZtGEn.`t9GZhߛ>j̯"((?OR&7U^rBu1'Q;@%ivqc|*hFm+Қ<O! Wrp}hEu rI-)6?75;탺{EC)n":>R'f?BږB3x?G-Eɲ G"pEf}_Gr1H7i(%*$+unzkOK f. j{ܖr 2ꪫ+ml&xX 2IKq u W^`I oHhsmٓ zP:ݘI6mXm˅$+oaq0_EZ g`;U `C= Vd5L!-0; F4 6JJmg;φX1ҥ@]B%)se'0Z:rc{v]@":4^ nUJKM $X]Xcq/LB ~$0mKz8a--H%(!'w0Nm7 pFpm;7Q 0+ 9ysջL^̓MX951s07omx%aD~.)2pG;v`mNдM T {KbCzCs!b=LnwYu` T/A6tAۻVb-ޅɚctC ,V^ScF A2Zi7JtAvĥ(' t qs摵 @yfMH0;ʓ,Y(q e%Ӄ],8ջ.M `V}SQ5y("2#|gjk{$3ns_kf 1rXHϘ|LnwɈ%M--b]Rx?epщF>>xMYqS'7ǰ}9#x+#~d\001N巨5&dfAL(7*+wGTmUH4!^Hᄸd *J |;Ǡ\s@X }_G!d$M&X @ bq9VHaqg9 cpsVhPL*YWjŤir/@ u_"yh9A0` (ڹz U Yng(pk.6 a.3XdAnbV;^@ '*KXw .B40杇$'>%*[+ 09$1ޱM 1Dr[] ZuJ c@6%i3]Ԕ;CUUT L2%GlUԞn̏::f p^ ġFi䴦˕PiBgPֶ/TzȐz2B\iPDx y@u.dƓ]8'XCb$.1Xu`[P#4?TD$8rD8'wOοfPh 3<2%X1-qEu}E:p9A;]6%Z^DS:Ʈ˂N:1 Ǵ,ܙFAT;%lNg և[n1d1HPl@v.NDB(*.^ S`#-bvŌﰌ/2w`w1$_WC2.YE=@`,v$:P•2K7{=4 , .ӆ$.` d%8P+dZYn6kH0F~80k.YoyDݳo*@X#K` ;Hi1k~]1;W^ef%0 L ` al-7~laFXjK$(7 e}xp(pӴbȉBK)>j\,ًG!'b٬0j/I2&9 ׁl!gCn Br|WJC!OQ/!D*lh9P^\5~b b(#2|H4q'imt A;2 a˶pwzn~1l*$GMBdSXjɴ!hy͂cN@Wpd5#_dshΕmx)l잛+=h[l0yP*n ݡ8)3׀l>bzw:QE3[>ekf,J7лp-`U{:18q{==\h,4[9[z,MQa&F0*C& 9;s =WUk] [GJ/,d[%.Ws톝%V꺽pTF3<3Kb$f.U97p߲-Z/pH_2hZreX&.(u-[Y d6 |nhb\Y!*CRXXP vM܀B?>&`|**}՟ : ky7=W p ww>;οV\j3LUpu}>؉D :1!;Ȇ/ xБ\nQ U2wαrj@ l4:mm;{Zevy%Ņ=y>4p#VlA$i  ,rы]*Jq1 bjqY? ,`LnwnAՖL.n+7_rԾ/~ }=2h%-3w2S$C0g'-gM\NԪLưXsBPʫu^>vLL…9MN: ;VuڏR8٨zOnƆ\̌G{5x'?!֡9==i;YwX-ͤ[kXv 6DlkH]]NDc5\`DqA`cu[.*+spy9BKc\h0",FȔx!I,$.3s+JI3 w 1[%㷫lpo'xY_G  {r[ W"/g()<;0bV8K*7I֐b)byہ;α9tcsdIFId8""un0Ӱ9IO23x4j`-6cu[.Z*I)*P !KN4NHN|)1&;ocv$x+,S[Upnr\xDA}#{_gu}$s: `f\2` ,o&q!%F.i9N ;NjN~Clc} xd hkD (&6G`E%$ a"GaDNe 1`7(yf}Kq0Gl %噚K귋]:ޘ9>s7㌶p1f#1:_%݃څIS>k_ ]qöԥVü_OO\*E>_gu}7'|)!UW)XA~y5x'?!Vĵϫ^ [̡l!GfSة,$P0F$'jm X1S(}Dn4C[&7UbPFA) 1K'i_{,r#DY1Kޚ!Vݵgǔx'f` M,Uv e%2['Be12wuv%yk@4~: ;tsOU$s$'ÐH?x-Av~α9 *##&%hj:Xvaq3Ϡ($ AšؙK٢,Rq1+uc#䈸wHX(Z/F3j>*qҋBZ)AW_v*3M$f[\h I!6 ?h J7}n0jq3>-٭>uwW0]zטmJ&;-xnLj e]kS P{!*2y5x'?!V7gՇ$pHS{QD8y`vI.^P#:lj0 b5P ]p~ f$ш`ǣ'xY_GHD"MrrDKRbdx&LVAA")9jJ$s8%$Q56tLkP_"]bGkszr6 ZBW5x'.Ybx-۶B|ɧA`t߁nݱqBOpm۴-^o٩ rw֌t7N=WcXpl(eЃ}ZZR6&p8$1E)bxY<jMFrVd '*Oأ§u2hzWzPFHI!+H<5% ۷nݻv۶ۂ\,d𧩀@F\A 8h\w_ N;5IY~7$1r2$HQl/G_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NyX1;_}cW#DG_\ʓug5)r8Ln*NyX185pڳB 诽h>h>h>h>h>h>h>h>h>h>h>h>h;rP&zt;jg_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU}_iWU8^DoKs ξ揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹h>揹@XnSѵʾ֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏hZ>֏(!!64|,AY@կpappl-1.4.9/testsuite/landscape-color.png000066400000000000000000002514651476704353100204750ustar00rootroot00000000000000PNG  IHDR+elgAMA a cHRMz&u0`:pQ<bKGD pHYs.#.#x?vorNTϢwIDATxwW^B f]RJ):UmVQE)UjUڪJgE;!"{'h{y>Grs{|>^{3<3cƌԖɓ'['N֭K,ѥK5<xPۯj{G~tvU]׵kk6(P׮],袷~ZE1cFg}V!b4PJNgG߾} @@U?1u<%~|K)\ <@?čԆ=-+(PqOdD7^CgL  p*PՖXbg7 T[lε]jGޞ]:`\{UwP3:P#]7[ (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((^[%yױcu{ޭ[Zə4Swѣ huLsҾcwJi)m'IcCNȤ146dLiT- ̙]YuլJVY%gӮ\3vl^z)ÆeذR^x!/@e"fUY_z-ج@bkyɼD^{2*49 { lpu]b%(Rz묵GRKU+l 63ロAr]80C@ Zeղ&Yj,jX%wK.=G$Ya@6GGQć2UW:iF^uK}@ ~vmĈyW>j oSv9o+"dウI2thn-__t)~xY>nU[Ow W+7n8!ҽCrUu_Znɕw* /~0sLZV;g睳Zu7+WO˟.07Zexۂke1d*\1f}-]cc?7|# 3cƌ]tR-H׮9Yvٖu`lM6gsVgX5h,T>ΥkfS=<|}sCA}@P!#Fm~aZJϞ- {s9Lcl>8}Wn:lUȾ 'Ȭ.&Тv2@PZ+pXu\vY^{-G٢)W^66+m%*>s|ŬK 9f`8ҝwy[lŻᆱ@0 wܑg~Uh-p. < 6p%-n[jv:"{-L!'K-)7fL # %6mp衇Κ5K5f¹<@٦O{o89"s#p%Uo>C.K\j=ZNA") ey뭷6tK/T)fֶm~ W۵[ӻ u{xn~B6حOUl_~LVk4߹٠@,Dݒ@P{guyGhf_R|0gkv!O=\d}:fW!58awdJյyMe &nI (gV[5J)ԪU~9GXNSzk6R,J|ds%nW,wzG@sZd NܶcoYdj7)3XLKB@P$̗)S^? 47ΓOf /` ԈDeM(W(ј1j@"n khfA?I"2@-^.>T>MzywR X|2T\@P$̣;suyghNm}{ȱfj+ç闯 @Nw @$- SNnƎ@s3ߞSOno .Hv*χdeA>mge(ʏ.;F'nI ;&M}ݏ>&{tͪ_ VXn|{`!):d_)P)P /o_o5Xt,=ӭ2@-x<7e *0ޟ/R&Mʌ@@0n[W Ex~ P#|hƽ k.[ |: @%A=@ŚN<į~ƍS 9\p2|B )ԂI^p|?se*DA=/0a„]v㏷8PfK콷2@xw2|G,2fĘbe*gcm1t]veСJPfeCYqEŘo}+g P#.QV21fLx?ϔi1stO>- kma<2v2cLg[w  le3dHznޛkyټnƏ4):W,@]4l>RZka`Ҙ\ŷvR{KKbҤ\}un%gԹa2lX.$${oJ \㬺UX|}kj13e\]AYkjV `553qJV^ѡC:wn'޵O{we_~Y)seҗrŷK9\~ysaη?)W^PY\2 SOQsfƆitjԔo}+?^@SCfݲ4݄ {Ò!3/SrorGyXz-j,s1>/Sf<$3 3foV)Z0eJv)3-|'RnBؘ}CU&k\@=֍ϟُ0 xQ~|9&c̍'WN݌`Nqk @3%|z3ϬwyRcĈS&OoljEesi( S.rskӪq;3|Ur2vDsͿ͘wJ北bϽ @s2z&k\s̀@y|[szseMe{,=ҧA5/?o|Q_i;g?SrQbEf~f,MCCƍ+q -n8∽kʔ)ԦnQsWCCN<1kh2qbiD@ 61|'MM537WhAw_3rQ|o)МƎ-~ou=NQF6ۜq? .@Ezj. ײf9̜<{pql\}tfw4;m{C7*[iU* ;O>:3hРJvzᇟuYӦMS:(d5g' Xz@@ bK}y{Ox>jT :'/W\qFmoT#8SNu J1#W^O}~e„?{Ic7@ْ2q hge/vaocc9OO2k֬Wh{;πʖrcYL 3ʜ+>C[ A9%- #v[{mݶ{=p}k_Va'rZ~%Oy .U@QzuM7uڵ6wi!C,첟@|,42G|n1fR{AaV6X᣿̧^ҡR$ujUV iUV7ܽ{2s >O Ę1;Vf&eSǎ^"+n\V8S7._TXk/_Ϙ̏1cjYA@埏]~Gys@|7/w_Tclgh[oٳ̙3U`vܱx@J5[\V㷜77?ZXk{ ֫''K Yy/Vs.]\wu'|rs7xf̘%6>kV~XJ;Y?g*0K k[~|*L@$u]dWeY桇׿>]0{_L@Emg6߯M;dܔZ;a,l>?E H ȯs`뭷~V]uyk+{ Sc]!߻_/_@ Χ km~gOq/  U>Ժu+r{r)mڴ́oۯ.SYk9tQJQF)vmr!io4O ƍ˰aLǔ)}ƌt޽?X`޹E)$|]7`'瓝;wsl7ҿmo՟şo4ؘˤ6>kYgcƔl۶Yp$y<|^z)C~Qfǎ;gͲYwݴoRpU>_~nԔ_~7tk1-ڴǗקA Kuj $?s 9v09femE?mZy'3JΝ3`@6|҄ݮ>Y၆wN픵/F?3uj9vX>8ݻ) Ѻuvک6́}˗9礩It얅J5,._Ǐʯ[Ϲ@nɐW kr/indS n<2CaOW/&B́؂ Sb\xJC]5}@G[,TϮ 4){7'lw^t1$ϼ_Lֹth_f0?3vl 99gϥs90cS^..(ǫ4Ե~NNN2#@߹11-_&ǸqiݽdMy s923NT9wk]̚Vil~__^/˯,0P-Yw-̈.8'B$IK+曊 TvV\7ェ}%Z%c9b 0?ƌ3ᆲfv͙o^% i*_eʔ{bUiȜm.IfMW Cfds3eL!V/)C=́Q䤓)$o^z/ga+P)?]5K%O:Na-HNs.`~U1I "]7M齼nN;M*=]3*)VXkNs- ̇|!;Z:#6)-xn9:g$3s3>i"3nMVoihtyWS|3;!CF([N,Xg*|5WXko2u  z']ziY^Mˁ hFGn΃w=to u}Ne:|藿̰a DMMy}?rq45c;:_,dzL?3qb&MĉjyŕrY98H `>j/.T^neLKEs\sln>5iR%ܕ)綾Nierr䑹/\z鬱FV[-.eKgEҪ\8vl{.>џC+@ ̇s~w?^ՁzԺMyJQ~GfLU ]Qd8;@}w~qVPu~{s}9 uWWy!Y*]wI } `p@ 5sfy-˴IyS'G)H:nǹ Puz=w[?{lȵצ} u)y@{\tQ1#oVux|Hh//T|VM]"3fes2U>zw͹_(.TMw<ӕ.H `W.<+{sKnEՁ1cjK~YN&cީ\me_+?T3o=0n6ؠB7#Gw]@7riSWNN;UJ+?]5_U7fXE* y977VW"jsϭлFV P0eJvr@u<6;g핆cغu+r{7jT6\ԦYsѕhZc.}&yһ@ |v*?f6$O=@zvPF^z/ .ZRYlr S@'lMn1:TC6LՁZԘ/DGoZzr7NH ߾|s:vD_Ox.$*{Dj\$Խ6˭VWg]2ueUn:!mItR??쓙3U;@T)Sm_Q'$Ա6kJu)9J M(ӱJ %uB@0 g#G+9P:Tdiő@PJ@=ZqGn٦zh?_Ɂ֣O%zERvQ>Ϻ;ӽ{͚o;W^@L1cJbո.H 3k+=z7r-JPMViBL+.H 'kJϞx4H碕ewߝ3b.H kJcfJ$=c/(w~Yl1e je,@^:<YkjUz/3A QvaD@PVY%w;z|+6L>֎e* P_̫ۅM Gk%ƭr Bo:lX6D)m;dT^UlBWw!jJ+eРSzGO?M7͛o*9l[:vDG"MMӟ_T(~ G@Xj}w%v:rzc-1-+ܔnͤZʱn-^I+2 Ch ɐ!9,GQĆMf;_\Ze "&,DN~wsӵkjL{W@k1uvJcC^7ܔGoo5!c95}|OaDWr9,`v1;N N1"矟Nˌ=7ΒKE@7wߝeD_\]}ϨѺG"C^y4ܔ7ܶ;emaY J.eSlaZ룏O}6-7ߜ/]ww]#-xβ˪P[7˭o&3g2>z> 3 KլM:4O+<n A>gnY}VJy}wڴy߁Oe{4f6n:}+eJ?ˮ6-V_@81 ;f啳+ ,3iR&Lc<|z*/YZIydX;"dରJ|v>IffLIc3iG:1mۧCt욎5{deӮCK]zI>}7JT?!:(C=jTS5<2|;W:%MSS9VZNrP$@锼p2|G~~I =xeh]6?25 P=ƏY{A%ZΝs6wJ46{gHhڷύ7fwJpb -\_6* /V @"ͿISJp~WH[%Z姹*yd~3ecjȽW@SO@-)9sh&N]µi('n/Z eyo9ky̜^;mRu~lP˝wfmӪU͞vs9̚ncslG6'+n\wGeП?d{.;P:[o^Yg+2mZWsQYc 9J-Ԕqxa~i~L9.#^S{aD9FԞsy뭜xbYϥs|;:4fx￞Oʍ'e2`,KmD}%ܜ7vU9zkn5Z5ߦM*{]wM׮.&HG#Iұ[aV47Ͳ]}ß#7ћs!Poڵ˖[f-?"z( -h7 =jDWQ,}3 Ct]>?;L̜Y32szfM6)Q0ꣿQ3̜lųa?ky݌2mZOcƌ45}ۧCt옎ӡC:w gEYd2Wɩ ԁ gy9K4e eh[OV93 !Z)-4 (TvҮ2Vpxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxv}뮻SN{V 9a6q8ߒ}Sn<@?MKCڧwW!n\g)^d:@ZOm۩@f$qdR1Lz$UrДmҪbTԤiyyd^y7L4?'MˌY>];[tnҵcΊooEA ؘq#G~VŇ)>%3~)5*mۥmO|tHңOzIҽOzIYpIQnXx24a\2]=%͸ZSļ9%oLSƔ 2+S2!MIIv.=ڥghһ}V鑵zei `=V?gf؈7/tϊeųJKiFi[2 zj^g2|vf}+M5әg%ҵ+Uii Sߴr $<;eUv,I Ic#y呼<$/ɤ*}'gcX8A36ew+:ScO$&&oKY_se6vF127;Ԇј'qW|o\2/fCyxXv;##?>Zr;057=IΡdөrH Ȑ3䆼`> @3@]\\RytWaN{ cʌ|xnyԅj.s9o/76Ǫ@3l|=̛IϓՓ]B3sdV3?}:[v\|;0A;l;N%fotQFOl9|Tvz8/fh'`~bN!G,4OɗK<-o&#\N5'6jrsihr:yfrřըHJ@0œ_gY HJT\\>MrޫwI/fS\F2oΦ̥;ѱ>Y$̣oOVOKzɆ#5tF'&\]oWuU| wVszB92Ћ[sI/b$̵w_o˙_o)@s"&Wv^MMiC#P'@~TfXZoVΨ *񙎽&'PݧؔC !`}i~jC%Z_'&5<'upy+ u)G<_<[S'uLopy:#.K}UN&~$]KvI+@5#>$~:8gkt0[ Mќ1OwCfB@K\qJ|c)74%߹ uK'`_m-éWvdWo62?BhI=u̓ۃ52r.o$|ȵ3!h]gp}Cs?ǿ7,! {>)'y|<|뜼\ _`%9aˌ{W%Z:|z7sԳuq7=ܦL^ggMcb|IӲ2ve3){>3f%@y4|' 3UeLqA5GS?/N~f{pLyP%؁g?G^qK"3{E.N"h9O^ӟb@-83 -{57C3sdyS%UXw:kЗB=pM?MÒ &W Ps{*rS\Snv*&NϮ=Nl<|}46@KuPKnz'^>fFyP!e3sS'\c|?cv '=q{+nnZ{U!INr*@;#{+p͋\J̩Ywg}<>/Ozu]V :p@8ŌQE yp%퉬wT[%/[ )9M33yJԬ6w+IsmH2 Y:Y LH$c1ɋɐd|sՋɠd+#s+ʐ|ѼMz()'ݐ_^k她3 ~N}+QP  LjْCoe*t]{8NYɟ*{H \7*C<)~- 0%[5N{]q>W΋|kZQnL2YhtӡswN%;afNȔ2>S2iLw_ǖ@uX*Vd9IG=m:;FB5{rl~cY}5flH/Pd3tJ̵^]4CfE"Y~,-o#3ldx?}|16WܛM($yghq$Jfō tz/67HgȈsy|z. O7uϗcee*jdE:Zr&ll\ y y$gQݳb~>IfcSޛ=*s9-x9XЀh='ļ]e'@J0GUHٽd z6_[=O{|\@ƆLlPyoEYr,ǟ15メs偺aj醊s|Gedp|ؽm~bD:/h*vʢ9`=%}3&V O/ wu9Go\w;_#-y_ӡ]_+ۯqThGFGF@ןl~;tɀ=w +oN ${|Pmڌ1%6u,iH]\+$_M|Vu*DdߥrjY\|W9rB~34'P̩/0M>mOļ;̪=_d[vY/;^RYt"(M ;ҝ.^N63\[騬tT WܾlfV Nϗ ܚlW摿`p@>iV3<~{9h}$Mh,0Vv9=/1WW蚻˪K7nCM69Wgsk/KYջkͤ1n!w5%z߷2\t(NɥI2PS*]s?ǚWe*qSWk? ?̯ҽS%W;[o6%{ $_7\z˭>7Rl3ь\b+PJ}}nU[ Qz-,\V Xd >5d1>J% swqiۦW7/=wCQ3o=Wn[)6vfZ; ڀڤ2߬"i(àZC\.z,i-f1G%{)BzSvc@͞G:/2I ?(vT L+Pʻj,TS]Yؔ'ƕ@Od׾ٹ7Y fklsRGE;Y[0.Nf);.@ۡ#V3|6UbosPVPcrJkOҪRgHi-/`@U:1f~6ٻR_f-!c2t!kY zcvͬ.-W/\4eT?LQQrklsdvq/{pZWfr%+xJkY1嶿ѮBҷs~ٿ.!lt\]Nj7IOe'lRb=:guJlVcy?LQwƎWҦ2̑J~w̲1TSgrۿ?~qNfpݱ[~zC:vQc905/f:,Pʛ1.rM5.̸_s6쳟ג%455$=QO3'k~ l?,Y= t-} |@ԗsyYur\BJlP#L{9Iiޤ!hJo`){~-13x#ҥC;s|*oh&_^'#~`ƼSJomU`9ԘagB[j 5Cri)]Z& My̝< 'v[fbd.=iKOv'z+嶿*8|lļ@ԗ+]QZMslĭRpC )o_UK PUFNˬ2ZW׷ظc9kvѡm?37)\?M[|Gw3Pm6xvyjzUeJ*9g)fmD嶿ҕ;R$O 79&9?ioa@*u@ДϿ#j+SNfLZQf*YٕyH 34Kx0Yq9Ɔ 1L ;#.M6Ynm.˭-Ѩ3_bt\X>,XI6LH~,\[锜c@5+uĻӚޝ۟4/гKny68:?hй}.>8{n4b,=mT[ |I } j|LKؐa_ryAhqJd1ԓ1s\dl!0GvY/$[~5l΁:#\Ans^[5zB{gh sr=vʏݒ''w_Chf~_n+P%$߬x?5UW>I{6ϩ]Vs=ra>cKW9Y4-];Qs@Ծ2@,K0rZX956K_dDh6S̛W~ ui8 @*u$m61O+@k:;Sdڝ1vr@$KsCm֌zfeŹ,!FPwȄJlj鳥269/9;iSPr]rMۅ֥mVQz/aKbDJii<9E@e({Z]iyal*af>Irw2uBgc(Ceށ.%Vfm I֮C]!9>YeaE:]zx,E5Th8@N :#eFl><󯪯}ͽ5Lr_iQϵbPr\ ^Orn|ufJv4B45崡I@e(6yuhWu9~ղ$w_7H4ռ}}gYS9.u@| ;ɱ+!I[ R]XL7 ) w/-,Ϙ[ eM3=vݯb.VƿWVˍ 5Ris7q(gɾ{Ӣ ̱[!})7@c })z7 bVaP*LH j[Is j+C2Be1}t^.V8L||K:'U_$]W?\F4%Weܓ/pҬ:"?x"3Ḉ0y2ؙ+=ײ@ԘU+׫aJ(Vf`\4\6Viԛe櫋}iQ8*?~B鐅:d&cfd􌚖la @/s 1F˓gT/ S`NMH~Lk92/9?CkuW:ק)T.0e({0j0n;K ^fy,2sdԖ?,uf>Y2A ProW˞_ Msفy9e]Sc^:.AZ>ߘddމҔ\<B=j0@ڕ:Nfm,y%1bZ6kz;VYd\$J>+3d}J5ߏg砋`%~.Y; |&&#_K6MJ~6Kg2zJ|>e'ʹNs;y:wԫj1Oz.վնj_Iυ?gfyyy3kyJ/hm~iS0)9"SHCrRrGre c|ofJ|>(^_.; h~{E}Xls ^+?9%yC紜lN}"+oQrM]5x|P?Vf3 O֭?KL<1zpėD'eb @1oYyH jY&ˬ=>uwNf5-Yo/F 0/Ynln ֐d@R{o tj+3(CٯK H"m͵D679ѬmjrSY} /g(;^Ȉ )30;7&[$5dd+ 5mr5r.-e@e0e֭H jÝH]yߒuv̝ag%en},eZ?Fɛ7ԴVz TYl`RƔ@%(iʹEԒ\@Բ'+lӞʛs!?>ZSx'6#F -#e/#8 ']u]m[ӭ_6֭26һabj3%SWwjUx~k"4ަm4 ,^Y̕WMc{go)3i&Sl˵ڵlq*>H.I~ O {OVP gɯO9;ZV9,cH%vѹ{s~'2fىyrX{iIO59HMkRdk~k){D%n Ʉtt`;k7<EYL5VZRsQEY fJJjc!姾MHn>{^'O޵W9?J`YOЪm'FTףy@ m{bɎXJѫ䀳@fK S2`9eKpW,oYo@_+1 ]&%# vrஹsܼnV{z.[+s%6S݄ʾҼXQe$Yk f;eJN &J yuf阥HfEd"Z5WRe'w"PX4 MX2m}I<=9g߯M ke~~fJ w4v5+;Xif;P3ω>Mz%^QnK* $InIQr;59CrqRfKf(PR圲r\uf sʸS@eاnjoztM;,XÕ+.L7ۡiؾ0/3gFr;@{&'_(o%w$S_H5PfthWK[/fݧgCQ_έg؋r{9@*3x9>;~R&O/%1jĦ5k,d=5u_%\M~[nn+4$;$OV-ak%d'jIφtZ:3f斷r[u2O/}ün e%k 2@)ӡGFɱbI ZKlsϴkߜGש{.̒'9@e>EWg'|+&H6O]f/$'k1P{g>ٰO~J^[c3vZN;2vZMtz5dYKdE>VK2eV~\<(O,ӷGTzۨYPleluVb׬iyrB\]Xf_K*d2{9;|wy7'N(`FڷI66ڦSto(lKfʬj=s%+u D7*@^c,( Dkַb̙Ӝ(u 0sysyYnSn*so+x, iu䌤q|Z,ژEnvtR]Ͻ>@v\#z~L[DݚYgʔw*Y3 SsgEY* |2?ae?#ՠof6bU]^xG4B6$YǮRf,׼*15>uK&<]nK7m;4M7qD{$_- <;!/O*5{6@:5o/{EU $ f\[A4תּ&O(>mmOR^qT݊6hfr4k2VXb^1{v^,s͛ Lʕĸ7&Pb ;wۧ>JRҋ.ʹ?M/+Pq3fJiyEUՖ*ٕ;2o%&@rxyhbF.)Y&If=C| rTܟ_˛%#xƬc P& ~_/&@rЦy& M|!o\]n=LUNfzWZ:@ŝ9f_52?^?{׫OfVH x̚\nv* |ڸrT-={TMcrRZޡ[0UꍘB&OQ<8*hȀ^zSZ7xsP/?Rfu2sr^8.tSiWu]ciDṪ3Oi)PY .3s8۟(Ֆ2RF@z0oz[koyL+KT%X5XҞ[TaO)ܧ}_Dh-];QbFJH Z Uݟz/a3+,Ti`nJJ fWcT}ץmvq &v̚˖~W1RFQ>+[S?eje?O#*F 7&鶒JvuMHI jMrݾ6.9)o1 uϟUsK}'m;40oKkf=%Jk]255ߓ_Tn/v6hN_]#˼sZыagΑ^1:Vt]$oUnٻd̲\ m iS+(6Y* |l[139 Y;:fԻG'Ь:vkY7E67}m󵵍!!Yz#oɜ^N_Y3}{e/)P^UfO+~ۦӒ* |R`f:l9C(ά99kT6;cZ='@}r۟<=]R[c(&ɢ !!m}JKsɏ nslmlV~ {܋{yfBzƒYUM}Q'խ9tnއ䄌SCm߶;SOk?(}?A^蝺}5'9OQܥM ͞Q(Pi`>tN*GM9-gJeKX1 =w\]U"n^miko4ar8)OVjlthP,$ DmYtlwzJnu|ƴ\}b\1Bxo]{cjWe+vѸX|]i]+Pr//'%#YA4Od\FTWLF'"-תDG'^S.̙??gKƁ[B>}耚w>oPi`lR^IVINKfdݼfˠn<>>fUfoo'3 -?W ]r g:}B]PV9$;|Ȭzhv>+ϿU*Ah>(WPG=QvYo X)=ͧތiy<ۂIDAT!ܓY3*]UH]oߞE}ctod;\,$)j}O;*Uh5Hۺ,%_U nYCOѓN x;_Ng2>$w jKeپYo3f\Fc2jL|*zu8ԆŐ@Ԣmmw+ɹOOIRW}ӥW̘&[d\@M%vIETXJNTw&%K%IL5wK%UV=}h-f\Wi/t2ӭ\~umu2+geLџMI=9/OI;Ur7'Rm[?fu纇?Jj֬xbPW6Ԝ]QGθ73j)*fԮqJeUX@MHEHrrtrl24n<_%_̚. ^LcsVuP/vn*YctK'ݒvdB2=$_dchQV_QjwY~z \$($Fk]}~[uwR)ԮI+JeЁ* 4ɏ1LK$&#[Gw;~Hrh@Zmr@[{PaYJv@Q$k-l~Dcj dNouZ&m@ll H*-G}r B[wN~Qv=%K*> ] Je@9< @ Q\04;/@ѧ[Nع}ۜmgX^ԴriՍyQ5f%ϴ]3г`${ @ha,uWl_XZwu^-x"jڬiy{YiEsf*|9 T@msX;9/{Fs]mzs򡦽zY)eB\ \W8eh2-ՠ~h]sNA ٸw2ljڜ9uFJ:/@HNQ$I]riF&@Pr_A%ma9`V~wK!57xlws3{tJ98*$'[tkau<=ÖkGwq\ i1ߘ\e||gsEU* d>6E5VJk}Zm88?.O4v7eZ3ri֩Zރy{YJx~I|\i-g,E%V_u\.ҪjӶ[WvrY~Vxhkl#oIcg'Ȩ_EE3`J6*nuZ^M]N>FK]fޭp_1΍Nl$_s߲nZ9k~u,1%i6ER#Z,7YωڽMrĊ*fcӿg? # `.;g?eбK]}v8&\z$g%Kϵ!@L,sdnFBwZ}gՁ-Z=7NJ@0OSGfzb9|9@LˀӸbr2*ٯ.ܕ\r*VT"Y+O N̷6lyM}N5=,ݸB$|+f95^;PJ2WҚjHIH6t^c\04Ԟ xih9;,3w÷W{ؘCKZcHM9]qO̜Uz/O/$%$`ֺɣwզ.;ψsFYB-}ow|VVӲz*M|Y35޲LzL{^@sKJLڶCX4Mro2U6oٌ"WdI5c=ӣS>s,< M +SK]ۆ 8kn_IN0_.J;PdddLr]22y$y:Q>Y5Y3Y#٬U 2=fϬ{Wr:7ƒ)?:n;_[so]YlJvY7}SUEAè]V*oSȼHF?dVl{.e2kϠ q4KX<<<<$WΰUʉgqYaݬG1-=я浧3i\&>?Ϟ$m! !ҽoz/Kd%{,6(=)-@ےՓՓ>nV\T^A2>`n$O&k䋉d dNm$7=O1%M3nzMY<+SfeʬLYs>B]ҡM:I6?wnd,1Kv̒hcum P ޛdMd(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((^N;tW?4tH^ld|M4‖l̙ h$sڤW-|Ys65WgZ&f|}vRX&MRX*ŪU(V}.]T(VT(V}NT(VyKY{mZo̔)szdZGno hܘYS251-ej2)C2-{ypJ^߯;X{/ l}v2-o7q@>ח)h/S3wzeMq@K`z߯+ P8 P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< P< PJ5dL0SkB|_3';~u[4]{+Pۥ_,=ҡ!]:4m̚ SČ'fܤSU*Dԉyd^{*>ןɇf֌nS[> JA|N TR]L߬DV^"IYgLMim̌Q 7͍? ee؎iɁϵ&9ixR=(mH^U^4Gmϣ/s?Nw=7کD?o53uS/zZӳ~PdhfNυWL;/-/V{<{_.> ~3[L0/ msMT"_dEqTV[*?-ȉ3sl{X;;ogؠ.Ba,+oI> FCr7r9Lw't_:ÆDs<8' PrT{SBH ZN;孷TBzSƻ>'ןWh7}J91w\4J}B<(}nnnn[Qt>?䚇kHu͕Wo_hNmKبPAW{MNqD!ꕠ9lwZ[q>eԃ9iJoU2ʊȾck7~Xc?K/=enj~~7w%~h~GC پ9ڴKǮ:5/V EVhn/Ο=6.Ӆx~v99:'.=7_oN5;һ?8#Oͥ8ڛsysOh~cQ(Ru^6)SbH Z^;UBz|ج嗹LZhFxh;?ĝD5zꃳƲx}؝&i۪VWon]ߟ0䩥m@:kͯ!\vT k@:Eq{2twZgCx\zPGnʡfԃN2cyj-rywV?oGb2m#ANYC$GQ>;ÇgXPdhn>;W_dΜ|N~Zkc=orl;~>jY>㿞.jU}N%WiUaذt3نxv\ŦL?A%ZS^W}-}+OY~rN:5C6vi:47{gk;6]-R_saXj.Z!MC%\rIڴQ (@Co5EQ^y%mGU EVWrv#7=2Z9?!l,;Ֆpp.'K/jdlF !heےڬJTSNɠAd6K SU qE;rPGfGԭk(~Sm=!yj-KΝNJ>h_euo3rla_Cԑ](qF6,ᆱ g/I2I=9S?cj~@8dvtzwc\!)TZvHn-{D%_:!9t5<# j2yrv%ٳC69g?9$ɳǫ噻kw5! tl=jz}.{ rYEeos9ߪt9#*,9a=ՀbªK/es* RZ;>vE9~'w媟*-}Iy?.4>m\thP Zt|0;U_{+,>K)nެ(p:4O< cy՗$=+Q~̜_2oG[ңJTs+4ݶG[y(f5qbv)G9sC:1gˏm9r˷7Q6)IN];Cs5x~]Pt2|O [Nk6o~jsX9|:T V *gvyYPdhx6o7]}MteZ[?djB\{hVX\%g!YG͞q23!Lؐ.1];dӭ* y`qAo+k *Q. =z(,~+k)I@J|0A%ZϹW=ߘ#Y*K}ӱ[:vKc̜2Q#2alG3?0z|uh./];{bpX-{{^̚Y߿X|a`d-/횧 [0.t;ɖ[*,_~)A$=;NP Ey]y\v-kr⦙95tȐY},zΟoʳ?;8!bP rN9fGh+ޓolP@S=|<XXtg+]Usc&N5.>cQ` >;Mq  $(}tJ(2B痻W_ ^?{&Yb.Yq:,~3̞YjнcZ]%gY~ylpo.'/]3ɹ\pG6[ћke~AAso?fTEKձ{cV7-2mrԉN~$ezl]^%Zמ-WB[y\wj-[> |saWB~l[ƾ\jƎNh,J`tĂԬٹ[w~&_84}5?1mTK hm\{m/z ~h#ezm30\vזz%(UWe0+2N#Q䬹} .V[~|t9|iʕ契haqH7?n嗷dfsoiLήg6pY3b4( 0혓G Son͑@`qDv)QdhWeG̝,M,F]]~,B:'ȪٱkSagxQA3=3)ʃҹQ1 vХy6o<-'_%g;{lW7슄0h>+LΊ2i>;NjzJ7cI (0뮹VPdh&w㮾Bߐ#o4}[/6"9~xF=XzM^|ظzvegUULw55;ݙ̛,߯w`,[\vY6\%Zk+|=eYWBaK"A@'Wdh^y"!~(獁~ ii.ÿ)7~9&=ҿ2gqA%D>EP[7̐o-~SKkJ~X W|KS?5GQ+k%[)2F"G,z~dA4`H/m:W͗Xz/?c *f/*Q/+u{cͩiylJ*=KDKҮ].$۫|/휓̢ԷIe5.5+]vɊ̞Kٻddkn]O;=iǹ!iRz/T@G.?0SN^Μ913\ʍTy*5gm$uTV_]s^qF*3έ+;wU/樣>HukwٙPKS\Pm" y ;hԩPCTeʷʌuo0]9YV٤.d S3|vz9il_vF>-w&(~[-#GfoghӾ}.$mE0oW˩#reLC-Mq6X?du+C>Z 0e"+2?unem7~$kkېNe:~c7H]O!L{%hgܐ/M @r]({~#G\`sYiyauZ,R)3rIPKS\ @4Ձߨ;GOO33k"+2oT:qz̚ٵ}uoL|9[<=Jsַr~N&1I֧'U콉Z潡$;K/t pI9$i6m8 M:9F>:+]ZCmki@P,/ꦛ*I'?sH-BǎgTVhOq+>jlܳ%IT\N*ݙg#?kHrMWƙ鮾$ó%~c:QHL`y%9OLկԭmLT|on~,\1M{lzPQZ3 Nqkkk)} ˵HT+/DGm䢋}5|Eٷ"W_}sQ7uwͶq?%Wyh|Ӌ9nySdܳ"۬|/>=YTÇ?(=waj:u/jLyS+i3s3%UoҦ Lە9Ԓiqǹ|TL4] SWWLkQ*2ו<͘g@EQ$ 礓e5ޫWn=n;)24Oʪ]}{'g͹]}"L+y 0Q.+>&'亇OTv/{Y緣򷿕6M6um~s&9,d1Mzk|0ItQWZˏcMq6s܅($X˲ŷ ?sךx"C3^}_%\}V h~(9P@~udvj'*׫sږ]O+0fg] %ofr߬Xp[m|֎;?XA+6gv5o0Žl\+ckבoŵHzȵצs7Wfe |EҹG JNgE(;賔SqXhyȬud^++k benzS LqnLXvCZ+/8Գg.n1#F|gk h&ejSrZy{S\()8.3µHQ!CT]]~\w|h?\} RCKϼD"@t=Ԙ x|W45gN*۞ ʭbY-?1V`*8=o}lm&LtYlb:5_;%kOWMqWӶ͔ϜjmL5KQvȑG.l#]kӟ~.T"CsC[諯K&_]ZqcJl|e9m)ܹPQvY(x~:'ۇ~{l|@,w.)|jyJϫsBOqS>/scYw@, DqN8!_r|2bܷD9E*'dՅ.G}.LoT 1-6ǟaG}.Ll@BYy1喅ߞϰaswz.03Es>k >&.75lN Se,Yk&oez(;ReNy(=sw쿢SI +͏d#vf;'bWoΚkg{~bݻ/>jJ9bͼ>S\MD]6Z%(T#׿{3Y:uϡ-N rtUQQc*ll{J}5g?y~]ŮRfe5gmxWO6den.˟Kn[A͘<>mR_sr~M&/צ8 @mr%Nr9/>]KwAWff#7ܤmTӯ~ctf" mUJ,է)Ӭ7{~vQGe߬s kE0Ԏןι=M3wGeNqmki,WJP ^:>wlJ>\>g`5%iqC9GM jb~fv~饬vI5w[cszǎ*Mmy\;S/3IS5@, D9?>[nY߰f92+}<_}W*ԑYW5U[0ӌ~g}mgy&o DX~wY&UP|goe<%;@|cs9Ϝ-ͫMjj y TOYs<\Cs)i|ESX3oʡ/g D5=;\Rnn4Cdߐ#.ˬMogUf5[9֍mV K.;|!ڬj-x"C?8]3vH|$k3oZ͞/a;.(3盿.IFvgljPlj1EwJ_ go?Fg>߬ړO?$Ԭןɯ?ƎetS} a,z74xV4IMΨy枼OiDDɶ.G$o#yg<>P.$C6Ω#b Dl]2S%}(']$w>?֩},>+YnzS۵9$ ZLk mk}<3{YV۶]CKе$y>!(*x|B7ܑMv.5P~ӬFڪg>P%,FVߪϭ:U`D%:*M8/yBmX, g!´;!۟I*ߎ禛j;Y17mKҡCa ~zFQrl^|8ܴP?k>-MC 8C6N榳r2l$嫯WRp>P=WТ>k ӽbKCu='7,gѥ1K.Uf`/2<@uos Eo@͏*gO9#93){vj;"ʄ.f5P 5Uh»av%Ҵz<΍ɯvW,;|{so?Ϳp2*9#ʞ{f筯@@WWN=ZquV?]hWH>ЊYQ~|v]ltҴz@|Z^0oQcIju~ڵ%Y3C}I SԷ]dxf.?*gb'Z*sϥy蚒͖4>Փfcf ħ'YuZ{' (CѹW ͶsЮ DqEV]ʻ{M-@>s䬛ymŠ7 Yc~xa͞o;S7K 5@#]qhlltW9sr73eB4t'*6-Nʏ.456KҶuV|p~Y,.j`G'u|$<mO)'W,G/[,J gr5q欳sù{7_b-=dyobzя kmΜ|;2e~h)n"_U `.:u66BZ] {qS\+kO8|)9mی{VX7RoE}T6=Qiee kr䂯GX]jfD.CI[+5g^Yz/ Sg/=f{(WvJt`ʹ캼8 PXkGh{Av9)cFWDa$@*Q{qTfyTuu9[yW9+ؠ$Psͯ~Ud][oUWt{@6[ Z5i|NryWVi5Ԁo}+_J w>@]4kFpLIҽo2,,ώ̘ӷͨ+݆{fTht˙ߏ΢ZrYE6x饹fuԉo̜ai @m=+g'oPwCgߨ:P;6GO.ggZ\xa4TWLMge.kb;ӧdj& GէC4vNct]%}Iū]zes EI ̙󿓇Pw琫Ӷ5e'9Qh]li @5R-7]Oͪkͱ/gcy剼b~)c_@O:Ȁ!Yb,1$KeתW&X(%{.P_=7{M}N5,"S,O/. 7+PF?Jee5>O2K2aa4.ޗg话zd3dԷi [>Ȼ M$q յO=,@-~L+!5S|쿿-w53llZ+ܝ/qyaɰAL* P8:7Y:1+:rnflp}{ $#O7ʹ? csy9h\vdNj_eS'鬁p %G-Kylt~w|OC4KcC}gniW/n~S޿;=S戀@@s=}5ta7d-Uhn{"+\!ZaPsr2"[Bˈr:hMnd2"g}}NYա!\6mme}x/?u]DX 59k̞Y;[2dcUZ+ȏ.P_[1=:)9TOfu(ŵT@4I[%VrΕ[:-_\:ڰgʹjC`p@m~x?GR%?|hou2ujV_ݘy,]lc DH Uל̚Q:vQfThe ˔J zu/N]]ͮbk(NօLbLyM|C } ]{䦜cfND_]主@4mfmbC:WPחޅi$=zKءBC%r}Of{;+6T!CX.܅i$В=vk>3U~+o9JtHc_.};Q7Z'ӷ͌ks=@ՁVx&X=^ .LM#;rW+?~ˊSF~^|^E{iթqSH z+>}U[:z !Wzbbd5nJ-3gdzEK~pIڶSu~]H 5i\K hQ}_N:&U(~j5-NCr۟.h #l+׶GdRPޙPz Ҩ){Bk Bz0'BîfדYW $N-2{^f(9PtD/(N DLVz/<6ϔ R6?}MɁWbt(L ϪqSH Y&PџW2G4UѾSRn?M!*#9aL_'k?>+Wr$uD/4@1V(m+sSH Z~,'nZ;Mv#nΠaJox%:@e-m27+OM2;h-Kꩫ+)3kbu Jէr&^^"G=)9eX(+2va&@@y?<)嘿JoM+*ŷ;Wz&@@5y9~x&%nME0,+ё ˗Vz/n2 T7ߔZnX9{(9ܘvP_/Jb D+T7Gg|H cn?Ktk8cw=+#/8@k>{/nԵ:+y$Pz!ocJhWsMi@vZ;#OͿN맡Ů?lY>>oͯblvCz6퓆-^Y2`i" 4^q7JhrUi^Ɂbo$/K+Hv}ҮROfl۶ijRA|R/Csi_ 4kܗӍw>ίRW@v_QsMy蝿A*㭏)P+RZk JlK_ĉ #ТtW_j}2`H[:VS/<מ24NgtZ}vzӾ]({nG3iZ>Ac2wE;1cyɖ)΄ ~m77?y}5\M~V!@,pRh2nwj 4d!:==k_G潉]һzͼ˭ʮ'yz g5Y||Ya8gNqP$}-?8.Cf\6]-]cC24_Ys3\p^{9֫ggpfo@ wlsp98#7m>rGlOm?{}_(^O7ؗ*kO]Zv7QCVEkQ جn{<-^C<<+S>+FH^wflbja;cf;S2JzaI ƍO7[ϫؐ5͚~i3+ u}] g3.m` Z]º0}j^:ΤqGOϓe4vN5Ct+e|TǛם; K2t}G33nRMʸyGpJڦStnLtnLteMvxhw=< _Ccb>^u?s& J9q24A-}8jgex̜ WvlzZZ7ћr͙P`\|2FPS=(@ p)yg2FP{O -[/ӔH YUMsu$=;1U͜3ϨU`RpunR9g<~JOP W)@ p3Je(`^~sTǹe(K[%(ʜ99&h;57 %@c|^hn>' @`tfn~T%ݾb(`a=JqnE%ؗs#!hYs 9/>S1ȿW̤q*Q!&z~L<8J%ofĕ*QQ΄xu~wKYLP1*M,?? i߮ĩ9ƜqC>-;sG橫k-숼<$B>3׏#ӽc^]uA~wGι%op<0Vr\ggU~InN'緷緷g"}~J[s\ZןoGfg{|,&riyy'I ~''^ɚkkgYmoy[< ~kN?ˊۤ2-Ϟ'}CdD'ZH [OvYsُ҈/ J*Ky<\MPe󛏲V 2u2@o;o;7.&Yz \-WMfˏ|<{M2e*5PdhnW='Zj$Sg'פM}e2fE̢YoY4]:ɫ7ܛ5&/f `aՠ*qG v).IyC\SVJU=WkND+xG+ʫ`?53܆f c͈ d+p1ϡm4]*%x:\hh#È>|s=矿 ONiX@֓~oJUj{^'89kwƐ~TMw5MJ\p!}Q֠zFW8eȡ"p{4cN=~y~ã!T믿~SZ79s|g92vЬٳ曇rz7?ÇGsA\|r!̯{^WS2U!mꪾE[wW׈-:B(G\]/>뚋jzf$wIRr9Au?ѳt?z=d^ܚ;X&Km=?~|ĈAAAG>zO<O=ztvlcǎ=p@4 DSrU`>"YaTsڞPg=ۍ. 8-o]pz^v~/h޽V9t[h 'ֺ({KgBZ9i֭lٲ{מ]-7ow}w޽udgW_rr,QĢE>&C8sUU)o6ȜlU;ܧbO<pS7hz2I4@o?9)J#:Gl!mW{h9]A};*g|DKGL,s5Jj}EE͛?ܴiS˖-tC*TaÆމeߥիڵSNY%߸qcѢE^lϕ!oPD"S|BtI j0Ws w.7ИZG(zbz[kS9 UVx9ߘHY:^3PoouRN#__gy&22o߾nM8oə37mTDիܹy\8x!/wC5ۡD"S vQC*Bk} خ;qkhvB(dߧtmZtC7Ь'5;6hXA;PRDz7Ў7T9+`[L9ʖ-?N<9,,ֶ͚m={ԭ[W_9s p7r̹lٲAq؆ +=T W+0ȸR[p-4F)Pp!niSB'hCKxkZR`VW';3)}2p]^^^C ٽ{w͚nnBVZոk6{^~,Xoo3g>\G6, XUʋ53Xا|ZG}iX*p!.f ӇljaHv7ҿ)_?*ϼI5[5jX[-~A$! .jժiӦwK&M?^rawߟ%W_&M$2ѹUm@>r:yD 8]_?BWOh}ܧS-5qnҦ݀HsaZUї3M6{qJB4kGk9m5{^zqMFif;*ȸjN%Y p=jnB}54bNEW.oqyhZI;PD6f PFnۺųcqq}_zPP7|ӰaC'C=~?lӦ 8WSy5X\D"rSYH.g&P˺L(^;v|jyB8p?+HƋ4}  N/_UV57_|N|gv|'E3U{(/NK&kH%^}*:7kpKhAx`p>FϙC5MN`I8QzvݨQ#OB޼y?3oЯ*44]sWRBM6D"SW#k9cuUw 8]GBq[ъm 1JܟX YW<>>SL3gfM6=z<ا~[nt0@8_sL)je+弮[u wnъ#wsjGE~ bFv#H~*>g EpaK6Pg ٲe8qwMm괄|CU 33PWD^>Dp!n4pMGi>{Q>W"q@/ܦN4="Tț+u-Z*U?nCEcƌ)P6gΜƍY >וV-*ԕHdV6=_޾Dp!Gt,BBu4jAi;qtVW?:,t>muY{tVШNt?%K;yWef * 2W^f-2NF۪6eH$2+j#]-:()nݞ\̙3h)KG⿙jŠ_Brh +/*A zT}w7fE:| 2ŕ'B9D+bVxή־׼K.ܦbT+ o}*<ڃAӦM+W m=ӧOt钉›5k֤.7Wv17a v ָw"jU(,bB RIC\|X.}6XOUPLyrUVw.ZK(,H?5]]~AJףMJ"~RJ5k֌PUHHHϞ=Nj^xc;vy%%%,A>龯VHX*5*-Ew\qR7x=N _/|~aPr -ŢRȒp'u:Ä.0ĝuP=2^Ro5xF}WBCfNԒ˞C]=iJf!\rp+H$Jb~j.(_ԻWJ  JII֭͛˕mDJ*͛79ˑ#G9rB .]L2ETz=g%xiWZ/HX#[9x%$.m半Tqş#%Sz+[YUR RB^ܨµ->Bk5Sb$8}G3b@(/['lr}AXP)}pO+ݦupjL$3휳P3Z]KwDb^ʛ]r"QO+'tʟCCZksaֵkڵku֜907p?~|߾}.\~cccr?:uɓYVZ wҋ yު/Ux@XG?o .ӥ^q-.<-I> Rh)K4K& 0gq_՗"Vj0e郺*=k1/2pT/^J$!W6=XcGpT״}V"ԫ5RJ]_~s+WիW/]t׮]/SLzz锍z=rH ,RC=d/^W^ٻw|MbbҥK.]کScVhkje˖رW_}yd WyߖHXQ :>[W~]i+k;}G(㪮+ʴQ7tq3[utmU =gL.}Ն;t ּ!j[HϣM⧺x=uXIK4FwizF~Fi6lx'Νk/^x͚5 {~JqCZ?Ku}e˖1b%3g裏bb2*O?ԯ_{O?-^=a)RHbN8aIi>>>={ᰯ^ڼy}mZZ̙3SRR}]YVF[/?E !֫#.z:>ja!hCA-u KTQ  D\ wORزӵ'MQvTtovPzo![MFe;[nmժUOo6o\J 5jXUT&MkcbbZlo{g}ֆ>c\wGHPy]upF*JZ{MΓt&t`: lk׮޽{kׯ_Z4DPIDAT8/^8}tӵdϞ=O ֨a _~9%%:4w\ܴi|qe x$ՙ/_~W2[9ZP7lR'e&+S= qwMgs`E*Є*E&a  kzcU\"_Og#GGԱcVVͪeҤI7n_1s|||Zje w[^1c >!7@d._ZiJYq6ohǣJKGpY[[zJjh.".똎}/v z-}k&c*W޹fCr*VxZa^lZ{J-7 ^Յj~௶ivUl7a„| 6|WrW\OLג#GLPz0FiߒΝ;7uTG޹sg.}F&WUJ#'k0zPߣ #IwlvPZmg٩zC]4MKu6+Cz Ö!x XvVMUJvP(])P YUijzNV>TƳ\ANHҧmjSstBpK\.Alׯ~UTqԇ[j*2?I&Fp۶m+V0ToitD:uead 2ho5٤{wy~zN|<(e5XQ3guI .1W ?q!nzlRxK}$%O9=am26Yhk*J'-sKR;axW[uݮN\տ0[E\YRRR.]=իW߾}cb?=kiiif?ez ļy~%K+׷QF\nF"LUN%W^>*TWks79R Ӱ>cs%4Q%(+Ȥ^L 懸hiyzKJQj;27U֊hcuASNJI| CRf˟漿Zq&g7]r]v׮]_;VnO?Eի?`_ҾlhCR͹2 Dokw^ѿ٣`*|N(5 wikz֟Ye%(a+zVn C.ۇ_?%}́dC+d fw/9Mg1V.b𓗴͉I|/f7pk׮)))5jݻץ022hªN:AA߳^~ F`W^5W> A?vVOl„ w\Ș+W-?Zj=իW+W-iqJ2:uN1TbӒ1"@tSa,s: kF͕?L2lPGCB=_2%{BkW'\p¬/EfHLV׷4wݟ-3s;9]3X8v~M Z@{5;wd1d 2eK+LnSVaRF _ӸVjeʹJ: 0[RJ=qp+U16ą+UvC\'\bY16 Oe`Kl¯PZ6喫0epC;],6BB.t9r*P!gF{&+R\Njk=ջ26অOio> CܐRg`+U8QX!MVKqPi:j`gU{^Nԅs,ypuK?T "'3Z~LLLILeǎ T9C7_ȜhmꤔX+"_3Թ 0mfأ@Fjo/[N0 >6W~{/j]K+ӷ<$U9xˤWCuf;*P ۽_}g1GΫKwr`qK~/00e3>>>˗7wlv::::**\UV?gikFw>Tk)]0"Ғun =OJFmi[~2S3aFCЌJFU *tĆC\3_oׅz5KW358.5R/ݥZ#u_\u˝x gG5 0WC2 789rhyT\.X'6uLԇkJor}׽|^Q)7@+|wWQ Wx:RyJPG3Պ|zVWj|2YūޕzWz`Fh">љM3Xxl]vFߴiShѢF2sKжr8Sⴹ.a *닽 dJEUH*緄( }1Nһf,QjU.6HOz( =;N?yPuũ2,Ei4ffxyFe9Lms*Wqq7m^Z4GjuХ,<8MKTI%pi۶*%e˖-v2U8JbWcZSWgf费fv.6< )*yrPpQ]gu]Kfm9rǭ)b]݉3\l=Jb˳Y㺪NT X=-/ӵ|iQoy5)Cp}ɾڦ_0COr5}mt!&~UBbŊ+׮]qqLg N8as;f|2KL«*;~򰒣3Xρ0 SO9*¯WHQyvJ/W*jʀxUZz/h rd|@/q7W@ Pq q}! ˑ%~7ĥxT<+PODLWG'*Wy=~ C[ޟZuDM9\_>Kṕp5\ A: GnBp]=|21@H-&l6UN_v]/i;Zfۯ҃&wsPh*v?hgJĢC~n09K;%x+w$y{{h˗/̷p8Ο?osM<@d& f$_ӏ}Sⵥ}Dr 0Y]Bx8PtFPﯺUKj*5PUڕ:V|Sof& @ZS;͕+ތq!B?,zd́TByGmթ41םS:[iL-'$zk .Z:Nԍ?<S¼L̦ 'B$顇P򣢢֬Yf .]bs9?鑁2JwBks r1R5TzZUϕ~yYG9loTNފCTA~+u1ۤM̗W`tJC\o)&bKxuUƶ䘭5 XIJHjczv$5 rA<3wz"J?ZP[a4Q|LPCXl+b f5g0ٿ˗/+ D0:4NhU ]cis9asoKQ26 (~5٤) N^DMvhGUs '7W~5.?zI%5Qz|_|!a қJ%%@ͪgcRGԄK m$ٯ#5ź&Wa WNkZC÷d u޽\rF?~ơ{\p)7Z3v:]fW^="9C˨,n&t#3\4JTͶjɕ~9N7ES?L2`Mjj>ֽ@RLyc=뽦T?\טϵ}++/{΁5[~͒sfg<  N:iӦ̔#GhsAzCCCcccw9+bDy /^gnQj}DLo6.d"lt3}f*A3W̞97@=mUC=BKޥ:dD,vɯW ax^z.]h3fd 2&gΜtX!+6}]5?R q3|U5A\́pn<R=mr_Y_q1q3Y7M@ulѻ*ϖ+W &ƍfd!0]oDD<]x5O΁--/kC VXW Bj!๘Dtmf+?=G3<{Kzq>K5*Htux"7]u6PjvpN=x-{͛h3Ys 29E"Kr9s?50nvKioRtvx"@8z?F1~a #!.# E~ʸ_Ӟ4 K8EԦw0h~sWV&jB|֣' ޕVzvT6N%Z{\A&7 ҲT:}qKdaUx5k?t-.\x7*- iΚaސ:|k mO$ֽڟɗ[LD;mыa BEhrWHUȫfґZ֠)XEL?З+ZUٝfu&| !o(I1[~aY88%Tm#jZ5W~nVխ_]%\P(" _r+x [Aү>,o kAKLs-Z@+ڸqٳ-,tY0|!'(TZd"&7EST q7ʩfLy6S<=I'c0%^kطÙ2w5j͛<ᰰL'%%9$&&-9E.$LUMBTm/ep&L#?6ilis hu>W>)㜼sWmWm|UKe敵q&,^d 1^{zȆƌipOMMuI1]/"T^rM?/eiZ ~>{PW~ .V=8H.4} QlYj |}u)4iȷMcb+̈ <àA^z%*ھ}[oeyd 2 Dz 14䬭ָs4h48H:}@]xvD%=PgPӿWZ}yyg}2C+G뙶*Oˇ1@G=xΝ;Ϙ1Æn޼ٿOM?Iw @RÅfJ/H" ջ29gw.js| ogo5' ,ǢNuw_5f5ND)򼢮R.f"B'@=!wW~O?ێw~(9Nd BqQ6:) JF`zޔ>:k}5T)Y-;{Xaf&+.^800І͛7{lC@9{w@Va M Va@f}Oe*I3@Ji-voHmz\(YоSn'"E,[,G6u+쾩zRpO{e.t!L Vf Dd\[FxJOȇPWv״KB{5GI<ȴn]!pKy]jUBl+!![nqqqHN6X\ *Lp!>w{PQݼKJRR|_c+=T;ȠZHs(Q=Js^ײWTc͗+ >AoP0"Ϣ˗.]چǀo{+s;Yɺ@x*j7/J]X+x_\Vvg$}#/2QW}NVn>ӪސTiϧRF8Y43gQ́ YtkOu/ Lגd|әgk:nUJ@DҦѩy~H֥Vܣ4P%kdmجP %n.7H?fU j'pi Eխ[מΝ;n8*"1́H/2p DNmlUunk&A7";}52b&-ZQ ௶H]tXܬ]J}4#Y)eEǩ 7k̞V^OS'd p Ҙ #UFiUM&E[UtaMGqA\%Fa_}(cO_W<pgEnҖ۝FJf //9stɦtbn@fRwtFoïgdm&hS]l缏 }jê!v*bs5'-}M7lk~>%iژϵhoņ"B~ Č3kO]gϞmӦ]>:-9Em@\Q+:MK:Mu?@:*hq'c$duЙ:[9JISip#A}g*͡<٭/<5MWnMzSWTTTfN|6~n:p'́p5d J DQJ)&W!NAwЍ*A "~v lgx=}IK@ON4ɦ!$)SN6lpVc\b|gd^әC.$Ֆ9Lg뼍O2U$.,:aaFܒeٷi YQ_{TPjgR@9l]h7ĎrH}>w>8wU+w7yÍTt9Ȫ 0}t{JNN~衇/_~={v+< ;'@V.B2Jc`CE&*SP!XPZߵj&5.nCJ%%zO>񱡮/]nzge j@~YpNӢ-?ўe2#͓zƧx\NPL l +qƗQ~{"sQן<&x;cn&2lk׮ͳ'߮]+VHM?Ign!bz:iW g @ɚl`?Lj3[jnnǚS5Q5|QUTl&R}{3Wh?pQ\q1|AewQh Ν;ϟ?׎bcc[nfi~rrk̕o:p'r]hKִJ5Z`!!voFȩzJZU`?s588) JQ*]pi]2C53]qsC+~R13CQ1&`t 'YEǎ,X`OƍZڰaĉ ϟ?SU@sGEE%''s ӫ0%8#E,UtMOG^-h ]WU1KFJBM.|mtS$$E*{W_m5OX Uqp蟿6Ԓ6Grڑ%<l͛7ߴi 7 `ۥM?]ҥ6<8---Eh"88lٲzF߳gUk3mUκlU@GuK}iZUWu 5씩pUŹM˫*o_'<l;#~Ui RnޞÈ#FEk.WVͶ@0"c@D"j;4Xx2k4-UFE^-t[Mu |I1tjTAU)-D.v˖-˖-'Lucuq{TZնԨQh́2p-)骩){E']i `tI>F(ԍP5M>E3!n=`؋؆.f͚˗/ 3]QJJJ޽y,.azZi9 \_@6U9~ O-xbɏPh3S 0aद_+.@Ek"+_kX*3[}JK|oV~G܉ éQ(uv*U磷UFfk-)Sf͚53]ի5k!]`G=~:vXn]GuׯseSljo'l_RfbjsPjwRHJ>?g'6mD+P5c4Z^7; 6TRk֬ɟ?/^ܶm۸8Oŋccc͕ /X[MGtn푁Jד ):k*@xs:>1Z|ӄ( yΚ\́`h+g p%K]`+Ov횘!믍V1l0kׯ|F955? 2p]'@{՘# {ly=+#=h353Qf?wTǢ*J2&39]h1W~iѺ)um=O6r8E%֮][P!yw)))y-?88x^^<+\رcMd͚5 @u_Qk)GUX/HQ:R9R)纡ӵ 0B !E}zE7lnY]#VX5Fj;ISx] Ŋ[fM…MW4a„;W^}Ut}/'o޼Va%>K/@u9RtjJ-|u7̎#?nxAV]*;Kiעk[F fnI-u7c2Zq~EߎPB6zm;JaE]hQG5b rjj {<'NL 9s\jU2eLjbb镩Qv'2@-YS4t-C5PG қLnKǛUz9\!sC 4$QUzVz:ז}H^.\x͚5Ŋ3]Oo3wo=dooI<7o|3aaa˖-T o_Id ,zҎrSy{7#Un|m HK9Y׬YSdIBa &SQΝݻ`o~Ϟ= ,-y729pu9Y^\)}:Cg֩Os@ Hx(RЎu2wkVnU*pjwJV%Ř(AI/4A/Y:o}Z W'բY^BRR9tR{O꧓_`ˣ{^9/{ٯ&$)JJN_fmOqˎ;V^ݴiSz衇udɒݻw=zȑ#GΟ?2eJ.]L&MT^8dr ' Vў*SiyAIW$;@y1L<  {n&§M{ۭ-ZqyDMQEdKHfk:g[":H-3 >XX GYb rQo+&A) WpsXnˣyT,dw@Nqa|YƆ݆W&L'qwǎ;vۿ81/'Xt*Sv^ *+~x]ڵB+L2L5tyLM'i+j5TJTɚ*UNlRNkN$X=vDV05fըy4{ 6[|yr刃S\r5kt87 iҤIiiiK@;*=L!E}0mdqeU&ҥ7V5v-dTmѭ:zPhv+$]1J9f2B @VrO`RJ':tM<'NV!!-QRy>ӵsZ`&@Ș ğ$*弮5 pU ]@nH$Oy?aÆ%&2Yƛ  G"TvjGd@KUi ;˭Ԋ82;HiĈ׮]Va-2J/(\ъ~_Ƨ? &m>!LU8z=-H+**_&'&&2So-/ K}IJͿ\̤mfݐA0La4PȰ{Uz\zqe<9G% {wv98qѣG9",&v Ć']v -Q4t-4 m1Y}J*/qj*'g?;+ݻ߸|smdI yDc9瀧[ut-4Psz 5#ջYxS 5|-[k&OpBβ!d Ukc;]ZͼBqh&4TCB Bo'Vnp[]t9v5mݺu/"2RC[]mVȑ©q;5jƍ<@J OߌYYj6MnشCkrh"vWwB rYgSSjuvhLj7iNVM:uqƧNrlذuֱ<}3 XJ>sF]#:oF?P@'YzbxG~oп</ED;qDƍϜ9~6mڐ~XmHX4USӔf {0k~s+̽_*ҮУ$^ǎ_={n6mq6m@\k{pkC xErp>HRjZyh0FjSj喓!(Z@s*r84{՜5xȰ'Nw}~a;ԑ#G>G{[qHkw_X*j5w`aF#\!5`޸_eݦQ}Y]jR#Upi?/tUGdVBBBUٳ7~7r!wvSiSG8e9v>('+~fTUU Nz#=Wٳz[n gJM-3J hs$`{~pCV?plFb-)KgZ~~KߗֱY>Gd<3N%>ji7kޕU qBDX2Cm%Lضm[*U Gxm۶k%^u2p[Kk0݌rK/>.ɚl*A6g S;)#ձrf;(V;wW3/yqs@t,x0*%%eeʔy\.]4hРʕ+/],--QGRO)0)階?pG訌uVZǫ8u_k×rC7]8 +5&EE;/˭`˗8cƌC#88؉sĉƌ111"CtuiPG} 4]٢StcqNhl!\RcUGiZJRw?-u/Y[.j/rܢ#ڿc=6| `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=2zd @둁#GX `=;G6Oփ@+ CǷ5C\+j3Ň$t֍ k `=o]re,vPx*eXIfMM*V^(if,,+?*%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ColorSpace1ItEXtexif:ExifOffset102sB) tEXtexif:PhotometricInterpretation2+tEXtexif:PixelXDimension2091sԵtEXtexif:PixelYDimension16742IENDB`pappl-1.4.9/testsuite/landscape-gray.jpg000066400000000000000000004327621476704353100203160ustar00rootroot00000000000000JFIF,,ExifMM*V^(ifUUUU+8Photoshop 3.08BIM8BIM%ُ B~C  C +"  :SAvqo]Avqo]Avqo]Avqo]Avqo]Avqo]<9j0˴Ë.,L80˴Ë.,L80˴Ë.,L80˴Ë.,L80˴Ë.,L80˴Ë.,L80hwdݐov@qdݐov@qdݐov@qdݐov@qdݐov@qdݐov@qd՚([#μC:9 3#μC:9 3#μC:9 3#μC:9 3#μC:9 3#μC:9 3#)XG'auryXG'auryXG'auryXG'auryXG'auryXG'aury#fWA8?N ^O5RLe ^q$t8&Pq{=Tm`/t)&|agS8J/Φe lO~$mK vB5VUS+  Vc eH1pLjqg0)S@ W֘JyҒ`250-W@,tx^D' Jnw=M/t-TRHquTQj{|m`l9C@MvXĎsgԾ`IxvnONPJyҒ`փIVܕ:9]q8A!|@+-EW4]ۗDUZb{n^[)=ء%]Z%hK6DjWArK+0o*4BA`:q~((<2-PP/t)&Uq_Zsog^D耨7]fH Jnw=M/t-3Hdr;Fڪe{}X9-4" ~8 eH1pL S*d:n0/t)&9nu!a #d,dzjlڂȀ,,-Xճ ]jSu9i{nwTy j\6-椋1sv_>5VUS+ Rk64BA`:q~(k&?ٸҘ+q{AtSZʇWˈ{n^[ `ۂ# |h^qB\(q 8ӎc@0HHm3]>p8Ҟktqk܁v_7PrU{PY ekQ  9i{nU(&{}@DjWA lh惲$t8&PaG Fx?pxw;L JyҒ`(Bw xꛜxm\  ^D2E^1GQr*N9 cZ=M/t- (fX73Z̝ s$&He_l^qB\(q 8ӎc@ŭ`Ʉ^O5RLClqᖦ{~+-EWƧR]mK v AMh f~^qj@ ~*fĎs Ǥ+l*J ¤6Kdq{bid(7#)629G ʺԦ(gVŋAhy}+P I 3WM1}D5 S@弨vً QE?U.t̯Rymԓ` C!)VC?F'rQI`9Vx烡x:9TzW e]jSuk^:rبܪjtg]t@(TN c>(ndvFɭ{5]VD\QIe7QmgYVGk/kp\^۩& KJdp[^j3y,J~@ 3~@ʺԦ("JjZ;Sj޷5t̀P I'C/vi<4o72 ffÔDO ܊n.[ʇo0Z s?yw82sp\^۩&uB&7~:@$zvnJC~O_cfX2|<]:9uM$P)%oZ(#1x~6BX*u&`si1;\~}0/D k`@To7Զ)弨vQiN@dO6~۠ ΐYO-lO^r Sm!%JcFO:ѫkFo1%#`-v9uM$P9t?  G3s S:0*$|qnhށHݨ E/ɼlX EU\"z *0$72F4@ FkV 2IRMS5 ?W_TjںrQI`o4'U֥7X@S+gvV8c:_ׄNTLV(9U؍8db5]!`:/TM_ !ꢀKS+G(^d+k@*:AfW-{0C*WW4&NTL? rAsD5 "n(o*a3cmzP,uP ΐYO-lܵ1`:ILZ餿D ?vrQI`Jt$utZO@ʺԦ(9X>m6xL4?+:-DzD~BX*u&`U*Oj y;D*&[uQ@%yP^ttؾtah`n +Ԟ[u$(r | $2ސךbKG4]qt]WZbEh<vɘS:0ӂ?e4{(Q6 `,۪.[ʇoUE9ؚ@x^L&[H,'I6gE[/'"Γ0@9my$?UTųnʺԦ(2Щu'z;g1P I~yܡY$0~?`TM_ P`k"x ũܑKvBn +Ԟ[u$kFo1%WZbE `ԙQ6 `,*:AfWGK`R+'[,`M@|%, GVҫeHlf s`k6V? $pD[J"uɛ)́Zd@7B^~en*XWy_?W&nc|}σsQS s`k6y} 6^Iy$JZ02 ԛlZ*U@ "=ghl*"N6K͠!/wHb<lHm 7fn]N T x\`o8, GVҫe[I*5*di%ƀRm@R˧K PHlfΰTW f/|95X iͦbՀvXp"y'x$ Gҥ@ RJs![LIQ^=]BP@5mt@B^N^&"ͲsXIyA9"X@̭եWTTk%TKԥwPڀNY:d`ASI> ԟ:m`,e6UOVbxzd:6a.49# Gҥ@ RJf0`RWS%;S4kC B^N^&"rDxկߣHBTad`K`Jd IqPTR+'[,s:U*u)`g߬~# K`Jd IqPTR+'[,s:U*u*آ"ZNl ~&Zji+X``+[{ꯚo,ŴvTkR=}AP@5mt@B^N^&"W X~en*XgՀmڈ,%{}XXPR+'[,-z &6R-z ^ת-z ^d s`k6PT4BZ٨@?tOо$@|/\0}M0=L $pU")iw8MѨW, GVҫeHlf s`k6V? $pD[J"uɛ)́Zd@7B^~en*X&n6Xki# {>GK`R+'[,`M@|%, GVҫeHlf s`k6V? $pD[J"uɛ)́Zd@7B^~en*X&n6Xki# {>GKum2C k$1ƲC k$1ƲC k$1ƲC k$1ƲC k$1ƲC k$1ƲB3=;<@;<@;<@;<@;<@;<@Cص|G}1|G}1|G}1|G}1|G}1|G}1|Ʒ=Ck=Ck=Ck=Ck=Ck=Ck1O7+0C#Oj;q5^SV`G7*nv  k, oT>ݨ@?2@yLXYX!@̨"}Qی4wd2?0B;PDvh_1`ef~`=`w2Gn2qbze@ڎd>$ ŀ!6=ĉ|#=灐>|_a}|_Oj;q=~[BiZ#G?2@Cy@}OH=0džboYR'ȜIQY֋H!Gef~`=`c)X`0|qYI履G7*}]#oQ*jܩ! Eo]Gn2#В(`9w}WaKf8F4wdKE}~ ]AuTc>A>|NG_1`q"{r;+W:S8.m or VpҞkV`?Dr Fp0|Md-qO&_yo8w2(H7 %U-]Tu[3?@st 6SS>ݨ@7f(S'{(h?ә/(+ŇY}~@?2@]*4PPkA^G}o_!g'Xac_1`^pyQ N9ғ}Q]v֎__9;(\H+0CP{P]`0xzPV0| y?| ʀuM:,LQ*j\,X כ"}QیʦS?`9Z۟4NQ0;B3pO46tlg?2@[ʇ2an'wtDPkA_bS6ʲ;$Q;ǨT ŀuef,uO*.o1 xfN_5Ї>!y]%F! seI 9xznn'FGuފ{B]^ZJ#Jvר4v֩Z %U-]T:W(yʻGVGn2Cd0 w}4NQ0,FxB΃JoQ%:#+:N?2@]8, Z ~)u4 /x'(hvPn_1`8^*[Jr]> kMYX>p҅@b +TlPᬜz<oTUVQ*jˠ[p09~S|xOj;qq]`& sci$'>z#H?2@.PkA;wˎX@Ŝ_w?LGA9 l[h TV QUq*M."Zy/I!|M<ѮrD@7zD3ՍmĶZB;PU[TDG4y9w>ݨ@ǽtRS'{(M0x>'5\ś\b9ԭh9qt_ Ԏ"L'ZPl}@jԤ*C-@/)阀Vʟh*v kq enV.Ouef~`=`:7x<`^#j93Lʚ-Mժ{%[@!@̨ jUR@}~V,10>ݨ@ǽtRS'{(׋^P) s9P Q Ϡ  JP{K5aą͗:{`b#zp\O`7wm"&||@u[v!|M<胯Rk9=-\*Bs;ъ  oTUVQ*j:H`ڎd\{E/X9w.-:Σ2|hc04 }C-zqt_  HX__d(L6k,N$ ŀ! ʀ'۵Gx}H/)+0C#Oj;q5^SV`G7*nv  k, oT>ݨ@?2@yLX\H7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V7V>xmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMTmMT}xa`}g`}g`}g`}g`}g`}g`V(eXbUV(eXbUV(eXbUV(eXbUV(eXbUV(eXbUV(z<4 456P 03@12!$%&#"pU㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㢓f::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮:)6j*z㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::#fqqqqqqqqqqqqqqqqqqqqqqqqqqqQAӔQqqqqqqqqqqqqqqqqqqqqqqqqq_rgQFĈ.$Aq" \HD Ĉ.$Aq" \HD Ĉ.$Aq" \HD Ĉ.$Aq" \HD Ĉ.$Aq" \HD Ĉ.$Aq" \HD ĈaOhhE(EƊ.4Qq\hE(EƊ.4Qq\hE(EƊ.4Qq\hE(EƊ.4Qq\hE(EƊ.4Qq\hE(EƊ.4Qq\hEpJrTar \F*0Qʌ.Tar \F*0Qʌ.Tar \F*0Qʌ.Tar \F*0Qʌ.Tar \F*0Qʌ.Tar \F*0Qʌ.Tar ő$m\H2@̐.ds$ \H2@̐.ds$ \H2@̐.ds$ \H2@̐.ds$ \H2@̐.ds$ \H2@̐.ds$ \HXUڭ&L[$] "IBHEВ.t$$] "IBHEВ.t$$] "IBHEВ.t$$] "IBHEВ.t$$] "IBHEВ.t$$] "IBHEВ.t$$] " *gPNIfNfo:mK_VZ'$u}y'n`J7Vm~JrU-xnټtv%YΫ6%[zR9*Ձ<7]_lIۺX;?U_~rku Do$,VfͯV޿TNJ`{:rO W7v3yfo_\%Z=B9';wKgUkU.S}XΡhu䝻*uY*)VgPNIfNfo:mK_VZ'$u}y'n`J7Vm~JrU-xnټtv%YΫ6%[zR9*Ձ<7]_lIۺX;?U_~rku Do$,VfͯV޿TNJ`{:rO W7v3yfo_\%Z=B9';wKgUkU.S}XΡhBs(Yejo}Q5.Yi}uʢ(]s$+b$ą3tv%@X 4j esO+]s dL\HYU_VV OcHLi Hq|.SWX"S;TGjQ?Gvڣ;T~7+_VZ'P 浄QEVUoưQ[jǢ0d'-5[&$"|R~Gn`©5 4.2dU,+3yf)(~ipS+o_\Z?T Or-RS MXvUo'.4##tv[U4FE5#U_W@WV޿TO~ xZ{}XΡh#ޒ(v+:voYɩ'{ " X!6D|ʶ^qwKgK EVVRM!XI%QJ5l'UU *iS;*Z#_fo:;tu( &*{%mKjg~JՁ+(rz| W72Xv|lUm(bzgJ&0v7n`wku A2˾ژ]Rڜ fo:4QC/w:֙[ <0 H&|-k~i%ˎliu Rڻޟ3u֑/'7jɓ()͵Eſtv 0moȂ67&Ouk՜Q"9J)ljdM_VZ'2\ 1dU/xVw>gW e6m_ݻRA[j&4YΫ6pHm3LE|,kϝMS)*jE4,U&ʯwMPfͯV{ƋrkZLEY[-=o| 3E-=ZCɝ16sԦ*Z=B>zVoʤI uv{lJh3U`Uk/؛s&G:e?닣e'9k[.aqt5kYu{⭽~rRlthmNku De[W{xnٿ"4o7aX5w1nRɗwKgKRۛ7Vmvǖw[zR>]j,??Z=B>zVoƠM,qrڿT0 CtvP1ەLYΫ6ZcW;⭽~rR 4b0b!Z=B>zVo|DWYjGB?hG#vmԑYm:$Βb_aHH1)RĦ˃U_v7s%?NǧӇzpv1kЍOV*)V2Z5jAHNr!v>M8m$־gPOvUw>gV3AektvtD)LK*XY`(+LV3|uk5S+o_\Z DuKfF(6xʼoR־gPOvUw>g:G'n`M6I$&3yfksEV޿TO/J%ku De[W{xnٿty;vlŸ\]75U@4¿%fo:MnhJ)?R 6BwyꓛUi(TQD4|-ZI.U?VFu}~% n4ƛ`lMi?64ƛ`l詿tv}!PḺNj}LUK\ /U_q6%nm$ַ[zR>3Dv1TeT+P?8RM%$*L,X`{:rO W7v3yfo_\%Z=B9';wKgUkU.S}XΡhu䝻*uY*)VgPNIfNfo:mK_VZ'$u}y'n`J7Vm~JrU-xnټtv%YΫ6%[zR9*Ձ<7]_lIۺX;?U_~rku Do$,VfͯV޿TNJ`{:rO W7v3yfo_\%Z=B9';wKgUkU.S}XΡhu䝻*uY*)VgPNIfNfo:mK_VZ'$u}y'n`J7Vm~JrU-xnټtv%YΫ6%[zR9*Ձ<7]_lIۺX;?U_~rk4j[* `1cXc:0u`1cXc:0u`1cXc:0u`1cXc:0u`1cXc:0u`1cXc:0u`'Nfqg#Z1kbHŮ]#F-tZ1kbHŮ]#F-tZ1kbHŮ]#F-tZ1kbHŮ]#F-tZ1kbHŮ]#F-tZ1kbHŮ]#F-tZ'NbiwI81[b8nq+sV1[b8nq+sV1[b8nq+sV1[b8nq+sV1[b8nq+sV1[b8nq+sV1[6hk Kb(.Q\F)rR1Kb(.Q\F)rR1Kb(.Q\F)rR1Kb(.Q\F)rR1Kb(.Q\F)rR1Kb(.Q\F)rR1Kb(8yFa5U$13bg!C8&q L13bg!C8&q L13bg!C8&q L13bg!C8&q L13bg!C8&q L13bg!C8&q L13bg8yB0{:mOm l -0[``m l -0[``m l -0[``m l -0[``m l -0[``m l -0[``mrD-,=0{h`Cm =0{h`Cm =0{h`Cm =0{h`Cm =0{h`Cm =0{h`Cm =,n"DMф 7Fn$I0ta&Mф 7Fn$I0ta&Mф 7Fn$I0ta&Mф 7Fn$I0ta&Mф 7Fn$I0ta&Mф 7Fn$I0ta&MфP֊"RN@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Yad@Y<ɧ((I(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C 20(C yiN97?mrNyy'bh|`j/G$σԝ+rn~:KnO}*՘^I:W$ 8uU0>gRtIɸkp-=+CVaz9'|Τ\p3$ך[w{V&VrO=Iҹ'&gIï4$ܬM Y䟙{:rNM\^imIX%X ?3u'J䜛'ۼr4>J5f~gN97?mrNyy'bh|`j/G$σԝ+rn~:KnO}*՘^I:W$ 8uU0>gRtIɸkp-=+CVaz9'|Τ\p3$ך[w{V&VrO=Iҹ'&gIï4$ܬM Y䟙{:rNM\^imIX%X ?3u'J $(EYe7c i#p3>|ұH# D1H# D1H# D1:Q^imߘ)*f%Mc$~a48gxȓ>A>gbh1)*f>?ѿ2^3i( YgTN93:tw'CF =G:W6l֫,jT+ʽm97?m|/hmï4ȺOE nuZ{J8Fb%`E@>I_#r4?uI)8Ui좚a)⨟JR?-`j/GE462|t:ls&J:U2˝/σԝ+YY$MQpcnɸkx+CmNy~7qEqxIȆ` |o}7c톚i 0^W Y3 D>Vp#pF>h#>gRtɄMPѪe4ܓNֻM 3;>G&g㶼QM48uπs'()D5nyR`)m3{V&,)@>t3.dخU!ԕ9'KlX UX&%YhVڰ Z|ɑΙibG ʥf+Rl:WXiPn,$%˗*|M_  q5k!0C\`t5ck^im߉:-Z(, 0CcIV`YU~@hq$AI C`S2OX ^sJѳgw2ŭ+ĩ2ܩmD?Jj:Wĺ :Lɑ͎Ɠn797?m}U+ZIQ>7ۿݹmZءڽ]NsJ'#J]3-mX w,MM4MLTmYZjѮV4'ZFk[>gRtTBEDܛHQң)Jab(ï4ĪNMaȩ&t~˖Zڹ#>7bh_$GcV좚hX mgk7|Τ_ ?Gj; qV*~ʀ3D [VԗRܛs1QBpG64DWۿٲKpLT7GRi QLܬMrRMOkjBVaz>k+Z{hֱ~~k?]3u'JW>FUm{7%چrXܛzW[W=rך[w⦚!f}U'85џN:>UfK*nɱ&T6#!(; Y-kM?Ǖ?;YVo=IҾhtSKPuBabZ ,["?97?m|ED0UbYWt|y~'Dmg Q0<@+H-6NR,*N4I͕dfҚU7JZA$a;|mV6#16`xߙ{:|1CDpϕL#Mk)rZG?rn~r=$op-=. )&IOd'Ks#ܪQM4RoM*lR7I2Ju+`j/Gmek]RzPcw-`Ǎ:W%й-o)°lq.]i%Kt!>'&g{[W=Oך[wpE.؅}D?YKo{V&=(.^}%~:՘^ֻU J6C0H' Z7,-7|Τ_h%` 1C6VY6HҠܛWЉj:tjr&_ך[wtJKs#1!NBǚUk[ri.=+C?/<ʒlٓXBje|mV#GeD6.+JH%QLR4xJ3u'J+''=<ݨo(aZ?U*W7ɓ'L.Orn~_͵l8u>GH[>h]{Tj2ljTQD4|O}7*ÓSuF VȨ>@0X =[YZk6Lh)HTA9f(N6:ZoTσԝ+}"WMOܞ?&L7&gīB2DQS642}y~%+ N5ܹo}7j邟5f{h% xZ|^G|Τ_#%Z#Mn3bML&Srn~+_Pzï4Ƽ$%ezrYYƁdZ~GbhCSU I*5f{hd )OL89 4+>gRtaI*5`Bm&**.tGIJP%1Ik0p\Q!'}.y~H8TYHg1@RrL W@\F0Q"DWbh}`L#8 "Sn0Z)Z(dQ =`j/G| Z9m)J,3P=vCI~%0cL ?3u'J䜛'ۼr4>J5f~gN97?mrNyy'bh|`j/G$σԝ+rn~:KnO}*՘^I:W$ 8uU0>gRtIɸkp-=+CVaz9'|Τ\p3$ך[w{V&VrO=Iҹ'&gIï4$ܬM Y䟙{:rNM\^imIX%X ?3u'J䜛'ۼr4>J5f~gN97?mrNyy'bh|`j/G$σԝ+rn~:KnO}*՘^I:W$ 8uU0>gRtIɸkp-=+CVaz9'|Τ\p3$ך[w{V&VrO=Iҹ'&gIï4$ܬM Y䟙nb5v\1#bGĎ8$p H1#bGĎ8$p H1#bGĎ8$p H1#bGĎ8$p H1#bGĎ8$p H1#bGĎ8$p H1#M2t+KbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbW!^xbWɓ'L^]/ p_\/ p_\/ p_\/ p_\/ p_\/ p_\/z}Ȕ.Dr% (\BJ"PȔ.Dr% (\BJ"PȔ.Dr% (\BJ"PȔ.Dr% (\BJ"PȔ.Dr% (\BJ"PȔ.Dr% (\BJ"PȔ.D"Qe$DfI\M:hEΚ.ts4\M:hEΚ.ts4\M:hEΚ.ts4\M:hEΚ.ts4\M:hEΚ.ts4\M:hEΚ.ts4\M 4P.u'<]IORxԞ.u'<]IORxԞ.u'<]IORxԞ.u'<]IORxԞ.u'<]IORxԞ.u'<]IORxԞ.u'KN2<ƪJ&8uf9s_$IcU@%]MJ:wO䜹﯒p $hrNYN\w8stGXP4~IWSDҹ''.u9{:C#,j?$i\Vn:N=!5T U4Ië7tI˝n'`ΐK*hW$՛$η}|0gHdy%UGu4M+p?r[IØ2<ƪJ&8uf9s_$IcU@%]MJ:wO䜹﯒p $hrNYN\w8stGXP4~IWSDҹ''.u9{:C#,j?$i\Vn:N=!5T U4Ië7tI˝n'`ΐK*hW$՛$η}|0gHd~?p ˜bSM?84SE>eUGu#'"8<2̛ AzK9v9 GrhWDQӘ9xKBOo-A:wOh:*:c0#2_⣦0:cη} 2gGGLdtDRgAGwL`tGLdtGLdtGLdtGLdtDP >G`ΐɚbjfQn(LȭPڹ5T  1GB=rZ)H,\I;" h&iyU]MJȧ \6V[q)(Rw$P 2a<@t+VniKxHq(˗,[Ѽ\w53Ab ɲ6m~ixn_#0gHd|Ɇ'$Iּ ('&Lع5T H M?3ݔQM43aK!fD3KM*hWy7Z2;k-"IELBĤU+UL0w՛i6k'-&iiH֭W.uAsck /X{{ܾG`ΐQ[i(P=k 4&Qy}cU@FfJv3JQ"yRάEA$'ݐ6Y!?=M%:wO"Z0"'r&[Ѽ\wNM8e&mbmxn_#0gHd|mZfa;lE2$62< cU@ Ię2~gZ]qڲjϞIeR7\jj'yu4M+kY"-ڈ5Vw%Et4h@16wVJ#VnFLDHM/Y9o Y %a{o+:"Mσ\F+J?+DCG`ΐAirCSZEk\1T6)K.rbucU@mh:t63ݲ̑1%HzҏiS3TG gxu4M+lQ 0 D4'8V[T*b2hE2Gle)p P cZ/8ل4(8yЙ/bލr[=)zdJɷ4㶱6k mgL9{:C#jV)*KeZs6MkخU&Y*Ft~-\kݓaS.L`Y4CDq~u4M+]rTs$uU}GNy Ɍ(QcFp?_vLF%&dwWsGVxM՚ #JŽη}~45(gϖS(<G(aQs[X{ #as. fN nqK e<"t&\h8?!et4%Cj +k=@#J4"y>j$rKV vx fY#VnF[EVY9n+G袊(HM&~zp[Ѽ\wh9bB6yPq7#bv&(?*Ur؎i=q&1i$)stG.d3"(ⱥֻϜ^+P{W52ƪ(i:i063F5)|~<&by͵nh^E^HX)(Iw.+VnYLʶjw)MЊ]Xَy`7]"&39DP./!,AS4!H0s0s0sC9#6:3b93xh(q xF#9RIs0WTpgFpL:W#f{U!1 )&6@K1V/bGVJ!=TUR=&QPaWő;k'D#mVO"z'ꗐ`L,ʺ*\.Z b} og]픆O%s*=há>aͫ$gdzڼPVld k*K!)):")H^C-=\ăråS=k˂mr*j] E1SgKk|f%IJ;k}BqJOC b۵"ijH3R-?yCM\Qm[X{I.+_,Sg!WnK*5JRKs6K+䫧wCԜېlU5ƫm#ĸ 0 馚i*u^pJ9]jNch[>ڲp–jsߥh'6$[ZNHL*uOp8d7AS-\eMO?lGmrH^3~ϑVSU*T򶲌t̞ʒ1[]d)GDŧGs#쪲Hu"7Sd*XkPNfe|2`*]Nz/)\Gc(ݶ}' {!!QE^C)GeMmr*h4NcOeU7&\0S93vO:)lH謅59__SYk%VvZ|e2njZA]㲸)3~ω>TDE"L8,?.kO)=?,)GWb{t4&1LR+=8UV$ڲ-]2l&fe~ mWUm5W`_ ݵl3P}6j;YQ?s0WTrvK+ݓILrC\s ~3~υQAmiOmM뭮U;>S6ŵVfzV&)H8%e6>9%*I5_ BKOdِIҷ`_ ݵe4f*\{W(Q9Q{kU2Dʱu1[iR5r^ɈytNr8LQEHh soMM:u$#m`<gNbok\\vʏ)3mx|y-=UC֊tT”Vϝfe~ mWVȷկU3+*7mo*~_}q;ӦHr[[QJ`੬˒''Uxf [\/bJɦ[$ZEB߳ȞqTMJĬՊ6elmr,+ [&̂L(<=^mksW/{VɋUrh@jƭ *=4>3Y_4kcUa ֮KFI6d\Tk'Wʐ>@EګS-ˈR zёH Rqxf [\.ֺ5u>(GU5`'T(OLOIk)q̏o*Zq,f9F;Ll(^أ{/bQ՛"Q;*Ň*\u2q:Wci)mk8.vߘvGͱma~ل"'SMrߧ3dTi6ƫWȷJ L [>)Y.yn4-QG`੬˒pdO8|6({ey9f<dz=^mks6]wO1 {%Z<3dTi6ƫFur( H \Tk'ږueXIt((U79+*k9mrjxSMԔy[QTP3s6K+2^)?[xUos!ЈړU?VwV5`_aS7cGzE`h#[iS(.icf`ږ ?E=[irY~|3}؜՟}?EXꤑ\_MSf!Kiɠi4У\sieؾxNJNYښSXjkMa?5ښSXjku؞W&n/B[J{4gQ7YLt,Wd!\q|=,$g0W/FG$s6K+G3}|g*{;#͒Fsr__$oʞrG3d\$s0Wr=,$g0W/FG$s6K+G3}|g*{;#͒Fsr__$oʞrG3d\$s0Wr=,$g0W/FG$s6K+G3}|g*{;#͒Fsr__$oʞrG3d\$s0Wr=,$g0W/FG$s6K+G3}|g*{;#͒Fsr__$oʞ@://///////////////////////&LْfI{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M{M2?YxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxLxL6e3c>)pq1:W\cuq1:W\cuq1:W\cuq1:W\cuq1:W\cuq1:W\cuq12e3)\ (?V?VU  4 1Prs!0235@AQaqt"#BR$bCScD%dT?stUjk)XÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;ObpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝjyg'18sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxң;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wNOĄ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wN918sbpxÝ;'wND3M&RȯEe \ Rhͤ%7@|R(E{Ho|>) "P7@|R(E{Ho|>) "P7@|R(E{Ho|>) "P7@|R(E{Ho|>) "P7@|R(E{Ho|>) "P7@|R(E{Ho|>) "P7@4BWˋRU)baMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMILSDZE\b:.-H9Tf~q& b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@1M`)4 & b@f&JJB.Q1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZh1iLXŦ1cŌZhȅi,A}ura֭W|d-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8&L@3Md-4 8! Z#g"O|Ee?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?WNuTӪi2t54NzQo!8<zEe?\$#:vBMu2q˘ ˘jl S#mE[{R(fgK[M=U8gBm8ҍ M-c jG>[S'_qs!Xףc+P|k«|bP7> ߵ^ VSpx"0*Wk42 Q.S >XԬ!m/y"jY$aQMyIrqĚT\!K%AZ֞1S/81.j|ʄW=ԫ:)-a%wU$wC_Hk9s3OpҥW%VŞTo|fJ§"[(QM$[r ĢؔP7bQ@lJ( yv֍rRZIgǩVQSYP|K$Ci|BZziֳTmpo62VK Qn$ivvy2.9~P Y:O#G^ ss洏ig9]QF|fzC&הIIr[ZQ^ig)UoX^YF#O/: ?qDaTipGePE{/\\Go_F^ɝ?Gz%q[۬ԪXC>V:*^ 󏅦rSHxEm5Qk^7^2J֞1S/8IG![pΔtYZCg*eJ;T\""-Tk9'e5l)"" M#GS)L<5{]'#SSGƽ/j%#ఽX*yU%jKu TH18Q#%p*{eҳ=@6R$m u@qdE۴Gz7m"{"rEY-8喷^EOȭBmr?ki=z8/^ 8S zy+tK-$HOY#ఽX*yU}O=K VYIO~&zA|FYEOf2+ Z#)^.C)+lNR M#G\^9沞UPAqjRٙ"p)"faeʺ R}aUGazgUqmF}*YIRxUFJǩVQSY* ¥a4=Xogx3>R.y6[3.s2fBi>3M['$K/i2EγEL[ =c+FWa=dZͫ? >zp5>CmJ;DDP4$O*aW`v[}zQo!9*"9SC6M0G |dЗ~LRZDM%T AyPlĶ+iQH~6.TGOJs-%Y8$=H".UpeV+y[{Ӱ#ఽX*yZJ֍̺,N|ˠDȓ;h?dXBGJ]/ǩVQSY* ¥a4=Xogx3> PL4R++PmkWMQ$mTAeĞnSĈhdm6UJu=WOg|-8o3Kn=IXB&Cq*.2%JwC_Hi5+ѷJW:꫖홞 aUz|Bi ؿ&݋i ؿeK,qD~ MlR_R^C.Q4_*&6|Tj \gzgU YE̯T$;ea =H".UpeV+y[{ozgU 9<^vOUt[uDI) ~Ԉ+(]WYaR|uTr:9iJU(jejM}`_$L||_7! bض-bط*Z{UԼ|T>T[cE[?Js*P0hlԗki=z8TXN«|bP7> K1[*UGr!x"0*Wk4EUqXT!m/y[zp>VŞTo| *jIn49Zg$Ze50z)`=OaO@ʾdLЯH$"x"0*Wk4DEIRAHDrJF'Qg}=V[*IjAԚ =Xogx3>T'"\S$J3bso19wNc;'1g}3bso19w1RMJjRk{䓁~yxy?QI!KUC.e/+@qMqh0#!^i b꧹ i5TO?ֹ 2%SOI<;|Mǭ%ח2#I8+']~8s5T$\zQo!O%G"J/jm)Z(KmFYa]5Š=$\9tWBXCzLS)Ekv&@L´[/UZ^FYEOfӫm/ytZ{4|iD&MH'Ƒ4O"hD>4|iD&MH'Ƒ4O"hD>4|iD&MH'Ƒ4O"hD>4|iD&MH'Ƒ4O"hD>4|iD&MH'Ƒ4O"hD>4|iD&2dTNNH"< ytXw8 ;TzÙ ӊo0V"DaA[+Tù o):WWCy>j]60%|7NR#i]:1xyNpNFYDҺuK;bӪ=azyNt7CEcYwtzu"0 -Ӫ]a7Qg+wN+5Z.PNөVQo4Rj]60%|7NR#i]:1xyNpNFYDҺuK;bӪ=azyNt7CEcYwtzu"0 -Ӫ]a7Qg+wN+5Z.PNөVQo4O#hˈR[lIzi"+OOuy:PZ a`eyviQ']a7Y6mG!11#|X$očc,c7ŌbFH11#|X$očcY8I9HQg+|TVYOĉ7\E26'9 hlFCøP|i9Kt7CG2~-y(| nOŸ$SjQ8:|z! g(E'O6b"P3xxy(X8r>Uh.5$'ML̆pd!ByFo.ID%ރ=:EexK)הHBu" bOEEDy-6P=+W]a7ugyQg+|+O>hl5?e`S*' (zRRY@K,mzeh,WCy>jpSa'+I0xd䜆@gg{<"l'1,TITiNAG)Vp6G]+kSHn'QEhXaꯤot҉hVl=:EexKlj+IIm|%|9m-tҼpZ1xyOG^qlOpvJWUm֧EaZ zUNj0co'`\N2~\+5Z8=NI OX !۫As#6=O%+E.E9붾R^z:ߎ^"e8v$v+=4DE,q\ggdOI6U;VQihM-b]QA!UbdL.=:EexK[i>ir\|z0뺯"MIZ.Tù o)~ mEpz/+. TzÙ ?dQXUzXGy3lao0Veu6Z8fEZ`H*_*t= װx[Z})!zu"0 -h=t'X1 e#*/ETù o)նAyʣ\|'۠HZ\3> UenJ/tʉhYJF\eK\rCvOU6EUd~|+5Z8Jqg㪆 1 ];Nl1BU\ g(E'NȸH >PG\AدtR4ej~#HR 8H%i~nK/CDaA[.}XrKe)O`8F} 6{ `RqRF_ pЬ+$ǰ1򗞝 &U.q|)zaer^|I֢4N TzÙ 8Sx|eaXM v=(ZR.i>j_9_iR jR R.S @):yO"!Uģqe۞ʈ1f]+%Ȼ g(E'N#]stT6G V+)\=*6-V1jLbNŇ}d#gA+dԈ+(\2'-^=_(ejȝ!u&9Z8m&)ؔLe|}%<3ĮtZ1xyOєyطWQOUv(PIt=azyO9ҐOsJ9Ģ`(X&}f$Osn] [WT%bSM>{[E+.!:| g(E'Nӫab{JAx-T~v{MөVQo4 3찋.My*d96!UXG*L5TLeel%R>$i,<^{kۣi&~i+!/sN{-ZZ(Jv+IVq60%|<'MUNU^FuWɲCDaA[.F;"}Ĕ#'hܶ} zJ>fȴ]NK^ʰu¡c6Eʒ"ʹ7褸%R<x[i&1ݶ."Zl<m8Tvx5Qg+|ONFYDUGv(I^(;D^O%m?#RȭqAZ&Ius@S ԦϊUi;Ƹ^3Xs8A^Sf@aN gz,?Ѹ1]'ٓ4m/? rQF*T/$WCy>jpEj=wPVMa!S*lLTڛi~ќB{ ,?1:l>ZV~vr.*'[$>NFYDQp;Ow@HAHX§j"Z=:1xyOr}C9xVBGW=Qg+| 0 EGxVl$B6MyPZ'P|]0||h?ŝoBGo0V -zϜd~w#4C0oRf QBϮ $e] /ඒV!J{O1,?1:l>ZbG`{Dl[Gd;Z?-R#ip#Jq[mFXլMڏܢ4!us@S oz{ee+MzG/S=nTzÙ yʖ -S=TJ95ר^qөBC# dn+۽:5e-c! i3q] %$fpJ S>bVgCy5Br]t6-V1,sB.kH{dEK]R#ip8ȼ a [eEߖ9DR.FfD^HMus@S+,6 vzH×+TWy=X ^]ⲩ'ga/"ρt7CG )W{t).5e"Uz/cYw~bt|YDB-g'G):AZu$'DޓJRh!zu"0 - /*t*4'z+ڤr2]G\1%"='aߪҼU.q|ՠyFI?qXCZȞ3eBEE*Xs8A^Sq>7 ]}:uH9Kqz22`뙆*ğ@{_t7CG 8zdG&UzrPLpCR!$ApF0%|<'MUqɴd;k1 啩yUOUk6UZU+\U $L5 M$ٲCDaA[.O<:*Q<:?G oA \{u u֭s33v<xVO']a71¶rGm}W5I%>_'dKVWH"mpOUѺϑ?@XDkQt1K?8Vikp8|h hqlK.c\;M#¸}&EH efKOaX6$+^y)`K9B.:xN'IzDȾ*De\c!RQ$\g$<*P|Uu8n./G jazu"0 -3-_E$$=5 e5DqpJ1xyOVRS=V)\uD9 ڲ.SW/kWmOQZ088HAJgh~*(6k4H|h))UUqkU g(E'OafuV W/aD,9W-fkն|{,>NFYD૪2Fb]IF\.%^Y<VK D +Oi)Z1xyO4~]W꠬ R&T =azyOVjpDS&ɚ=OhLC.3ڧv0%|<'MUW%ZFSc6ԊJ7]|Ec[>6өVQo47 }]+dJJ<ЛO2D5b?pPoF6~56z6=R<\zW8J?#?7g +Hfj\WW)e)RZ3ַ8īi)F[_BI~b)%=+-Q-_U_jWSTjIH\+5Z8!FB- fG/0e*YiOƚGm7Ҫı'IW+wIIHEr]ty_%`a>k}?|L簚oɺ~58YVk2KYii>4=*he?]jA3m[<>NFYDҺuK;bӪ=azyNt7CEcYwtzu"0 -Ӫ]a7Qg+wN+5Z.PNөVQo4Rj]60%|7NR#i]:1xyNpNFYDҺuK;bӪ=azyNt7CEcYwtzu"0 -Ӫ]a7Qg+wN+5Z.PNөVQo4Rj]60%|7NR#i]:1xyNp"j5OMS&T|D>"j5OMS&T|D>"j5OMS&T|D>"j5OMS&T|D>"j5OMS&T|D>"j5ODV(<)j-sd|D>"l6O'M&d|D>"l6O'M&d|D>"l6O'M&d|D>"l6O'M&d|D>"l6O'M&d|D>"l6O'M&d|DCMC".iC.)j-srrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrkPUhxF^#p/ n7xF^#p/ n7xF^#p/ n7xF^#p/ n7xF^#p/ n7xF^#p/ n7xBk/MWHd7 ĆCq!Hn$7 ĆCq!Hn$7 ĆCq!Hn$7 ĆCq!Hn$7 ĆCq!Hn$7 ĆCq!Hn$7%֑R#N3 MӋ¯(tsH|gt0I]6tDaCӒaWC^qxUnix=&+H"|r]8*k7N/ M{!o%t۽өVQNK^Q {WCio|9>3m{wu"0!it0!t8*~7M4wMtnNFYD> 9.fyD5^QѦ鷃amԈ+(%ӌ¯(t!476zL=WM:Ee4qU׺n^yD?FÚC;IJ{R#N3 MӋ¯(tsH|gt0I]6tDaCӒaWC^qxUnix=&+H"|r]8*k7N/ M{!o%t۽өVQNK^Q {WCio|9>3m{wu"0!it0!t8*~7M4wMtnNFYD> 9.fyD5^QѦ鷃amԈ+(%ӌ¯(t!476zL=WM:Ee4[H9nj!U׺xڻyikI  `񦑬O!,|삱ĚT\G"!4)Rt ]sW`i/ ˔rvoJZFkCDvAZ>~ÚC>\e7%vܕcIYRڌ JmNtR J)%V{ nJ1+ nJ1+ nJ1ZVtDaCӓ%kZȎ"Gr96"EzyUXN!U׺x!\DUJv_XC`Y7Y"0%}ND>N)rIUi-Z_IiGEWCi)EwB )"-X;d0M.7H/!\rJײql)~E~µ~d?ٶ3i ck[xm%)"+E~'~s iB B""Տ;{3x=&.ڣ+0Ƚg(.phTmXZ5l RlQŚ[+wu"0!iɳd"F,흋ɰߘmv# qM^x*k;9CB"g<,I_%6MfUBM~!$6b!E>`MjrlxUvt qvbv+T{;dn9BjOX% 4xb8hȮ4)[M{+it qvc#z/Tts_!lha׸Eapʫ7aɶjRلմݶmoOM;^ۉ.㯋4VtDaCӓf'\PEb +pEƿ)$!6aWC^ٽvcB&NUqƶ1{UZ-rz6X*~;7Nm{TJm;gAYA+%-"F k5Z}5Q2~5%!N_|9>3ټulڧVU+n: y c;OfK}~ٛ0IlɄo8}\ hö'2lj4T߂8-:Ee4SU D7}@$"r9,**L]S*8./{b D'XI(sOfo%.")!9?=TL<2 ѬI+Ea P|"UW8ԙȟ}F(u{ p+}]QөVQNMdZ3>M_-ԕ(ڠ>wUNK"jϔ5}'PVT\D\/{j48aJpFtDaCӓeR0kTiK~'H8׬ V^%-"F+\ֈon\PR9|HO=4|:N y )> Q DSƪ5+7a?%z,>j4E:E_b\,[dKF<i|[+wu"0!i[V[/Sc^x*k<# cTII $ JuUN 31*5Ai٢!4iVM.Y QO)Ķ^ćπ^)A_!Y~"!?WWir6$mÑzj7|VsOfo%~JX|i]M(ᬜuȋ_'YQ- eG)en%]-/=42өVQNN9z& "aWC^1M=;{ͅA럵A, "-SZB+fI΍/ OF;diQ&x xwGML,Re^UN2D#]d^Sπ^)A_!X Rp0T[>S=_ezsRwaw4fzL=\EF:IA΋63&!Fyu%!ha0Q(x/bE"]?*_˲7{R#er968LXEg¯(b0,!zv( y%XkgZ뙘88#+gn^QѧޣMlb1f)ۗ\@'rE)̶R6== #i u2J3ZߥWf/Xmv;FݎЅِcPih)mJmv;CmQ*NMt+aQeNb-Լ/MW}dQӲ7{R#er968LXEg¯(b0,!zv +Xa5XT$!fTBjx ^yD?Fz6wɳCלܨ=o 'ԕJvGe;++KfIKӳE#+ Z捑:Ee4-+-ɱ`/{ݑ4|:N y Ż٣ùDZa?%z,>j4.)E^nxr2gFH"|rp0ea=3 Oh鲔dmaX5UQ1Km#؇FOWCi1a|/2|EqJRˮ Ym>rMYhm;! $/7ҭ|l|9>31רvWV(#"9 Uz]P'Uz]P'Uz]P'UQ)Q`:6F!uT wU@}C8)6zL=\EF.Pn )ǒiM,R2V$!fZDIIs[%U5FtDaCӓ|^& +!U׺x FE6MZZ>=~" MchV("לe]"k5HkM~&Z_tgɩkd¯(coQY,bpZu ߆I(d?+ȕ@O-gHH.=:!O~14+j4اSDQȢA-*jr8ȹ|HǣdkAKK.+h xVɦi)+be/t[[өVQNN9z& "aWC^1M=61/a6H*~<6l 'd:[N?ge{!FS^B+7a?%z,>j4اc\DBɶ)Tg<%L3:ͧIH"|rp0ea=3 Oh鱎v ѲEWCi1a|/j$֗_b7&\j RSBٞsH|gcQ אF?i{^6)J%Va9+OI#[3wu"0!iQ5)5r{?nOv' ਸ਼҃"/:޶+jm$G!FbpܞO݉.(̥aWC^.k]wEd7'r7'''/1O⒵yj+YyLFu?nOSu?nOSu?nOSu?nOSu?nOSu?nOS-BějȴxUx BҵDUGkn/Su?n/S:!|y[3j ւ\IG:GOJ{hq'c<{VA|̙2r:yNl|9>31 BNHIb;q #!ۃC6FuEodJψOGu?n1 /mh)R%QIl{bҵ"I$32Oun=~DQay+JIBʺ!Mm'=a[TaRlO܇D6=}*rƦTay;UB+KƀhJ`+Cu[RS۽өVQNK^Q {WCio|9>3m{wu"0!it0!t8*~7M4wMtnNFYD> 9.fyD5^QѦ鷃amԈ+(%ӌ¯(t!476zL=WM:Ee4qU׺n^yD?FÚC;IJ{R#N3 MӋ¯(tsH|gt0I]6tDaCӒaWC^qxUnix=&+H"|r]8*k7N/ M{!o%t۽өVQNK^Q {WCio|9>3m{wu"0!it0!t8*~7M4wMtnNFYD> 9.fyD5^QѦ鷃amԈ+(%ӌ¯(t!476zL=WM:Ee4qU׺n^yD?FÚC;IJ{R#N3 MӋ¯(tsH|gt0I]6tDaCӒaWC^qxUnix=&+G\kQJJBS4 КMq&8@} N>'Bh4 КMq&8@} N>'Bh4 КMq&8@} N>'Bh4 КMq&8@} N>'Bh4 КMq&8@} N>'Bh4 КMq&8@} N>'Bh4 Кt[j> a"VwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@74 MwS@*rI˲!6Қ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚ})nJhҚouPL.6~nIP7_T *uJ%@~nIP7_T *uJ%@~nIP7_T *uJ%@~nIP7_T *uJ%@~nIP7_T *uJ%@~nIP7_T *uJ%@~nIP ȅW(N@d«kCu!|n7_ Cu!|n7_ Cu!|n7_ Cu!|n7_ Cu!|n7_ Cu!|n7_ Cu J}UZEe Qkq[zݣhG=nv[zݣhG=nv[zݣhG=nv[zݣhG=nv[zݣhG=nv[zݣhG=nv[zݡi*2 qRcq>8Gh}q>8Gh}q>8Gh}q>8Gh}q>8Gh}q>8Gh}q$̂Ve18cq18cq18cq18cq18cq18cq186Jcq18cq18cq18cq18cq18cq18cqu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#Һo_n|aM^eu0+t]Z#[7Ln+YOd Hڌ_YLLo x+=rMYeZ7Ln+ĚzJKdژژژژژژژژژژژژ)6Go#W!(n+W1PhkRRas\Ta[Lko k~͔y7hQqH|^UiJ#"1/cp_tǥmHI ԣ-pFL~CY ZΩU ӗG/ȇ{OXK][Kv[;!G"(S g l8J=#ٕ#Ah_0KM$EDZ3BD$Jy5LG!Ghu6r Ϥ흁e))|v|Gt -qlѳ&0i()L&#KX_f߽tv:K/^J)ؚI)'lSDދ] ʠs+l+ɰ"բ4CZL<3dh[Rl_ogLOhq]\|D $~8]$&,cSpɲa7dv6tBAo<ȔEPDG["9OƦGy$+[/)1r¨^9SB#UpM8r%)TjȭS챩G2U>QB-'+/)zW!l mԒТ.TT~Nۍًeo(?=ByL~3Y.g sDJrϋl?s.+jSD\[*ܑmsͧO+(nbzV ̚B`[&O9=xK2uM(?X>k*VH.syѬM#4Rl_ofP?=\c==gvPXƦe)΄0=ŷY\+!D,#*沩E+'3idSϬBmG!YeЬ83~I((GRj`'zB?떟vʯp߅ VBYzGUeS0d+"HqJRqv챕G%q$,2;FF f2Oe.c7Ҳ7GZjOJ!R= ".I8*SJڽ j9k\iF!Ԉ}eD*C?e6~ T43BK¹gZEc=l"k`ꄫINkҔ ^YYSl岗FX5TؓHK̨ʹ*-r2=O/U = ]jH6 o_/]T ZC6K-!3\)yY="9‰mD4j"җWG u:YWJL7V~&D!\D{T&ͷJIe<>vh;bL^Yq{R0-iYeK=cWG1sɠ46DSo^Y~5[Z}NT$=bg9.F*R4ě\er7bVMJ!T|k!a7.UҙXA`~핖)XcҹЛE;oM} U5%FId٧۠m%)"+DZjSfaSR䖷6M/!YT ևhժfI; $ug+="jTpa*2K ;fnMJRRjuNUMׂaJY)%ͯaS0d+Z].v ԦZ:-C(fJI2JӧEĴۦ:#hrT^/ fGv9G8S'S?æSo?[RS8WSuMŔ YӫSa QN*JO70W$?ܛ ^B)e\4ɪ)R˘ð.9ei^8U> 5r=!s;Xt:d֚Um㲫=%z\qP'tIQZ2=EFLJ*UNSzyb!T# Ʃƥ:lcf>&gcTjbX/$b'~ڦԏ?K:¦S"U[!N]Ml# zPTEŐ@#\nYN.BGzRxOeW{RuMxk?5hm|+à)ڦԪs*f̅cT[u_¸gXęm {谩:k);I%y8&!,U]mVҢCI[V<[3Ih9 *&):G)iYXdr<^/F 4KCG xEPYvgo#fKo)%$5$Q?є*ny &9*?}ܶ$iX9RBq)eidrf|{*߳%ǔIYVVhv3B~r#Vum:]:l\Iv>J;dmw_$IЭ8!UFD~J4R+o%=s=HE-2`EE'8YEEe ޗbbRZ$mo]n+_AHXE{+1o ?vS>: `[e$1jU ^\A8j=5JaSpVdjF\AW>[,Kxҥ$}TgOTv3BJεIS'k"z1쾚[*2 _5Ed0,.!|I EQy-~"yb1[!tp4T3RzkZh|a85K*Q%Vhhb]rð>G٢0.^7ŃV'Ylbb9ȫK__y}ei^>]%l"*sL|>ж*նf.C- 7VXc~V_qmނڗnpxSE+9X/% o*s)(&zO9kYGyo(qi[GSUͳ+=7*f̅bZ:ՠ =Rlʹi/Us6֒H.B),{>Wu?d.L׺bKG@a3`mPi@ܯWz.B-TFvr0fJ!Yy:_k˲=|aJ lMAÕs( T6$~U֡j3"5IW\-dfpxSE+*D KkB6M4HX YDד )El\sD.[I['5~sUTv3B b5"YtEBNJ'\wV.RS?Qs,{9l*\/R-!tpmNoʾ!N{G_TꛥM_5ᚔ33m>.(amdtZ/vh"K~u׍䱇/eN`PR"/3cmIp-ca Eإl_oaҰm!oOhv8~YmGW; ^Bjq\ T~ҎTHB S3DAu:,؄-cpgӨ%$2#$8zɈzŗx:'taFw; s!Y!~g*]DmV2RNіTۇG{م)լYgz\]63^rx`l͙B=!tpuNh}㐈0Lƺ^_ҟ`u:;T.h\q1+7]t딥k;K6VYM'|5JaSpV)ye*aSek? ,^QU6?r=uBeQېa UR~%_7dW{ So)T# a%/i$MU+_Q+.CuRezia:ʗQ_7d.S7xI$)x3jN[Ԋrm,ۛ-n8ʥ+\ʦEKq kXUfK^F_ƪ/%I#nI#,_`y,c*y|&ZT"-61[u- .Q_oaҰ+0>w=eAމq|a^7*ny ƪ;쥢>d]M651m[Ci)R#i"BTv3BYiyV.],&I}[3cu>I5 SKfj9OG^ߵ?-9]u2VNFrfvrI촅̵u\w]}" !SgғR*99Y%2OZ 7??٢0.^75G" UV=S-8Z쫈Ð1q.Rn㮜" Tw/8Tzv$JUvG7c0iXA`~텈uW rU0po#+M/!X(~5wLn6CBҜ-E}QPu>]uwJM;"jyN¦a["`k }\|D Lt$eEHTmoѲѼ"RBUHPx+jy9PÎM J9Ob]LYJ^2'IAh"b‘G0Pe\bSΝjF>B!UuK.b3/qlEe ޗbd9b m|ꝇGZA-Q? Gig!eQHUoV~yk|;BG7c0iXA`~큣pbүݵ/yD% >ir]o:uYL jyN¦aÑYWk]) )چg : AתlA|vrUTgS\ZB`*z+PZgQ;*/ڨlw; s!Y5RM!Ig_%tְ-JyG82 xTR òWQ uN)=T4?ZvYylNXK )J9Lόe.8d:҄*r\UһS͖W6IRX\og뿼ogMHB+ȯYSʭ.v^r-uJIU#@H?Ὧ'B_A.%,ATsw`$ER٭0.^7Ӊ_i”a5("Wᵓƪ6W7c0iXA`~R?U{fzWzOj] 5JaSpV2OWaȒr~#FJY~ kYgg+=7*f̅e za*VmB 1Y)+HO]%G-+R#W$ɯFҺJ.Ee",l0.^7ͻzK`'JɶѮjQDSjI!--v=|aJ YJ{hHV]:IGB"?}fBp'o#+M/!Y">Ga!C?ҏ{ `#KZB Q/ לg=7*f̅e zaٚrCT#⹏'\~Шg.^K6_dJ&(j;KETK 7mJf6vl Da7z\q QʂIGOun=~PJڒr1QiI9 %bKG2yP|N JCZYQT="xN"j 4TCQNtEYIt D4so-N\^Le$q+&]~7x8iB"9e!qKE*"At+&]~71[/(nZ|| 1nGɑyL+&]~7#Fu”g %oG%/S=}VAPu~%(G2ҤmT< u'Jq_2d eS}\›\GW{Nv6|ږܦBmGmGmG ͜:j򤒷"U6K#9 2Wң8kUh\r)ZDd"OI?mK[TbԦ5oKdp6BA57 wMc;&X gq3koA57 wMc;&2Xo$j\!J05?4 ˵TUxbp ׫zAUeT)P`MJ5?UTTBzka7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYCwt޾0v.tˢDa7zWM 7o"=L.FYA": 74#sH74#sH74#sH74#sH74#sH74#sH74#sH74#sH74#sH74#sH74#sH74#sH748~ Ik ,cXmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHόV D-B D-B D-B D-B D-B D-B D-B D-B D-B D-B D-B D-B D-TJJB(- !Qa 1A0@Pq`p?!'!! ?KgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgU[UY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=Q #3UVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVz VzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY$p`0UVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgUVzUY=UgU,1'5Y@KbO3|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|8DKTACO3dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dp\g*TRJ*TRJ*TRJ*TRJ*TRJ*TRJ*S,Bz>e۶ցi&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓl`BoXIۆ32dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L0HM`lZ'+< h69$p_ ':J@Rgl.@9]@lyvd~$CċAYrpXhCǷpCv6:5.ch4`<yF 6#{؅"Vf2"PQzmj`"uA"0hAH,\# ;;Vcڔډ4{1#X˞<ׁ$jP8_M A0Kfo3s%&HHO"tlPMtpī̸5.x@w< twOdw8 ::x,e9SF4f&ܻ&-.}SX={ GR;4yr3-7|3'L\I#%3bE.p鯩w 4[Ico&:{.創^S;D}5.! Ee³ԤϠ"M0>N, 80dɉVEs4τM}K3@bw#Inr w#u)3D7K{<wpĝ/ho.qd AH) O2X: 'OBz?s[v@M[=,T&@ 0t/______Pv]|i oGF/֭ v=w' ` &CB^A=n~e3; Iz* 0ܽii+1JL{`N=$h Z}Z _`~J'@,G¦v,v $$0 z s G_ ō X!  +1?@ 6$b9ZLbhcKN 0` ?xA(,K',v(@D @7a1Pi5VSP㼁qVx4z8P$هUGq-!&hPZd@qHѷUi>w (YK.h]3Qϲ )Vb殀˚$WasŠU4s5+10f.j ,EvG> (YK.h]3Qϲ )Vb殀˚$WasŠU4s5+10f.j ,EvG> (YK.h]3Qϲ )Vb殀˚$WasŠU4s5+1F&.0YjJbx^'. )<Ǣ0O%Rڪ[UKjmU-TRڪ[UKjmU-hb#:B+?V(Hŀ>dp&K^z;]$#PMQPE$c3]Qp. (LG.g00;9Vc10KM{{9efYtƠcՄ/ IMVGd$x/(Yp}x@>i%䓸4ш8!@'1WaE苴_KnQbqܷ@L2#Ax#{G>|)\Q2548=p!T!횏̈́HU˺CqؖpuGEZSS*H Xy(0h/.!j>2X#,24Ṅ;GFpie.71ï%`.A$hCF@:`6 /*t˅H|xHB%>gj' #G u6 Eih@LG ᣣ7s˜=FnhȆ4ŋ^25ŝa`CYw(QIHh¥֗Z]iu֗Z]iul#s,=v3Yus/Aޙs<*EvePъv~݇(9y.C6 `v +7scy$ "3(u4Q/ @Jfn-Dqvwau) ~Τ𕘸GE l eкc p%@˃ v~,;G3DM$@6p`Gk{p+$2 l 9!NǰI+p=L}*Yo*Cv\U8 }CR̶eԢkPS,DFMS7HzW߰D. MSݷyLSb]3Hbr<0b4A_ 2@˃;:X3l MDZo;E #:%~É sFE+gwowЛ`wp՘gCߘCpC`eo Ár'Op#P_R0LMZo+W¯c K & ,=KGQϲac|Zq!!5hՊT0}9jR^v|R!&!Mr=j\+Q!vbJ,cKD~4IH.-9L1 ^X!t.Ƅz0cÛ xIp+aWȴnH^}3 :ۏ`^C=,Xf953-QI&wx5 Ɂ)p8z\#%2YPwؖ˘u]׾Զ.@aRL``pLk`G \!0xdoWp [ R}X}X-!#]},5݂ZYK<}3 i@:N,wOY7 I g>wMNuoYt"tm"`;%f Q+D% n[ ,QSy n+F`qE)DRoDɠzܐ,8ndqT;9Vc &$U@LzhqyZOx ,-R;Ef.цxk,1'XCOx@Խq3v/<&J57K.{ C1chH:6P5ۅ]},9I3;6XvFo#P65yG>|!8v81)Ұ FQ?tέ Z&`j)x?q+іmߙoC8\#F֛# rz#. ,  G׭ǟG "q[*Z# >r3i2i*3ΣPGkgb]ɭ+1/{iX;P7;pHh A spi&oB9ߕ-@>e@XA x+1p2Q *{\HZu. 1ˉ# )F i#y;pN35`dWa+u_KL\bq~hm80y%Ls0+6+1Xl d} "F+BG/c$.H8o׷{L#| cb^. \(`C4c0Z3bCEIqy./=D~. ;ld(#`] #LCi-cF0ov#cFHÁ\V ocGtD; $4B ͂/ !с7`DW7񽣟ef>^DIB Ny'l`X6-COYut@2hERS8IN9ga*%X4ІHߥK~/_{}ߥK~/_{}ߥK~/_{}ߥK~/_{}ߥK~/_{}ߥK~/_{}ߥI#!y鯥_K}/_K~/_K}/_K~/_K}/_K~/_K}/_K~/_K}/_K~/_K}/_K~/_K"!/yK/_o}K/_o}K/_o}K/_o}K/_o}K/_o}HP`0h5K/_W}_K/_W}_K/_W}_K/_W}_K/_W}_K/_W}_KÄ #1 5kW?}_@W?}_@W?}_@W?}_@W?}_@W?}_@W?-[qۙ#Y߷3)[ә:yVcTXy.5{s:k;ye+zs<XgO6j3Ƴ/ngXg~,oNg"YQateۙ唭Q`y<+1,<Η̽b5s<9P,3ef5EY3FngR3Etlƨ:\k2uwVyB(<ΞmgKf^αYJޜ(EͲqۙ#Y߷3)[ә:yVcTXy.5{s:k;ye+zs<XgO6j3Ƴ/ngXg~,oNg"YQateۙ唭Q`y<+1,<Η̽b5s<9P,3ef5EY3FngR3Etlƨ:\k2uwVyB(<Ξm /MC7`Ai8 " ̽  Wڣ (`f7^~hT OyEx k;D/_nsnX OGUEb(ŏh)[ӂ)\AeEsAz0`#jO}"O\]S(h(5\]UvU*EWhBýef5E>W`M%3G|@I!F=>Y~N&Aއ͈ = G OsHL̲:d8u;k;/pM.1mj?B8wA  /f',:;"Bڙ`b+<6}R\{1poBnbEX~]_V@V6JЀ(7(=yVcTXw@_]D/NT]-Lgm;Kf^y"Xgug5;`#! ``(/,#{Xg~Sޯ:1lJYqЛ\ 17]M@Kw㯷orVߛ0vnxl#0:@#\1.X8\ xs)Z|HXef5E|ޠ܃k/&$w2MP `/iq| c(}|D Yj:fF,1գ{Xg~&/B򝄝;c嶪Y8 E`X ,\UnbNX|rV%^Slzv,01\}]x5YB(;ULsw'y!s)YQaI`h`Cz/I8C}}63+Ƴ/m<^AC8E+&-A bc"gx5ɦAYa7F#[A'qN傜į&f^ M#=㨼Mѱ$j6;4b); QWp5aV.唭h=NYį$, 0p85YB(;I`=CK,+Jᅺ)ZK1 ]1mv۷ l 'iYQa7 (q'$F4"h ,i8G;V$`)r<.5{o+N0í@<`kX,fHEA5!0 A., 'v,\lmx;k;:_^maIpbP,bnzثlW#'E++w#)[xeg+~LfxЂ0.ma!`bP Cj=w xؒ<-*XJd.7,7U"`/0CCb->`,4IA@Xa:vhyVcTXwq>o(37GLJh27A\01miɍM78&Zp}Ƴ/mᣔN/f|bS֗NC5c,s_}/g 4 cyo+x(݄aPnC%`K` /H< ^ NcIKyܲ7M@\vRocaqc{mvKk7wFP*Q`w!{8 tR]J84ۂeB2E+O#8JyVcTXwl`tcDkn`6 =D`q `@C#d δdBbҚI uyKf^1&`|gnpN z 4 _kz8%E $Hd> ^ !8x: ,oM0KW n }6t,_|Sv@C0."N2\L H)WU"k@LL *"8"7&轛/2gl(iHl P4?l%}&";&J뀘tx yVcTXwT-)@;EZDu`83e=AzO$4w3{b5o.nCUK|O(k@P^0ixk4]Lr0}ܲ7PB@7 n1^dqIyظn'JDU"" Xml&*ŠV̜M^ b3va|ZbO<+1,< v-Tp}Ƴ/n[Jn&ff)蚏kہF¯4:CMG[8 .^}odp7u0lGU"P )Z|s2,7fFgwlƨ5طSa̽9lfҺa Dmc@m/C}Xg~ J6x7^⻐Ŭ7Q{"Lwk F,oN,C 4RN I22\<*1e7>ŠV@۠]ʴAHkf-Qt bꉘ. 7lƨ5طSa̽9lf\0M8 P 9$, J,'&l*n H9F]50tIu>8<+1,< v-Tp}Ƴ/n[.1 mO(3Xg~ J6x7 .`ie+zqBTaEo}6ՆebEpo)YQako¦Ã.5{p4r}<=z=Ȱ x @bLZel*Y֐L4P軰[ܲ9JQ`xaE+,읈`a <+1,< v-Tp}Ƴ/n[lyXg~ J6x,Ȁp򍙃 Le+zr *1e7>ŠVD K#rO0-\3SͲ"K>$H&e0'̎hAa"DubqہdyƐ87ZudrzpÇ8pÁ5 cw , ,\@-#؄3#_z0 >ʼD$T`E$817p)[Ӂwb$b:t陦 lSLEA7>XE.FH/qj!'ɷsȌ|t걚Wop>ׂAD aI}1 nYQateۙ唭Q`y<+1,<Η̽b5s<9P,3ef5EY3FngR3Etlƨ:\k2uwVyB(<ΞmgKf^αYJޜ(EͲqۙ#Y߷3)[ә:yVcTXy.5{s:k;ye+zs<XgO6j3Ƴ/ngXg~,oNg"YQateۙ唭Q`y<+1,<Η̽b5s<9P,3ef5EY3FngR3Etlƨ:\k2uwVyB(<ΞmgKf^αYJޜ(EͲqۙ#Y߷3)[ә:yVcTXy.5{s:k;ye+zs<XgO6 @BII%$RII%$RII%$RII%$RII%$RII%$RII%$RII%$RII%$RII%$RII%$RII%$RII$ܔ1ip@,JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI)$JI(1inA +;RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%RYIe%Q.  tR)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H"R)H Ȧ"ỨRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW%)\rRJW$1`p{:*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­*­+^Y'b"PT*U UBPT*U UBPT*U UBPT*U UBPT*U UBPT*U UBP 'kU"HER*TU"HER*TU"HER*TU"HER*TU"HER*TU"HER*TU" tC_ͫ19+-3e5u^36ƪ0t8γיI{\΂|ڳÙ:VS^g]%s: jjgCk1YMyt'ͫ19+-3e5u^36ƪ0t8γיI{\΂|ڳÙ:VS^g]%s: jjgCk1YMyt'ͫ19+-3e5u^36ƪ0t8γיI{\΂|ڳÙ:VS^g]%s: jjgCk1YMyt'ͫ19+-3e5u^36ƪ0t8γיI{\΂|ڳÙ:VS^g]%s: jj A&ü bc 3Rk=$"aιGAw81 ^!4Gi |_W+ |f+);tP*Q!ٯ;% <Fvx&u8v<t ]h=تmM ha'{cAI=FeSh'^ xC2=G& %M#ЃmJ]Py -&h k À5hb]N;w]+и$}$:l^mV EtG1n6>VbXJ^Aŗ2pnq;y3™ ~Dn3 I4В-v 0w^%䫞Yqr.7HM ^pDV!^z3ԝXP;@uvo74候{' ė[`0IHy4V_m`,#MsA%}U*dJϗl$&qy 8 j @bv%^S@5w %`qɖ!LAEe]U*B𛇑uۂ"~"pCuGc 517ȴt8cC#ѽdHG&z"+V"Dy0B`{;PA dIč{80csEq{c^`䞴9x/&/6v 8؊{7b\^W忬ƪ05񞋛o&\嘼%䘛UmabቕfDęEAU8Z݈!&>pc̚"D=KY+1YMw,ndc]vݥ̍6$p.1.ġ£q5rhGf͌˩XyWZ]wi~2Ғ5A(L"#S.x NuxFvvĈ1ak JRbMl z#2P?X7j Jj<ˈ  um2Y/PC s0%s`^I7)Oc%IID'I=ZZf%kbw8ֈV\No8E1M`->Nh [VZjՠj4pYx:2wւux ˗];/&$rՒm@I t<1 AxthM\ŋCg=y-+uWI{[ux ' .x ^LI"aBC,Q0P; `4`-ps:=cu- "ķ "+,C{A=*[~0/ A6 ݼ'D͇ΤX=p(֋$n`GVVh 8INm}s@ 2j R\sp= i5 @<YbzVR$RwFo@L  ɼ%B!a`k$m0&p! /%08 qYmw OA^vQ k X}zMFz{,/*1 f+),Wb % R.GAy&$sdod@Gsmi.vMYj.܎K= |08S0. ? /$g 9A27QUa:"Â6:NpH W  C7E5C|1k..iyd[{t1KNÍf`5bC6 AM.ß`$H |qvy;=]lٸ+SK@>V+vSkL'zH ւqv~;:8ZV[]B8bo=q.3z+ ^Q]%8?V3mX6pM6l:e5EFƏ ~^Q o90`Fr'ާqpB8cn9yM%<"c<^c{]%oH<04LJMlmpL90`ED8(@m"N?ߏyA>tl^jO6]uց Bu0fl4 A|k17iD>) Qvc ,.@ll"} le;`GۛL DyO?|:0 @y!b * `b 3_~gX{59hv㳨f>J/L5Nz!J-ehK kt(|]\`^h ( 7vfz2'vo&*7PV$D(Dok^ |ĔH< Sp9فƒD [" zdz- ܚx;m:xb6H=9v 6D+qbv1k175yZ$B*$Cy$v,Uz,^;}zZbN z40#%r'b^HX1vz@ (Ε;zcw^^ }w,<ȸVb M,pz\>wV@H-!]:1fP0XN# i#y&;/k|Xd`a:x Fԋ7^Mw`K3|7qr$Dvo'gz|I|/f18DV+nhjjhg|KAtT@C{Ckv wu3I6 D.&L7%iVbr #Y ˀ~lo`0!ȯyWI{\PM|1ҶHD )(]+EGA"M $ DJp@`| p%)/Ia0ztn71xV?KSe18DV+`T2F,aC䙂.uwR0SvjW<(qYmxnmǐ Kf]YkiNrry`AG LaC^5{h#G\  &8):b9APOkp1`1N v'm7 b/dXdVcUp4WN=b,'HbNu! S5@ĩS8t#[h7ׁ鑗X1 ɓI\z?S;i2nUBoFa3 t D%pNP4SbO"2~$v3&)H'^d "NIp ^\I61 ;P{ $M ƚ, 8:`|ƪ0iXCe]խF[ubO`[P9]1ܵ\n,y#øze5V ѫl ܈rWI{\j&k8L<+C,${,@O}H$y%'wy'8S׌XѕAy&$B3 j2G,9!Ϊb[wíۋ{~KrO+i'k1YMx9vz5+τ4K:Hxfb<ȳ2C 4į)-&İbƗIOx( 4=M@ (F@;AR+H"+H"͘AKyi;l3o@P07dOgR3+G\xsL7t!poj6 \{M3\Fti%{Ckv qv ix!QXtѮVbZr:Q,p-ݞf0. C&w^$pA1xZc258'.;'n.DE ~eo18DV+ 8<0  a#ذ|k=+- !/_]`0`5rmE>eb-G+&E-۶̾ JperH-ۻ(XUk^ /Tz.!9JqZ]Apjg5o뤽 g{J `V#&"؛2R6ȶh"^Gi2LT4͛6lٳf͛6 " q!/\: D+aML3t>)3o8cUs:V[^gYk뤽gA>mYTaqYmyf+)3f5Q3euκKt՘F·יb:/kOVcUs:V[^gYk뤽gA>mYTaqYmyf+)3f5Q3euκKt՘F·יb:/kOVcUs:V[^gYk뤽gA>mYTaqYmyf+)3f5Q3euκKt՘F·יb:/kOVcUs:V[^gYk뤽gA>mYTaqYmyf+)3f5Q3euκKtX$`,X* * * * * * * * * * * * * & &|1RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ*RJ S ߿~߿~߿~߿~߿~߿~O|O h}߿~߿~߿~߿~߿~߿~L5ꩅDa0 <> YVرbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,X+~psϮ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbŋDp@`tw4hѣF4hѣF4hѣF4hѣF4hѣF4hѣF RUgyjPK?>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ%((M0RcytӧN:tӧN:tӧN:tӧN:tӧN:tӧN:u",R_Dό0|g~w';43?_߁a # >Owigq~3H;F|0|g~w';43?_߁aWigq~3H;F|Dĺ O>nnjz~!h"WL=D Q9`-}85_p WuJ> h[_۴n42+⸡\>@M`ƀ_K 0I'[r$ry8a @ ͛5 h㺏CB57r sw@?(Phj쾄K [WM(Ma @\:m ԙ7BG7h제Gϳ|@0Epd:FGcB|4 UqWn PJ.m9Q,% iI4c#aWwUlF#} g2tu{w ;sTğn5GPΤL[uK̦b$*!U)_&f2 . b1ަ1]eC ,eOnq2ղaa;L䭳5CWwiݾ3 ($Ѱv(xrxT(٩ԼYbSZOP (qٝ2UP+FΘAY̊C"!* a0!nTǃU.s{F^A8d!1DՅ43lǜQRXfB@5CW'iݞ3g$X\a.V P@@"@q3*5+v҂P 01XHZH1F76n'9ÀPx)ȑ b>  d)E*<[@,-ӤffAbCVa&iWbg4"7~[Ŋ_0'ɋQl2^ Y6Sa_ (JhraT 5lMwP8UG?䤋k~23|g"Aфw0˖PJU[)lJ䖦CwAȪPR#F DJ!`e1n#5 ErSFyQ I ŠuW5# ( ) ^Į#M U[*/!r*L)E=͖*Z<׈zW++uLa;*4'dh6x@H~EYQ <د.ok[cDj!"l]&]Eݐ;B52͉][tO3] h -)Aj |åh3r #,LQעwǾm=鈔:O#Z'{a"Ѝ3!n-v*wMwX8s _sgs&QF 6߱U: 26R9ہƠ+-A?߯rQ#,A{Y`hI m}+UTTkN' .ylZC%5\gH0DeϙWDC'!p" yj)UJUWzttZ? MfM +!#Ch&8EŅ "5pHHQ(@7?4lҞ{ۯ !Su߀Sـ(VmJ*TRJ*8VU1] oa˝ՈbVhbWc\sU/3QbyB|0$2iRXYRFwZ| 0t[zq$Ny>M|`Į*U^(D+ovzO ƾr>y:0P|㢝&;43?_߁a # >Owigq~3H;F|0|g~w';43?_߁a # >Owigq~EF|0|g~w';HG7_Zo3ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|xTUYZYn`AA*]~|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|I@pʂUԩRJ*TRJ*TRJ*TRJ*TRJ*TRJ*T @$-18%Z %zׯ^zׯ^zׯ^zׯ^zׯ^zׯ^zBSxpTF@&Ӽ` 0` 0` 0` 0` 0` 0`3c +~?20V*7ׯ^zׯ^zׯ^zׯ^zׯ^zׯ^zת,P^Y/@, ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϛ*UA, hѣF4hѣF4hѣF4hѣF4hѣF4hѣF4hҘ`Z|%y` 0` 0` 0` 0` 0` 0`VUSӽ%Pgk,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ/Ӵb?#R+~F9W?>KsD'G׺}(\Nu5.Q^j\%s:>ԹG4Jt}{ߑrh_#R+~F9W?>KsD'G׺}(\Nu5.Q^j\%s:>ԹG4Jt}{l:t {a%ĝIEƍP'&J % |zׯ^z?RYUZ<p=yU>DgtoDǦ엝_>L(vբ`ChQ]NY:>r HM>" d:X2$l\1z!L#uu_{& ba%uRVXU HLy“R5'.XG4Z IPf-aSy -"L@dF́0pG$Wb|:4k\@Tb%gY+Qd-1Ka5*81O|_)VvR,ϯ*]\FJKU_"g>B8D6T|GTp%)fxgo!D~FH&J+u`Pa]^Jw*V)r9`9WM>J?PU8o_řc0 50΀b8 D`_LJa3.h;֗,h@FK8hLp>%d QF dCpκ +0} !; ̥n^ZҒz%/qt,,(f+,Sb|8 _?7<8<sXdA#2`kRIY2do5"Lm* o9KIurfev9,`M&r*į5ܘxݪ@8Prh=:ӿ#LVg_bFhg(U_@!kQ%VUYw.WuMAeDsIYR4 3TÒ'R`2G"҉\hH+ =`BԷ l!F~nIҮzDHDn=UW"ۄWm\ Uz*@1\#.r UbevLkU>@!#Dqm5K4YLUuLĘn\C:4!'$&:.ʊUlPsܣ tG5D.Є"dвRg $ÄȆOљI,jAؕԅ~F4z' h@wl~wԺT"5IQdS[X4Bd.r` a |' =س]~.baTll_dЀruL39~o'UhT<ӎ@ 1!xIr*ŝBE^PRU0 gJU[VRTs3SF5Vjlu.H  u`SA[{+6 Y=͔n«_W:/&s_~ VlBy[%Dh$)J6 rk9GRŅ dsP!n#g\ Pr%ݥj֊aq:Ut Ӓ kajZ J")c:Ք|q%BO/jKW^k_^g8mlΏ+gz?S:~FuP#h p•h-L{w-fI*:t+2ADfP pe٥irIE`ĝbt.9U@ƃNs[9ԅ J*dcu5 Uju4TB+`Ϊ8ҒT lbQm@F琐B4.Db3ugפYώW8-Kf5>,tο_(ryr ̈+[RPAQLڠݴ[]F F؞&O$q:g>Vpl,UTlwf"lKL&>[`c1:5F`(m,dE@tˢgDQ#.KZ%]4yIfȰױ|b+ ]/H]rv0AكA6M2H#X²X^4 u21ZmKlC UlW z"5r- {9ttX/]I%8ocuy@<'Hp#rɔB- iQElzTœ1 FUEd" jPtx>)9PyG0A&2+,|f9|^_^g3FG:h:c x2Q0FQXC8Vp#/B30|5!CuUJhfb ]iݑ_ޥ$iOm +Trx+݂N@zBW=Z @a[8㒇b-$g" M=ڰ4#ݯV#]>H@tDJTRP sDnr5P@= P3>0cp9fy(?䃈a37@l(`3_a{QÀUXĊµln $(s_ }xت`|wS,Wj$IͰ 1D hhxj)ŴReO5Y|xH±,198/3glI@xa՞1' 6NTUN \Iǫ9bq޽ \FpVTVv2 X0Z<&{Ζ{9; \9RpD 4e^`e:AȈ@5ZzPWMH3K%s!R x ۈ4/<6zlaC~W i083Nx:K盎M R!3(FwS,Wjǟ8R|P (<@KPHQ8,a2 s&^1pGR8*&(Mj=?7wjJv/,g<z"Qy'c}ܹA?q"%Y2StؖM<޿]9ܖr4lY.tHOZ"Up7U.VzQ93m/ТA2jKZZf\Q"ɰWDZЯA/H`ZbHV`b&})+>3IL N/20v"ev'f(DwhU 8"06ImlD ^2o_/̊KS )ڢ<< rS8]00Iq2evd@ K0lEn?:9v$U&NRN+D Yq\!2L<ׁF]-_[*8KsD'G׺}(\Nu5.Q^j\%s:>ԹG4Jt}{ߑrh_#R+~F9W?>KsD'G׺}(\Nu5.Q^j\%s:>ԹG4Jt}{ߑrh_#R+gv\RJ*TRJ*TRJ*TRJ*TRJ*TRJ*TRDյu^PT V^zׯ^zׯ^zׯ^zׯ^zׯ^zׯ]1C*pİJ7,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ0`"R5`-1]``y$H"D$H"D$H"D$H"D$H"D$H"D9p{JcU)pRIbwϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|<ј-BY5[:ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|;PBBeEp`a@K|<<.vS8> F;)\GRx#O N.#σ|<<.vS8> F;)\GRx#O N.#σ;6Vnr lj|͛6lٳfM`5<ޥσ*VV*kIx>Unf@y^ q5EM%{D>1 s#㳕U5WQpaFqSa fˇb2ͪqC 0J_T$-Ɇj:l)i+@18V$ r햅0 8y#@P)@>([4<''-nKO6%qC^HJ(/{)&W\짠"Vgj([_d)ĢP y-B(\7 B @n;,]SUEh#fUʪύ @5[bC^2R!+"k7+pk4!DiK#JHŞS}< H:kȕҰJ̕ <% D3W]Ep2-NG}f >ǯABP>#D0<;)殘(tUMC:Uf/zːW/:P7 %`Trt $b$0P"Hk(D$dymϟ%~ QoRσC. Z&~')UG ԂJ(lv;#AT Ȯ(:@Jy(Q)hm\E!Glw}g䦮3"Z0WЮ|/ |+ʇG]`ve8FBk25dm-Af1Z:;h}|2+aB+(@ ThUp% Iej"|WdT#;Mb1):i$53 0J4?t<>& !ks!RN2Uf$5`Wsphuaɀdsɡ?eC- .X o V )e6\J/_YG 7@BtX<{_ƺ_( 7cΝJV(LԽAenߧϛk|G89FL>-y"sjXז 둥f =X?r[pOX`0ڒ̊|]?O* k@ P9C w\(={H$h* uY>\,h8As3Gc|ٖwu2+9N\D;Y\P5U(u\ IbNvڑed',=A <Υ+v>|]?OuS&@rCFW4+V#J!܄A8fWgFىa5xa5B sXa.$*sz\x2+p P ww?p #! r _njj!T҅*"KB/7FCmS鬤W$ ͑9ɱd pOTp8KL#>ﭹ袚)*BMj;*gR~>nn D(J,cV' @:YVU_7jUNUkGG8]#J!g:G`ƅ/P|O7zN\D;vH^Q.9>GԽAenߧϛk|GSWzQvX0fUeUV|e\VSR™v҈i×BEZ&桪S#A+խj/-lPV8܀6" VB:o IP"<$H"DxWR!X (CD% n!ʱ % hSI)pF Gcћ> - :,nv!Y2áԽAenߧϛk|GKF1Yܟ@[YZ%A Wqb/b)(RDQ 'z8%)fO>eI&M!:0MX0[Ad8\+b,> -ONuqs3fӺ/w]:1XVrplk[Ln$ CIl[U`MP<]0%j^2o5>#%H҈i2K,3Oe7 gͧt^."<8qB;RIBHXKV|ƻ~:M鼑ЕuVYC6A7Y \U$mZT#pM™óigEZ& -8 Zd( CsԽ!bLq f?(H[/)9˜h>#3(3*dy3f͙չ ifc఩Dllٳf͛6lٳtI˘zI *I"v 0@vl2Q1M@RÏ 0^x`"`li,A#88nYx.vSЍdJ>|0LǘrtΛϟwh\Bg*uDUSw eT9IQjcfGd56![ Rx#O N.#σ|<<.vS8> F;)\GRx#O N.#σ|<<.vS8pƸ Rgɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɄ$J#NV[ͻv۷nݻv۷nݻv۷nݻv۷nݻv۷nݻv۷nݻzlR0Ꜹ%[pÇ8pÇ8pÇ8pÇ8pÇ8pÇ8p '6*HXfK,J*TRJ*TRJ*TRJ*TRJ*TRJ*TRHHA]`v,Az/J*TRJ*TRJ*TRJ*TRJ*TRJ*TRJJyLA 1XÏxq<8?LJÏxq<8?LJÏxq<8?LJÏxq<8?LJÏxq<8?LJÏxq<8?LJÏPKs&Rc?1wG;t~c?1wG;t~c?1wG;t~c?1wG;t~c?1wG;t~c?1wG;t~c?1V'%M111111111111111111111111111111111111111111111111111?pBR/3 0A/g,q{9c^Xr8/g,q{9c^Xr8/g,q{9c^Xr8/g,q{9c^Xr8/g,q{9c^Xr8/g,q{9c^Xr8/g,q{9bm Me?i}^:yxm}8mfӼuZ>Ϡqwϡͧy=xmڵ}AeCoNzϵkPo>o>;6j׎}Ӌ}vm;Ϲ[o>կC{-{ws׎}^:yN.[y?ٴ>oVu>]mi}^:yxm}8mfӼuZ>Ϡqwϡͧy=xmڵ}AeCoNzϵkPo>o>;6j׎}Ӌ}vm;Ϲ[o>կC{-{ws׎}^:yN.[y?ٴPc?wEXCj0c.3ap:$}#8pEqD٫>pV TS >#Djy^: wj"T>6, _Mcww;wXcww$&9^:T>-6D2/'uL ;1>ˈ7@2ĚS5tGL$$`YD_|zz*Fr"ՠya{+Nd$188(V~ }39%CzP1M{SjW8-ècNo &Z )S͠#:? 3'-f تaj#: ٴ Op J.,P ![O6i/V2,Ru / idz/t>oCK4rwX,B~b9'יڵ}#QUW*0hikMRyUlPNAttD@t+ٙ#Uc]'K6]ѹ9cRP4a>]췠j ZNÍ,y8( z<ʅ@%P\%y `@x0'x>^ZG1ڱ0WQZr-p3 !* seRT `Y]r6Rr˃W&8X#eW0\I@nIvaFh 0} * \).88A-a-FٴzKqXf )A=ӭ{6B>l!(QX D8pB8}+>o)@RT%A**̥g̑Sgj׎$~*Tń t"d+丕U,20z&ȓ(!XA@3,PR`{d0ľgAem_ id+&4%T(N}z#QyD09a *uTܻV hW˔`BTj)MGEPA K)2Q Muz(ϚF L7@(DZ ZriLQ4ps>oKHiJG`&݂$@WOykbj׎󤊔V RkX&B'*ˆJjqqp8c4A9&XUVBQKHpZbQpcgCbPh ꤥ4glt* AġF©i䤦`4 ܡ3mk[ 0zȐzLBTiPCBTP"\v y@ۊ XdƓU6'XCb$*rZSvZFP#8*"9"T'U~N^f2 R#+e+INU _(lZP(K)U("H#!lNķFRgw=xo1& "A@mѠ@*LtEU@$%ɝع.4H *#Z>dT Ր<<-   J ]R.<+'Ott|( 2))K 6# }Ӌ$ b Y |r VMC& e.9`H!C20YA!zڞ: JZqY8|-%P x܉yxdHLZ_o +^eeWqeDK8edb QFOBC"eU((%P!,хkĶ! FEbe q[yP|FhBQQ- %)|4T)XhI]I/#-d S,*{Vu)bŊ \ !? TC٨qy4p{ ;64ԉض`'fpg2r#a|5ZV`~ 4evF &IQh! U)qoLw[y.*#Q-hAA!h R?'f@اrf-կCOBX3'$J"`Fv$n`X @9l<,J"dLw(JjoAeD r_VؠLLB\ͧh (WSψZ73T%6Wmɑ9>os׎H&*@^ Y/bό\];POTxhdSZ>޲wH6VBt8h٢UvU) Xv yr#RW>]췪tHsKTd '0B"B%lH8`ô4hX ScE`@i10/%! ؠZWJQ6`fO'iZ!С>ʎ6nCu+#r׆؅aFlPM6!ԓa\Gqy^:pzO(q!bl8Q0ԟ??kPzԺaRF%ұ"nzУk ( 4)AyӋN -a"]MY=dy9#5yJb c3r;o^&IVWNMVsE̗dD1B8O ql%j `d[ʪdԘlҙ|Z!&WZq9(j{y^:O9 @5HE"K\gZ rBDb^:NI- u+p8 N@fV64ՙpWx*i:/:! !ÿy* ӋnJC}=1&C< !%{D)6 [y*'5zLlN恩\%Up >/(*]0O*}vu'aVxx;6UY$jѾU@jλ\V}3[zIv)Ex1(V6/Aڵ}Ud"}` Y3B=gZ9FD Um"/"œ*#/ۀݬS!h%S2i6c>]췬tkD%bD@!4Y& "q998<΃z@Rɀ1ԕpEL8*=]̰E\j t rINUMt?_ԚXcFYK ZKKbpi)yPʬ덃 V" f 6%o?fBQ +ÃbuwT.`p0|3[zIuIKJ6&3mxoUYo0jB+Uj&-@ qY(6,@1**vނF, yqD!DZO5E$ ZtffAN%JTPdH8X@lGPfLp w=xo[8+W~B e)bimOZ>ުz-4;;t#i> Y`} ΪHpctN.[pU%l8sO%@R Nc1jt?q44@%04 *j;YBpVUs|3--d]jI!6 >j0}j0Vq3֟yy;6W'P3Uٛ mxD!x֦j 9#š^RU&J~A@3-FJ_3[zIq.d*GF91b\DyLZ>ުys0lK\uˀ@X ۗ P|⡀%j0[W֬D,J s UhwmM%[JoQ~ *@,# ]^:VN dD &dL 'yg؆xU҆tN.[r:à"Ed)9 \8uZEfjVU< rU uB P/;6Y9}.)1vεVn!]k vĵ,$zʌ,gH,R8% 4'͂m0dhx!Vu rZQY y";!KB*K6`Q 7qwۉπ%Ujֲڍdj+;Pp^VRwCza暀QJ2L+\۶'ɲ\Uu-B!a+3 fU'X h ٳ#>,BMţmGPITC٬#aX^s׎&f ߿_ZD& Ul!$Jx^WA%gxoB5_ צ7Hdʙ(b-J- EX|JoqWÖZƼܚ%づHָmK0 ($h}8oB\k1 ۷aDAU2dAG9 {=w8+!tʼnx|_qdD$2@kzT X+۷nݻv۷nnrBBZSB@o ;+sΡF2K2O'&'pcȓY#9ED*+vm;Ϲ[o>կC{-{ws׎}^:yN.[y?ٴ>oVu>]mi}^:yxm}8mfӼuZ>Ϡqwϡͧy=xmڵ}AeCoNzϵkPo>o>;6j׎}Ӌ}vm;Ϲ[o>կC{-{ws׎}^:yN.[y?ٴ>oVu>]mi}^:yxm}8mfӼuZ>Ϡqwϡͧy=xmڵ}AeCoNzϵkPo>o> K\????????????????????????? k~#Шe@,*`Xeccccccccccccccccccccccccccccccccccccccccccccccccc`F>X"Y35pq?w;pq?w;pq?w;pq?w;pq?w;pq?w;pp=2{؉ @ fjpappl-1.4.9/testsuite/landscape-gray.png000066400000000000000000001341301476704353100203060ustar00rootroot00000000000000PNG  IHDR+e8(gAMA a cHRMz&u0`:pQ<bKGD̿ pHYs.#.#x?vtIME 0B^orNTϢwIDATxuUsҍҒ"?VPEJRJE 9~=s{33gri[3+XbT ׼ȝI%@"CD:,Y@+(p͟RV<?7KmH-hQG-,iɵ Tӯ`MjaE[ޔO(T6H-ɫ zΧ’ZߚP +znr(!+ + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY@Jä%%&%&&%%FDDFDD&6gΥeYIڵsnyt+TL̓{xcgNI!LkTHYә.5(&7ؕewqj̴-:i ox#X0LiӦ D tpŊUU<~|%@,ȽJ7FR"MH[}@V07d򦶄oVx߾=2aSgUѽS)|wZVxd,oi+H8搛/YzG83GF]S@n#50es쵆w'/=$zJ2a/]jSEK 5 +Y+GTV*ZfSAU^z FfPY#_>tk{4%#h"bƣ[ld3pg}R/\ C;ffm f50w:5奻.PKm]NIM1#)df6v/$jk>nm{rnV}'̺vk}5o$Rcu_sYH_&I'p7+on{KJVn]gMz"50mV}k^+x>}3YIjyRY Wz̥ A+]OJשn]_Hyrf5 +$ЖyZ-4>=05+EKOJL:u6y 5 +ԛs/DOo$j骅HOtfS [vW^yo)/SeQ^cLAdz9RM> BhkU[=M'OQbmCe7M?+T<絪zޞAypiL dmk1M?}HAD-nQ nrj)^_qݧ\~5=Eu B2E0GqiP]t>޵3p K+<0 _^?1z#*=7Ŀ^dɗHs{ Fa-5ݏ8}3ծ.՟|.ݶ7Q_-w1}n'R 3dZ9+9WVyOY+[Ř)|!UW@W7JxMOmϥQYAkQS/Iא`|[W>R64L du6XֲL g6 {]pY̻w__X6eO{뜬@VPiJー_-؛~PcTpY+種6^)&(> n&2Gpve+?.MV~ WKzý=)k@q|c0mNj`2%+C5=m'R^ R~dbnƯ젗llB/M¦K4{6'MWԿL]3ig_V(2FfS 6 QE*iPV!D1xYSmy+dy,%ק.ϬAi|`@Y{UE/ߦ_Qzi_^[ë: !+ix Q S7S&8)@_^W,Ϣ'+(y 7.Oq f6V1GO )ӵsqBpjdcY&+pj|'mB0`w={Je3%$Ѫ],hR70@VA$ Bf dOVK#NGIs1&&+nf p–dluVqi*OXЬfZ'+p2dx*.lI(Jdʓ-5Bc%.C%(.e.&ˈznkOJQ"+zՒVyu Q{ ^߼?+8(jjTH7\=6-Y(+ԥydw5&+ief+.mG2K u>NZR_xIz<~XaM/Aۖ!YN(+ Bz9%qga,q}cuUo=mCe(/D4GqiTH/\r`!@V[웯o|a^?vH%2QS!^jIǫ7~1@V +ڄNFL_? -V^ЀcJKkB:9% Y7]+k3V0\Nh!rm?oߐԲ+ؐDJd#օd WK*{\Ÿqp=v^32`?9?JFY}OqǸղB˩iiYG˟?:`ٍ幘qy$YoQn~qS~ ê wEia@8y#q%8ٺ WuB\QzV2`;HtDÿ[Jt2q%GO!nέ5իn` z6\b\v4C̐2mI2oP&!>z +BFZɫ֯!5u !+]i2`aw% 3ά^5'Q(v|8ijg:JVP#}Æ{G2fu0TWR0nzeq[]-) +3+!.|}v}|u6( 6seI!I=83----=-Ǐ% TQ'?wyN0GFfȹQ~r{c34"rw/<Egc!?}q$j5c{aG3`/IHVTy&QA7_v|ڙ㲆}eO| K@Vy=+kѿUz%~oig+yzZpٵa/Q%)8ٮ ÑICrVL YGP%鸬E]-) +~,f% +,_>ATA?w譛-KlX=0YPd]+/FR&ki>sfs\&{le N?@VRLfTf\-)?ag[gq[E"+#6Z|ɔR_GrEo26 f[=P%w0j2t_ . ./mii 0øM>J!#ũty^3TLW˒m ks6 ::YCğ*VVjY.AytY~_.R~P'ܱculM1tsjByLS/̰w06pɟzӗ{ ,jxBdyWK:JOӫRv"c(rQ:*}᳝BQ~J5_:B\Y=r0Y m畤Pѱ,xKu(Ec)'.^~bfw*;]96([Bɂ7׾rѫ1bڍխv}=˵vWAޓ?ZRDάN Q}HOOOKOOO=~G_jz.uWΟ-Rp} F 0goۄNO69O'k`~Ad7o۔L@>`\d_糲&-P'cnOԠpwZ.b2]7wA 632a8yTu~SfyMKt#+g|JBEbc >Gd5kQ8N/{ҝOcF;Ԁ]8Q'S{TTѪ5EýzO P3Wa@E_Q#w˗'+WrBQɼхS j܊TӬ%@X%^.,cµ/[t*ܟ?G{ +ɚ4e2ժU!-;u5?sQMrL}[zConVӌ_qQY*Ó[G:x+_uPL ~{c|CtV<܌ Yj]pai]E\ɠ)rVzV6U]T>#_BjV\W6G]g୓]Qٲ坐*5k֬qۢ?RUزU/I_^+W.WhۖG iGVO8EGBWYz|M<ݷ-t$IټYqQGx` g:eB?2#%959'njҐbW^vP|MR}5 aSevx %q R3-7%+HJx&d^x15<3m~U5z)~}~W}@ /KV)/ Q#״oKV'[P.!+P%+#x1=qyxa{m x LG/웶Hsl;g(U/͵Ixd!QLlW2֧GigߛOLOaߜ8YK24/|H RWkWG*ڵ dɂ;t<w)|KF'/ pRɾU +c?|/>2cpoI;׀8_'4w/(ݡ>WEϿ{rڄۻd'ԩ#֯]٣;Te <}Ͽ=omnʲJۿuky͚n(f R<1/\2޳7A+*7hP;YYrfڨ>qȑG'K+_lZ!͚Ƌ!ݳwϩlI4/[\JQN9W/pȑԔ!B#K T@ l&DN…ΟprFFFfF"088$(4.>>.>X!gdWջ1j [?@!'/LmʳYYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY gQ K:}ŠN\>1’\@!l k:O-r5dj1jB"5 Y!PA k#ŰWWZXk'M6Pt9jaI[37)jaEG.ߔJQ,sW[9jaE/\oǩ%=r ܥ-u/[9 + + + + +YYYY d@Vd@Vd@Vd@Vd + + + + +YYYY d@Vd@Vd@Vd@Vd + + + +YYYYY d@Vd@Vd@Vd@Vd + + + +YYYYo?4;CeY)ɩiA!’2sӤ?]0ն>s.9{ٔ,! ?&:X!v9઄N&$g2e2h˧.^xrFFF~aaaJ 4wzoqp˖vfV8kׁ3o=fJBBK~$Wa醭*o,\9tK8;WH2d>tP?MM'+Yd)\T2ZoDq!B*TKVo]jwW>`تGuph%M"JzAh6t8Q!6Hڑ EdY[{۷bMXbsVV8ןy;9J}^ʦ7G4nQ({=9f)+Vװ Қ9:6&\pPV8ur6/;ۭc%KlC匑 j^^,m J֬:‚-Vh6R/8[PKpU'h@_/+3zumĩM\pT.˭.r7h3 ~;Pk~gG`ul~/8auMLwU'+xi. u垿8CQC=mz֣םSwE祕sT!ug]AO3|7Zβ^uplA7=OrG>ؕ^Uz}Wp|EO_Խ&^h:qz6o@xMw85]w(9s 黂s:@ƍlABT zI;.ּu»*z':GEoRƮb\#O7}vHʩ3"=Գcn+Xrg7b\!*k͆vH=5;c,*Z/9:GKc:!wYΎLE537m:1;vz.Ӣͩm'1w~7jZm i''u^楚t;eY}aN݀;qST -S~CXpߤ輆34(wE3*dӬKwR+RVͬAX‚z? " Jd)&{fnI UN'9mJMպf1M'GVPywqVN3HV囩:{>9:t֋&̡aǬ\ހ[N-ѥ}+(&׼ UeTבbxlpO:5?S[ la>|RʥO\hZ~]hx֌bܴkN_ZNq[Hee}ՀKdYUME(7{ tvJlgXlͿrg}&ngN T6_`DDjhR*O^zTW>Kd%_ Z^XUU 9zbRU<9z/vEKRO;Y.QpQ]cmq)r NdL7J5*4XWxlnk?ѝGf]V{U1+:rT/ >>>T^6}ʭ ԪQH<2:|)ZȧL@ժk>M2@*U#.*PK'QuyY꛷ϸ}\GCCB몟USvZ W-+H?cwRoȏ[獪~&}WT=80?M/]沼-©pr~]bԪ.8EVRe"=&Yy* mY)Ԑ2ީ[KESkoHwڏ$N^Yj=ob'C '#R·Jl񎼯?Qm \n>ʝې ҧ6d>pAqyW?j وf']?W^᪘"r0KQ^&?5}6 ~ Se/;5UIU4] vrThGb RX`gPb/?ay56c%ٖό b6ay/oUZ#f_Ōڱ#G`OܙۇR#o\׭BPrOSbo- ?bIݍ^M_7ϟdd$kwomvQ륌emRłvU%fblE'ؑdXQAJ eU^F=wLz bG{?$HŤCF!'>Q5_>Kʗ ,5nL.YA2Yv$wQ#]96c'uQqvFYKj&47v ZdmD[v ʧ VckFZqwLas%7KQj!(7cܸB1 ; a|)*Ukx~])6*/>t7e/nKyu ;*CVPf<2?EY8nPу}]| VidʗNֽոB YAy=35n8r*//HR+)~/)I+$ Yb7%rV duxy\XJ4;qErݡk$lY![ж֠FZi%YՒ?ސ\؂zAUw$ LNא澛"fwȞU.+HF2) >n6o_K$orVNiD9~1%sQW 0No EKU@qV9Y!҉Nc߰9ˣ[R#>XWn*{DzX.d8 U yոֺɨ8kd@{g<w#g;54tttt|r#5ix&GFrq :f=ԺYq`[Vdkr),lprq 7_iiW4pHwHk#0s,8e5WI-[ukdݰ Ij5G.î~&.^Xȿr*X[P#-6K+z !D̓SW]]tj !bBd&Y1E~VP|,!ٹëaX&s'n9+fUb;[g(A+o1޾eB?_Ɍ+qDia>ITG-;bCW}<%Q-0 t)&a҄zz*޸V 9n#Hỵ,s(,A/6JoKPɶ&d+$1"~_^a?%7(Jt!ЊBjDvkpOړ+^֎ Bi $L{?v6E.0'bd;/{h~ʨҲ5d]\TɔڶYAveYA<ezͰ5O}zsc\Ar-Bgj Ԇ2h\V-ň_yy̳`ٰW+óa|) dG=\\[ 7}C[+/G\]Dzm_cw⃺bo% 6ܹb͚lKg:g_g܌dɎLmGVBX_ո`VJޓ;~:_v%Q8_l<v;Oz_WP;/kgLV9K^m R=m,nQ9QAU9[? w@V0E%~^7.龆]6$ x¤1w؃ԜFXBi{v8ZxsW +qyFZ(AJyjdsSW}ˊ~YVwW(*2*(911ᘻ+Os+X$+_ӘwqaX|)sezKzk4.8މ:!3) X ]I 4F[L^O[-޸xY +! X߇xWȦ]yzKD/s{)4^!Ř>2O􄄄sƌgy[eI!S#m&ן{^:-6+YA '9^p {]ֶkzo6lz綑HWi?.[)B%| +X/+矬uVpoO֩ྯ6Y{x_cnI03ԠClG-~q35}r\6~Por H(ⵋy[ddybHO_9I?~E55q2YA!n炦_}kC]+i ZZhNѳYYA哹c>U0y;x_BԨu]g;_9OE5ӵ=ThsƓW;4'k zakͥl}mdHG3~ղ/ 񮃐J7EPcˍ+MdͲBw602qkJtTkj350ᵭTU+{BHJLVP=IfxR K/ipGEoյM3?O]Ҹ7Td)MMQV};3'ճ+rb?5i";^d*:,I.H7?Www^]Q3TV+{P5^A 'ɸ \6ݕW{@EqOK*$Ph=?RFE\U<%dVd5$椨Irdolʦ hC|M DBk²Roz9GVP#"rHqüf:xTP۸҂ҼW:;tZ:"$`bZeDol,{vFQ~jTwf@V0{]\__BLE1S1Y?+" !ݲ'~7)@rN*fj)AyG$adQ6?+ܯIcI'dӭQ$*`I3/)-bv. ȏr Yù꺑rdϖFB[]%io&0Qh [d4v5GKea3_A-7ewg*vE5͑4Aqq@kJdʋH.6I6ldzA攜H]YJ1SNj_7(.OM|>beV0&d]`m{$ ֧HeɬfFru\;jdY6d*.>(w0jde'}!cu1[֠E21+lp+XN$ɅX8g++ϗtg7{(YZY$ Ñum)Y!WfF& +X[Jm?"yu0;d~&i0I6f]Һޤ>"+Vq饽;ڢhJm)iQ&U2Y5^$cY!ו'eڲ1ߌ 7.?x7) Al*,!Rߑ]\J&g7h҃ZYAcҠvQzXyN 9Eҟ*qMهٷeA r>ߤeg7cɄr7r\s #@{TEi6iڹ KZ:.;wbV TYޝFrL>V!GvXK,u۶ZX曫lbLRjǎO+ g׭ܒEx7`AI壤WHej@uW!_ISo*Qx OBY"hX EmZX|||s?Vvy;sEU6_D݇7) -"5B@_䍎]U<2tD0=rNBD/vfFFFFFʅ /$[bT*ڨ "w!8ov |i nu]e엞Sԏ1Zչ3ʖ-WW0e?xuCs~S3Iwkm(eT,qLח^[{m8Sy+aA n2F;}J8 HKIMMQTb M ,/3G&+?5RUJwd;շJHp]B)>.P )`/o̠.] 7ɎJ s9Qj_LmEa\9oR- SjY&&'+VI&C\YT8u|gAZ?P+H ?іk~^xz㒤_WdGu{j̾i-=Z^p2^' 5C ȝ%kq\?zQZ_n`Zxq {B[ cta2Xg,Km$aUu-UO-jbз5,RxC:sKh!M8֙ZIٳ,+`P63eۍkaok/WZ0`>BZQX+\!`]GhMLMaj4Ew^'靣NĄ'Zk/>ϣTįtai1#i qkׂy*Y\:otNW*ST )?nu#~nMۆ8{ާ&Cx5 {TZ iXD:k9 ZGDϦ|Y_ߟ*uhzw:wOuD֢y U2G폦IOVҬG$E£?o ck-(xyyfAO4spzM@F=QWjv7y=~6]O|Yj|_k/tq i~un/Clqgw.S=x ֜OV_ߝKsuZ5(Vn1`O)SuFMM:އaܽyٟnvf_ҝtz)U6d_9 ۺ&9*Jխwu]ꂚUgDuXlO`Mcy{>YZDHӦ6<|\EفʕYBx2pՕ{F-[۹Gr]p uYvƍ3ݷϼU*W nNY>|~ʕ+[kYeY"eR} 2jE~+{v14\BRyj3>k"ÉIII9"0$$$4PBsP(SFS.#### B$p)99%%###3ظ(9NlF"ٳ332 ,_ Zy:\XfI@=đ"0QBNn`+_Z?<;Ъ3y,yp`v6 @Vd@Vd@Vd@Vd@V + + + + +YYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY d@Vd@Vd@Vd@Vd@V + + + + +YYYY d gt!VtI-,) bYt^@ŠR2'SQP \1B jB5|)%ͺȢŠ^>%ɾ߰xjaI'mjaEn (ѕ-ڕZXј-ԎZXҏn oF-,ivԧV23PBVd@Vd@Vd@Vd@Vd + + + +YYYYY @Vd@Vd@Vd@Vd@Vd + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +R*233SeMtࠠNQ`….pSΝ;w dŊEGGGܲ ;9%ѣtYAW%\.:yq2.:B*+R8/J !߻ .}˗(V4Ҁ|DB?zl\.wqYA!DQ.PA].k_Z93_ݺug"7)`e߮+WT2>֯=I'c\.r/bS}}UzuRo[d!)VkCz["ժSU[*i_ Ta^QS'Qf~CJI;P@FzvܰY_`eoXι7Pt\A8O^Wd}6em!mL :Uf+(}-C z[܇VkCҳfrY~GZ 5SKJ^ɫ޻ٴ>Z cѠ_ugY:~.i:>Z;_z6ԭ TN QO_X3˧ ߡT>\olsG~|wPA%ڿ\е_(ҚեvZ~k'r`>Z\`POֆޣ{@RHէ& TaE]"WOK.)BѺKVmjmY7*լsV]EG7P>orpNw/97o05IJt6Z(+vC[w}Oˁ(h^woǷ[c|0, mnbF֫k[ćVkC1um}bGh>\FTi+s ]KBVN>Z*^uuhqA=k_k^mA}lT{U:Y"+hq{?Z e4螏}kY[ZSۧsK >'^޺sqVĝ}h6tn_:u_1ztc }̇kb_ymZڿWB؍Z݇VkCZfP,gy} YsA}jm(NzU*Jz|b [9i;a>GMf|q2^7 ^[ЇVkC w8}ӝ (ko[ f:1R*n_%>>nUR'\cB jmEqDQj<_T5tEZ:~~2QAܗ_f?4 *8bXܬТֆݧ+V鼡L>X'{Z Pՠ5!e7wϟ__EqjVkZ9&5k\ͥbEŻ՜ +|ę'akgE<)+dzS}#+CB{̆m]!5Tl͘K@EF2ru?9[w0|ӫ(%KռfciXp@~wi_A.辡6xQd*oijm(l`%טy|e$.\JK‡0:kY9O KthԲoԙ˴L]WIVp_~1f&ֆ 6+>tOw^vTq؈fv_ͅBlyZ5v %*dߨx>֮S†SDY!4!&ֆjeE'~tl~>uI+eK"2骛U8?e;ɘ%{\BaVu?f`\M~횘7Zʜo_phurԽ&/0Ge^Zu'r~]ދY$7~e`[{Pܓu T&a_گuWUFQ"W Q3}+.yUQa2ImTEo G02+VVMՋZ*ѣR?_>:e|)+xfM筼HtT U[?H#)Ng#n00jMɤPު*/BByف T:,w9fCUFn>.=P>Z=RYi1`;jdץR) zUbjق9:m $gJVf}*:)MUi?b1q wI!Ub"*unB)w_e7=b!t{ό+{Fn.N'\}U& 4q }NUsYB=ɤj`2w?en?EvEjc6h5hBAV0ija)О!|j6и:l g\`XV8+R}Μ5Bh|jjmTyk6kdd8'+ @ e=Sv O#Jd:W8ឝ+$ mZںLV վX9YAl\$i9f6dQ@ke%,z|6}3/>z zg.; nZ_qq=B/mVkC /ZO}fyKe箃]qq'¾\'@Ӷ(.N|kgs8&)OrŵW̎dw|QaqDŽ>_&~rT>a+V*q[mg~Tlf (NGeH.?O+N*,=.v g3idVH oU3VkC 7%+% Rv}}΂Hځ?r}6o3&+DhWS >C\=3c~&~jMy d}v9aS:e6mi?N$&: iAhxkuO숬`7yh\r^_ɤТyt3¢Y!P.8m-3|}ʚ(ߜM/]膩8O; ďÓoq9FçB}c_LZu}OXR$YmqI޾qKduԁ;P7nz~!, y^߸c´@V[-5 ZJ~fJU,? -2բ(EN܁R>y ɟ5W y\8d]73b2~sn:c-38h6tf J0•<"ہGqsOxGw;r: #ioA.DYA :o Axh^ˠ_ɤ 7^|p*+pڴߖ@ްb+L>|Ì bgWҀA~/fq?rVkC{TKWJp̃@sKɝcS, T\o@3Jɭ'ۦ% h‡XgNnzO X4)^Zkڕ=fv37 ]ujV'\@_~[eH "^̉9@W(z%1111FE S!2}{uVkCi?*ȸT-VVaR~.T1aevl݁R>&Hf;p79="WB$~"gFHWDŊ+}벌ģ۷ʼ|}HrŧVkCg w1ye[zz[vURVʍNށN|8S>tpysYӧ8~[ فAZCp\\{V šf pjmh&XRu Jlrڼo-S_׸Maiuav&}sy;&##_?4Z3@ H^RH߽riof O pjmc,_)?(tعhm@+Tj }0Q @3l2gpyzyR}r V򺇐Z]`m:zQVk?;_z$ V:ym +QB! ||;&}vu9Iۗ+!D:6P `e_ }j6dY m HHpݥsAAAAAqqqq*;iv jIΘNz3`Ԧ>w.i'Y"z4@:m{KH0e:V'BNw̞cdՔ4 dE'><]}ŏzKV0W{ZlL`YOαl7WKr$+mu4'5M ߐ~f,HsYTA/A#\Ɛl'F۬ GEyYWlLsW1WKNMs!YAQ  d-Nfǣ :ՒonǏj&= 6K߷3(e?ESȃ.4QwYY +v592Yʶ(ԛ¸(K_CV+!k9*YSUw9y7dgeQO ML{xӔAwa]~(.9>(iNrd ] F7Ւs?Q3E='VjH'aSs5lzǓ(t30> 獽X[)3@~ 32KB\>y[ uEKwPSEoȳ# }6YvRh.Q'_nM[.S } vdcPz.W¥mL(j7` 4jrѸTc('9FJdEТF6S(kͶL\. 6Yә,`piyuK)]OFQrџ$g H2lN 3F؃FfP(;}TA#]^{3py܁-LK?{.9%5%/<4,,,H۱qٓ`wՐ9=!BB, hz#̇39x3njQTRnIVnУ>>BلrdRrʿ)uz Bqvہ!yN!"4=;T&q% e5C˩~.O<&o.U67^Deu~#+R&sNIձEYJ] ~k?ZR=E ql ~Gw]A5S.֬<5cِj2W"+Z,c۷C"ܹ {ݔ#\Ns;ck?1<_كd@!D*bw)r\9"!˖)v_BЭE%R=iaYBѠMd %\.]KyloEֳ6YykG>!pBN~;uyXzp5T5xK_`1k>TݨzthvaX j C3 9 9jV R)s6<0Z>m>PSETϵ 2~lN 噠.o)CONVj-8}~ eQ#\LJIA`IUD_P+{53W/0D>//S([)A$E\J +O|LlIwN"".Y刈)"*NpXDV؁IXNm6ClAXHjDVTiUr)C kOC|Tt!uDY&$+7RNsX$DYpEvY>&3WS'bH+qn#+JJȣBMQYg gddM&Nd7*38dXG1yTHn?uraq'\)kqeMR`I{WxdyE|LyTHu~Lx`GȚ\Ã%P\v|Lҹ~ύIN6XEU\/k@Vo)z$Q'+<P9YNyT82.:MHOyi òϤďMd*!*=t8U z}g9a8yT>):ްK6xU"mmRQi8TlN'.xI,7oa\ zHT0HΑw54@hWveJ`F|70ƳY~r?hYU3)9wn 7TI=^^寤9J*pF2 Y&yP-L jtm |2VM3 .i;ACmYMa<*?# 09*~,XFLURM[{_^H} н'׮ݭz|#UU5Y4*Z:Zrm|I j,! E{n&5Ct{rْ`jT'mS-/WfJo~RőQPvgk.}N*>Pd<OltǏ9rJa&fjv%!j rAVjd()#D#G]Ii4/p"EJ/T'jU!2&$%&'&%%%eG,Sܭgޓ@Tti!NNIINII  +vG{PL^vpg#]L@Aj`ky|x,#Ƽ0 *{ ]Y9rgS3c]Y9gf5v}d;1F\Ke L3*|˂ L075< m2|d[ Zi: ͢gՄ,wRxf)AXR3&ZCeNM#+0S#9hҚ lxdf0g?H\Ҽ$qrd29ՓiCZAt r;i M[ >ٲ%m5bY"5oټDr!WR+ {с?6r>ؗ;v?2!+Ppa+1g76Ii?Wkа/4 d!*T, G7m>I ˲n_aJn2k?G0+djm(w6PΝ"L B;r+v;P F8~|fTreS[ΧtZ i6 Rct7k>[@ *7ͽxcGy_a6ko_ [L2$# G=r0RUr/\-  ?!22ϟ!%yxq~b  "333#3=ńN_/NVඤn .@u|??3YFӯ#0bXRb J-( `XS?(ZXRڵ k@ E$j`e(XZN52>RV8F BVH@!+DQJP"p{&CQ Kp֠HjaE amܾom*iŰWYZX̫ -J-,`R K:C 9YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY @Vd@Vd@Vd@Vd@V + + + + +YYYY @Ef6eE OOLLLJBEEEE%'%%%%9oJ#+ NMJLJL:x.Y ,\`xHhphHH"7++3+3J¥˗.8CW//***_??LLJLLif/;zoͼvPRR~>/rٳs5YE^i~֒L*qahOݱ].{tk߮S0IsVN vg`U-wKBE9qB[T#_cN^ tA k*lyym5׹M}O`~MTw}fM%jyg]+?ט?0H]z;_&+;=5kѲ_7ʂ^K[jw]̜s-smyAETC!77Ds%͛:#EyǍ]4٧1-FU5t};P/ ~^[פpЂܳO-zkzzvT0^P?{ۡF{Ԉj{,Ľ}_?0"ͯPCB!*DK7SרPg =za@sߕ mz.ڳxw5IDAT_; 7#/A*=rʀ(>{tfԱ^*]S񢭃=y[y<0ӳв 5dAOv4pm%G4pKs(7Ыtﮧ_='~z`_[kgʉBU|Cn!7q!5{x |f`T6>6`i3*6*>,ˇOљzF O\'6B{y[>P B# *<`iEF=ag3*6䑅Nh_/Ux^UY +;$մj|l4[$ojvh1+_>6}w̅apƝ mVkIZ=qGy']Cjzi%/hȟЩU#&٬~sÛOS+oF꺁}y|/_u_;2,4Jn MVi#gFjifCW@/r}wES$H;}wVr^w]˝8stUkx)g?˃hR`:_KxI: yWO˅>&s3; VE=€w $H<Eatا>s ]kڟa38F/xB/[Gv&LucWgx>;cy+ i73:{6Ϙu>kgK^)*P쫖 n*};`eu{POo2ty ףƏ9i+4˲񪚗sX=hnVh4k+ĨM,瀿s7P_Kn=tvWp>hV?o4\ 4zԛb祡Ý06۱@%lxnW"S/WKVjg@O<)>D~>n iu)-nÝ~ gB͌\{Z+G /;ug "u86L_Ф_y5<SeLrжxJݟ(-?=>üP⍒uww_}ԩ3)iiiJ?(?'n_rIv&5"i6uT;k.T?4l>uP[?;_BR. (zx M06)3}ؘɇї_r?_Ʋ6wjV{I#Vjį-SK͐?\q97lLK#_*/53$Kyڜ7`AO-}BƮ*/Oc529:*D$zd"#+>heКjx%n"yq @>7^*Vȝrя=.?N&NAOs{j% _ۺ0k#J^]>UvͿ~$;xN!SYڰUI}$yWΙ;PeP1<{0>Y'm+=tϗF2x̏*n/Y%wK_|ehqڽWFGqi<|%ޡ9p1Ͱ$?8Lϥ+XwοD3'wvyqU>wueum5.SqB^c[?#FVkaF.vbwmޣxN6Sw]p)m?(Otulw1j/&딋%MwϽ'$vjX᎜+wwSp'wڐ?~QF^nxVzgǥf֤ Bvu+g;DÍ\o$&QyyO.SR8"ˋpֶIv"Z]r'i!=d|foΕ23:+wHkTyǟ)?~_ ?N;mU!&wN>U2l]ՊZ쒊ם\" ^r}q.ɝmaf_6) dWٓ%@OeK.1޵ah_#._'`pgm2rnl>AxNuýٯ]u$Z=~ #oF^IQ~q@n|繁Bz~82 B!,kS 1U;vT>ǐ%_Sr9>U=hFOvnc鞺PvNBuZ<ZO624'?ǺʏQi_k2[%%!4Iյ$?|l_Uus5;}KgS3w^qU}KIƼ)/IUqu ._kT%+Ȧ}\d`qO6.+Bթ_ $x!Ql'2GKFHgd9i9fHŨUizVuף>)5&8A4 !H8ȝ9ˆb<ʋ/Knl弬 a&>1ݯ!l"2O|r8}6 @_R4ͯ6 >}ROlԖ,WuGɁkc8$!6ѭW]=$q`5%9ӽae3,+{ˍVh=Cq󔗹W*uk7B$׿,JpRw'Bq|*戏qZvۧt4[yyC<{zgy $rN}.+f/BnƝ#%\ wo u6IQ1oK|] !ȸP5υZuLT^SE8AudW9,u ݰp]iwgakJKw&$\5zmPVܵa6@ˇ ).=aPg?5Vh$mSͶl@ed2KMabq6.,i)G -3,^FayEi6Т1 5 sʳ\ݦt/_H?0USHrH`3 yQ"4aYQLS_U1+L?/o&<s8 񟊋/ 6\|ZY얺V>;Y_X#+&W\|p\)FWSB>q PXzښ* c K,,jV^>qcFOQXzF= lPbQa]kI&g qhB! bJf>伬 ^t}'_E ˙ϸ;xH&<:mWgCd5YY90+zNxO$M 7j}:Y ҒMq Cm M\uA*\pϞ'\mKzH"G$Td e9c3gK9IVS:s,6'?{euW͙ 輏\ 4Oyq [HfpFZY>eE#\B!p?+\8qhVun[ˬYou^ZV,'>YߵD Rr.yG;n, hQaZe+fdN]:3B^7y+ 5emy qS7P7.}甶Y!{r\Ŷ$eMsƥ}$ u@VPd5J]TYO՚z%g on(Pÿo}2I 1UvJ|FOuɞ^c&R~aGwGi}$YAǛ$+F E|1KYYA~˙R_MRAino| 4+7ǺIZ4Źh6Hc߼4-6w8j7SrS>g7na}%qZuG ,INzf1++2 o7r$Wbo߮XźoOZ-엑ʙg7:_#yV~z"+!V^w;Y*;QyLaRVǵ(J.U?i%rBBBM}k]ߙ{<Tɜu?g:y}Z[W+:wHBX%ɞ$&|^ʞIFdN\]Icj`1w+)ܿ5^y7\c,mNvo>lYrsBک;WvXhH^uI%T# ΜqmX){ ng:8'Rv9V˗*A62#t}~}Ȳϵ5 +H|kbVqzE ˳Bsݛ%gq>㘝J~l D6ߕ4HFdb}5+hvTT<@"߿n|Bds|M *Z@:GBmURt_0F2Y{Y׬GE|B/k{o/jcB| z|Hgl(Ei`dyUzVA֧q3hvazvi3mO)鴁RةA/Ͽ爴r%RIێ&>~zv>;6dW{s}ѡǩN1̤ ;z^Gmt&fLyQx6vs8ώ+hF>4!n~(Y>&o;ʨMi4uhd->N)]5ԬƗBٲ/|=BvaV )Bd³^OYe_ZHgힽC]|Z/m#kU;\f5Y1NxԞe cbwpVPR߾V Ys5_zpkR;ˏ [S՗H?}5Sޯ"*.^&s5]gԯOΦrZ;Cfgt o6yejw Y; ZI6o穑f'S5SѦ޼o=i1{U=1&?dg-TʧKpä1*TpsOosT4]w?s Wz~!m6$ۋp1+:wKD/zInۼS]|Iw~΢zMp;x…BjѬG;׸Y%8!?Q#E<8(ă|oۨƩ~]7B96?x?G97`2P'\~Fo%B<{es"BcvT_lE*/];^crpV5`Jqe?Ss(=|9u( ֵВ Grnnoicsn_{bBBbHttt1s2+,%ugS#xW//wRK\X~n}YdY@z!+h.nXijv[U/ko?HIF ja*#+h.bA-y.P{~!+hNiٛ7)n?ye:5%1+UrRc;uQ1H@w}$ fS$ݴ~U]ΞUMꪕ鳽y"(ST取Lv?V S>W.Vݟ;\ W09+1J|PN6H/T_9uKu5Þ\ I!(GVB=O>geY!Ze?8Yaß Xʒ^.-M~ ;vswۯjP5az9n( jOzY7uH&d f$a˨^_3-[{~0|X3t-46z<7w nnݚ-^AmV`\pʎHG1Md_Vw8$>daWAWK'H,8:SJ 3O U WZx66X,D/랯\I\`ɸBQrrV[k즌ds-yzE2)+\t'Nb(i*>ksOA5Iz^$m0K.ܞmP$'rnWٍ\NBJͤHfeKq`Io+.?oѲ&ɝxU=Io2dS׍dŒKsqOHW)J C9 v]mٵbos.Md +8<+l,⪪@t@d}ԕݧrdEҕ!5I-"`nowWYZPzVk[(9"Rn^[Rp@2H[kׇjqk˸| قk9'jedMִn`?wŔdsAe_VPt._e[H$ΣHff; h<6^wIZq]qYaY.iBԲ+vo,yZnsxVMEd=% مsR)OW S`rC9.ɜΚ?Gr7^)췼M"d.{)rJb;z$iͣ vHyVxFb'NdM~SfI{.(~>Z#6  zy j c3+BǡW)o}_G0RI >^0}+V8#o;ӫ1u-,.m?s&xv)K֮Y}]zQ#}?+/lIjvՋ>fMBku ϷT4v$]Vov8ݹէݜ.ٜ33h׿M3udY!Z<}SMfؠq*R"^: :r˖-[ :M/9*_9-n&66[V'?s 6<*K~ Kq1{ kx"%Ǫ]c =JKKҪU֙|ZSf:ey7$>7K=BV9I,v}VH'f޶őG}O}R~D"ɾ\XP4)@~`7W,ϨqܺJ]QBNd`T,[l1h: Kxω>h6]jLV|ٕ~ Ñ΅ᢖ! jU}/[񧈯 G"!>|S z^~= KnEpHVf͈ڇ[pnm5)Aom\!=]qY}U^ɻ\ ȈgE6)R=SǵmT4 EτGUY-+gžۋm{8%t?OؘNaYmӤgT8 y==lq3Y!aXX4Қ {i1*&Λx}4Ѳr'+ÖFՒjvCS<> qCi¦IQw!fE7 e)9ˢh }<5>CW=8JQ4-swQ?#,+3KY!mVݼt˷cҡwXj{_:>oEM>IpF}D A}|DfCN@劰j"e_o]gG8Evz UHSAyz0k^-^al⒬شbUʎy}»W޾K=Sӌ՘6e\Qe7hW ?>䇵pec֔; {P1 TaO}_, A#wѮ~leMea-t:V]q۶\q^ʑ=y|n^.W:nOǨo۰aʮ}6vmw\sK!y \c9+5s,U l[Umpxsk ^Q_о݂U´X7a.UȎ=k붟Qٝf&]2:[:CXjU)9{uL;Ӌ˦m7<~d|èK=ruYUa*[K_=rs6ڥsL[Wreyvg}?mKL//Zn..>`^8h,ZԢ2NVؠP *j܀{}  + + + + + + + + + + + + + +  + + + + + + + + + + + + + +  + _J+F*UY^-h"ܳC-RF PU1ҝvA3C+B ޜdY_xP )/Vn$h}eXIfMM*V^(if,,+?*%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ColorSpace1ItEXtexif:ExifOffset102sB) tEXtexif:PhotometricInterpretation2+tEXtexif:PixelXDimension2091sԵtEXtexif:PixelYDimension16742IENDB`pappl-1.4.9/testsuite/portrait-color.jpg000066400000000000000000006065401476704353100204010ustar00rootroot00000000000000JFIF,,ExifMM*V^(ifUUUU+8Photoshop 3.08BIM8BIM%ُ B~C  C +"  :SAvqo]Avqo]Avqo]Avqo]Avqo]Avqo]]'f"ƂSSSSSSSSSSSSSSSSSSSSSSSS>I*#rZB)j ZB)j ZB)j ZB)j ZB)j ZB)j S,jO]-BtsI'KG4-tsI'KG4-tsI'KG4-tsI'KG4-tsI'KG4-tsI'KG4-ؤdEo~MHt;r TeUE^NhYQ c[lmڛ+ SčNc.!{2_-MY\E_nT[QUD慝25Vݝo8Ht;r TeUE^NhYQ c[lmڛ+ SčNc.!{2_-MY\E_nT[QUD慝25Vݝo8Ht;r TeUE^NhYQ c[lmڛ+ SčNc.!{2_-MY\E_nT[QUD慝25Vݝo8Ht;r TeUE^NhYQ c[lmڛ+ SƤYEkn]BdBQI΀|U6f5su}ݽM6f1θ,؜x2QmEWvtόf|S2ܼ{5Vݝo8 pf?MvXčNc.!{27כL=8PCjC 蠇pTeUrU=̖X`>G~ 6bSA U{Q9gaGL)} rJókU1JM{})m`l9C@MvXčNc.!{2x,7(4YHs< rʜ-_(J@!ƻܐ@+岩1 עrk}zնQmo7:!/@욀=>JY:Il`GU{Q9gaGLmayH}JókU1JM{})m`$g=3MvXčNc.!{2`_]6^(ydX F$T9WABRx&ֆʦ,Ʈn@~G W[rJaP]qbCc)ډ ; :dPі 2+[[1Vƶ*۳6WA lh惲$n:vv ِWB>RdV;U!\ρ pr|U6f5su}N^ ^l 6Kp}0L5jmoȇπ*-sBŽ>A5[J!G@FX7VZ6oJD8[?5Vݝo8&P`D/4q#qӷ˰^̀ =~%zW]4^_ذrTeUVҋhR>jѨQmEWvt@ "Q f&pR)mUgjloN#k!I8 eHt;r 扶U[T6"=prmAɷY&=f:g-_-MY\E_nX] @WJj z괒CIPÍ6:טBP j*г@Aߞ fp*3E*8ډ ; :d+}E/=S-mRjLkm;Se{}JqX-=7;qܻ둯/|J+˟ "+Ȱ,2 ]90@+岩1[ YoU_{o_wa!E^NhYQ :2<ƶ*۳6WAn]Bd[*lډ ; :dLkm;Se{}JqX8یv/f@+岩1 j*г@ƶ*۳6WAn]Bd[*lډ ; :dLkm;Se{}JqX8یv/f@+岩1 j*г@ƶ*۳6WAn]Bd[*lډ ; :dLkm;Se{}JqX8یv/f@+岩1 j*г@ƶ*۳6WAn]Bd[*lډ ; :dLkm;Sd7O}X:>zp:>9p:>9p:>9p:>9p:>9p:>9Gn\F)C8泥#Δk:R9H泥#Δk:R9H泥#Δk:R9H泥#Δk:R9H泥#Δk:R9H泥#Δk:R9H&c#k H"(j B(j B(j B(j B(j B(j Cy}UKxDj kx* kx* kx* kx* kx* kx)6.c'ܯbxؚrG uˀq piPQ REwv$^ ͗dMT )]'݉ k\W_Jr+Y$R?fNl% h ONWGէ=ޝŧ ŧ ŧ ŧ ŧ ŧl]_ ͗dMd3 =j91x_Px@@SSOWX0\ReǎwҺ884(rMQKa3?15=a1P9KwiO,)z`3Ow0@/eRrUslQ2 'z?Ld#dy&U=| *>[ 9^۱5u uˀ8^$ؿ،I$: C*WW_J<ޚyCnduJzqc* h'Ij0o* ^g= t$sБe2Hr/Ц+~͐zJ&AT >y\?ne)w`uXnj\s[mExjEofoh^(@SSOWX0\3ݏX^󯢚 ǫ@/AD`1<[=Q x|@'Ij o5^;Uw [mߪtxb| !9L@"Ky\wXœ4.QzXըfĄ͚nuT.FT )]'݉ k\)SyeP~~x]M;BF=_N * #CJY^ΛP Hg#gJ8㭛7G[HydK֠YnhXr\lUOhUٲ/ID*Nn6'='Kt iR,tEhD_6Yҋ6A|uU }jrbjfw5v_ {Igd^ ?W#/'䮯nԩj~4O6ïLON%ntT r+Y$R ?۔%9F~aٲ/ID*|9K7 "ĵoZ+f[ Xr9@SSOWX0\ro5d_j,x$=Wzs7Z ǫ@/AD`8c~V|[ׅjh#]-{̫+ /:KB9KwiO,)z锂")p$0sJl96Bse(S@~i|P-k-+..0D0)f&F۩;S;ڴP av+؞;v&6ap @~789zTF5;' oaѥ`9юZZlnq^]um_p'Ij9'c-Iv^UQXWQ0 ͗dMI⽳Sm}>{?x#X:~4NViŏ[,) @SSOWX0\74+X^~0½=5P/\i4J6-(|Hvq{m޻i$0zTFs Κ.,=HU g L:˄ӱu]pY-ݤWwag3f`CREwv$^̛OR/@,4x  ͗dMоhK 7m&ؠz[HS.6T )]'݉ k\LNi+M[ 9 [^ڮ$B-Kz*ފ-Kz*ފ-Kz*ފ-Kz*ފ-Kz*ފ-Kz*ފka)VEuBibXb.)bXb.)bXb.)bXb.)bXb.)bXb.9[Ƨ[((b/X((b/X((b/X((b/X((b/X((b/X珻p~,hȝ\Z1WUţqh\Z1WUţqh\Z1WUţqh\Z1WUţqh\Z1WUţqh\Z1WUţqhDJTn;=9w߳Iw7/e KMv缝MSVRk(;=؉P;%sNd&ө+D)5”~ezWUlD@vAwGDd]9'F2vgaiJ?dC6"T ;n }#}wA~bi; ` MpY^sǡy*~]>~srQ; d4`{ьXZu0h&R,C͈ۿH.zH_@9{(_Xk=Nl-:B\)GWuu^fJmߤ~Ͻ$q߯ܽNH/,M5tc'a6~VLZ!IK+x:3b%B{RB49s gޒ8x^ׄ>?gX8sGZ=5!? wA~bix}G=ax=\keRtc'a6~VL疰u)1y+sI5BI~(ƫkx1`=r*bJ\{j $D MpY^sǡy*(|a? akqzoyHm߿>'m7r><;yS^-qq,uqs 2[=U|=QYYsF̪r>n^'{$&O #:ypz_<}uom e= me %jۿH.zH_@6B|LoBYg eıs1l;&"O'jY|dΨuGwA~bi e# ?W7x}J]ZU l:ypz U m,\lmIU~\as5K{ьXZu0lFv> 'f_M`!V^J'[\mϯ!'“W~(jukVZ!IK+x:3b%B z׻v%bb:8+M2[De[3^c'C^mߤ~Ͻ$q߯Usn-,sZT:ckq,uqs V-R!ۭ ^Zlo@Kd]O:n@9{(_XkΩW\Jwˇ?`@*5y$<Ά˜SL:u@sֶ\Ou,9'F2vgaiCPDgIp}mʟ14lmr>d';fӐYo~r Q%wmb,[Gpß0eK.YU@sֶ\Ou,9'F2vgai],]t#3)+sI|eL)M$v4I^ݡc_Z!IK+x:3b%BxW@q95 4zdeޠx3֎Awz~]>~\K\lw:՞, 8%Ȧ] Tzakio,swA~biZ@61-t2Fa [hk[.'; `.R ck$GP?xka;,XeSbTZ!IK+x:3b%Bu>x_Te ݓilΏW:;n }#})sp2:u9 9EAq,}p~5D9'-~esHwA~biZ@61-t2Fa [hk[.'; `.R ck$M5cl]鐟h&R,C͈+/`׻+}+fg/i>78 Z;n }#})sp2:u9??=fO~4:e&2÷ޢVT}iܽNH/,M5T܆"Ŵw\9^5Z m>\keRtc'a6~VLAJ_a32lmr>5>aj%54!mç.4 eVEϦ?3Zq=԰缝MSEtuҗ`̧[\mϯ!'ȪX 6ԫknP2+D)5”~ezWUlD@"t~Ӿx篃㢤Kr l8mߤ~Ͻ$q߯]7XfB&N``ǀ>ك=Aun_COs0wA~bi1^.uGׁѕg)P c'~KF 2pp缝MSQhQU^Z*CU^Zn_WUyhE^ZWAӉCZ!IK+x:3b%Bs gޒ8n^'{$&y:1?+ N Q%w~srQ; d4`{ьXZu0h&R,C͈ۿH.zH_@9{(_Xk=Nl-:B\)GG|侮*FL2ʌS*1L2ʌS*1L2ʌS*1L2ʌS*1L2ʌS*1L2ʌS*"GceML1MMMMMMMMMMMMMMMMMMMMMMMMM9"R=Kf$ebFYf$ebFYf$ebFYf$ebFYf$ebFYf$ebFYS D2߆̖55555555555555555555555#٩~ϖT#.wa]dM\^Nd}݅hD15 9eXE>b=c1lI9ˋ:ь=b>Lh@1Uvǰlf4Mc)7['9q{@":1v5Dz{TV|ɕc\0 ƀile&d./|_'F2vn"Buϐ2}W|1U 6MlN\րCQSYY&U]p *c63ɱ|ٻ c =*k+>@sʱ]|Wl{c@462ust/;_{7asZ {!GMeg|V>u>y?riIwۋBcQ'+c`h2 {$;8@#2Oqwɱd {<}c { 1Dz}_'F2vn>~|/9m?<|^?e;Ayښ|3bq~?a@@j5XS|:Ao$ؠ+c`h>B1UK8>|}Pw&<_06NfNHBySnT. xlI9ˋ:Bm5I.$IOmeQ 4r?Etc'kf.k@u֎bcwkN@sʱ?`S0J|@Px^h =N g/? Vm^vrEH.]cf*+c`h fL}=7sZ!|}Pw&<_0mnFBʁܩ(\462usttjRQx@R)%ۤI <45Ro? .6rfFOَD=b>Lh@ F'=qFL6&WnJg?0  ǀ۵Gw!yU+5U6&@>b=c1 Dl'/鿚N5Tɏ S33l&HpٚessaySnT. xlI9ˋ:jXtiP)?ʹ>z9wRKI6@`Rx]8spd!N\րV3wժQ9ZKSX*!nFQďJ}~[Gus$Dz{TV|ɕc\ ðPs' 5|'Ziջt09 ǀd8j.R"fYH@dnHp]\0 ƀz,'%Gh ?~M@ G5Tɏ|DwU5q밳?8RY(G=VNaBǀɱYہ,kcb쵷gR)%ۤI lUԸD|th{Մ郞y e|yukk$܀ь,EQ8Y{O! o[6XYoԪ)TeI 9>DZ.=L>~rQ0a ʀDz{TV|ɕc\3<13,_jiy!e[sv*츯?RQw@Cwa]:o*iB<6Lx&`?]JlЩ,zS' S%ܩ(\462ust7f]Z R)%ۤI O"Do~":V7X#Y":1v5Z{PTA V o[6EwQ\%M4=>Plԭҟӿ 1^''}жOpCQSYY&U]p Ϫ`!}; ID/;u: z:--%Cxp<_..ԁwa]:o*iB<6Lx&d^ rH?t]؛*@*zH Wւܸile&d./|nn&:RKI6@` &6y>dr濾Zuf>]\r[V ̓[/;_{7asZ uD`liKE[y_tKu>7LT"]>Klu CQSYY&U]p Ϫ`!};z<ozuFKe@1Uvǰlf4EvM! ꃹ1qZ 3&燽bile&d./|nn&:RKI6@`"ycNta-/;_{7asZ uD`liWZEUmT7&PQ@F=*!a-P` {!GMeg|V>u 3>\Px^h =2Cw!VȦg iK9uL}% zn#WMͶ0 ƀi!^|}Pw&<_6ܢB}=]rCQI ׆~q[!vcBcdM\^ݚMvuj>/Hnm$'>/Fv'Eb9 i?udtg,$N!(@":1v5Z{PTA V o[6teViGbu*^vURX9?NfcJŵQvw&Dz{TV|ɕc\3<13,_jiײJK> zwu|Wv<\ *c63t"T;yzyPmAܘM|?_yl)ySnT. xlI9ˋ:[IέGMtm`GdcN\րhmBQ*9X*!nFDp=@Erԁ\SKrwUCQSYY&U]p H ]#ydC|\&Yj"{sut'-)d|Ӥ'LAwa]-,Tѧ9X 'PmFG*&>puɱb("ju؊M=At˄;)^/GT)oy `Etc'kf.k@'zH`ڒ1I%7Ao|Ac]0U0Ja)̀CQSYY&U]p *c63ɱ|ٻ c =*k+>@sʱ]|Wl{c@462ust/;_{7asZ {!GMeg|V>u+c`h&RnNr΀Etc'kf.k@!d(Xϓ*.wa]dM\^Nd}݅hD15 9eXE>b=c1lI9ˋ:ь=b>Lh@1Uvǰlf4Mc)7['9q{@":1v5Dz{TV|ɕc\0 ƀile&d./|_'F2vn"Bulԫ]ққққққққққққққққққққққққ}_ ҒMRRRRRRRRRRRRRRRRRRRRRRRRۛ+)s>4S~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#~h#508ŷrB۽*TOt%% =VfFn(tlm֖>VKWfY!mހ*{'3t#7V^:6ԶKKA+jꥫn,@ = ImO}U /dj[nuRٷH[wJI'*Յ5-RGںjۋ$-Op$BR[@`fnf‹F@۩}ih#em]TvmŒR{)-I 7B3uaE샣` KmԾ2Z6 nS =Д$YAѰ@_ZZ[WU-]qdzTJKh{6;˚a'vz 7B3uaE샣`]];?@۩}ih#=#dHg~"$2Z6 n]M-Ʃ r1~*:;^JkYӾ!VRv e؁b]v OҤA/{8IpJI'Ac}g1&vFˀ| #]u E_٤1q- 7B3uaE샣`z;']3cUVۊ :# Xε?g00vWڻLW/S,5$m֖>&b(wL! iCQ th}@'BTںjۋ$- aֿW@S~w`C:MjXX_*|bС'Yg pOp$BR[@`1H ZobF@Lz|զNtk|y!AIm 7B3uaE샣`f6[Юx cT~68Ka?qhtknC]hpk@5-RG7Rs;ƩMj cq'%7]0[WU-]qdz aB鱲9l 1%ߴc32VKL'`6d = ImO}"N//^c=x\N>Q2S柲XڻHnZfnxqY?_a ;jagnfnf‹F'>eFncQB/psT~684"ϏDB}-s_rcώlnso3_ZZJg Y1f\9WoJ; RF`A܍s8[WU-]qdz?Vl]WU>3:Xp7]D0)h;fdYYB!-s#_[6*{' ';Q6s=hBT@u`1Q m%0-jk#.u49LtkAb@۩}ih#˩`uKV[t k)ѫήsF#em]TvmŒV }еRl~f@0y&{3s9{l^<R{)-IԠD&F.l- ߮t!}+hE.\yiJVfFn(tlfHps_VZn*?`XI]G`ZN8^|~48ϝj[n cfفQҲ^z1{B9.K@ O͞sD ͸B۽ աo@aS~w` }EZW]Xm%=ܛ%*{' PJ tBobF@LX_6 BO\Uj {Nz?cjכl93t#7V^:6vޤ[~u89-G, ' r=xVokH*Z`ԶKKAVʟx:z4}+C)/6 Ϡ2Z6 n+VZߩYMA߶?m3 08E:&wOp$BR[@`}yAM]([h)1T0 TLp7WX@AvV&BTVfFn(tlfHps_VZn*?`X@s-b=L͔Ν+OԶKKAM)yWvGg@I:s:NH[WU-]qdzBt-oԀ,ƣb }TJKh{B/5(1 Q m%0AaA%[s9jLhO^6 +j{eU /dYoR-:Ֆۊɼx>%H4sS W7q@۩}ih# 筧vӝAur!Pcͮq <ʕ&K$0zsGuRٷH[wZ-BH >olMD֭B<*%A*{' PJ tBobF@L?c箨c{j(b~VfFn(tlfHps_VZn*?`X@Kօ_^u9iO/D8 z5-RG' Y-(Ik6-2Z6 n F!5aYɨmO721xZ³Ȥ&Rې R{)-I+ ]tct-؁ߒ4KCo^Dڧ?UF)egVfFn(tl:XW@Uu8O+y^ W'&m֖>/t#@9:#@G^~z x:gEPuRٷH[wJI'*Յ5-RGںjۋ$-Op$BR[@`fnf‹F@۩}ih#em]TvmŒR{)-I 7B3uaE샣` KmԾ2Z6 nS =Д$YAѰ@_ZZ[WU-]qdzTJKh{ЌXQ{ Ru/-| ͸B۽*TOt%% =VfFn(tlm֖>VKWfY!mހ*{'3t#7V^:6ԶKKA+b,RWE fWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEWEٹ ."PEFfPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE׷h~HF3rB7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7<`d4456P0@ 3$%1!"#2&ppU㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::f::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮:-6j+z㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::㣮::#fqqqqqqqqqqqqqqqqqqqqqqqqqqp{:7bDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbDv$AؑbD;%)Ι"LDzr.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.:r.e В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В !В k,D kL0vkL0vkL0vkL0vkL0vkL0vkL0vkL0vkL0vkL0vkL0vkL0v.]DΡhu9#:u˻`u D/!ηt^IӮ]/SZ'$iyHuNr%yz=B9'KrGtw+<7Z^C=n輓\^^gPNIwE:J0{:rO ֗g[/$.oW-xn${:y'Nw{LΡhu9#:u˻`u D/!ηt^IӮ]/SZ'$iyHuNr%yz=B9'KrGtw+<7Z^C=n輓\^^gPNIwE:J0{:rO ֗g[/$.oW-YN~e,xUu=R޸LY*&[d7`TL wp&J)dzԆmdȔ;,PLkDji<}gNw{QR&Vm+H_M\o/SZ'P QEX]/!馥V0wil&IyO3a*dwEȜbbk2l(H?(8U% e :u˻{P?yz=B=U%2}iyI8ra$^RޡwE _Ĵ%Xqəu˻ї]//SZ'w9݊Σޞu=&3Zo4"nK*n&LuDN h's2vmU0x I"+nB?j7܈|Oۉ\5 PEB*PT("A PEB*P>;D$c m_ւT& P?y?Ṽ̝mػy I)\jm߂9Cm*_vm[tG .Ee;~%%3+ҌJ/P? =GVdoQA@YGK?9Cm*_vmv8LQGᚌbx=E7^SunfNN^S={&Dj9'rʱ ޣq46ߢYdfoO=#- ṧbUV;:Y+ PXm4gQtL3A80~f,?\`Go C:3'kzw0RpFB.\,sn&fKl%([l %([lvQ);] YezO='|e7k# 0DIF ›l*juGx|w{nޑRQ=9L #4i6hmjտn+#龷;DP&7y?V|X%N5{:NId%mչ;[Ҽ.F5 sn&NDT`Jj/龷;Dul6VR˟/Թe`>juG?گ71{V|I]!^CL,h^s2vzg_e8nL$JXs#!Xv8bUnz&ńř>q46߳x_JsGch'CrE셷şdx#=DrSzw]Ҽ&htWVdoIgtʑaKjdS&L3T٢3ϙK6zm~ɐIlh$z=3ċ[D4gA8ڙ=K.^]>s2v7FUv8\FqKۉV`%usOPB8$#R6EQӋZ?nzNm~[-cw]Om{L- f * "QBK=YQP?zCkS['4Éy/lы6_sn& ݝtTKLY'5.L)>RY fKl$ΥeJ5{:W n7VdoJ,XJ7>㰨91o鐽'6hmZ\n+뾷;DbKX"~;NmozW][BK mcxpӉSKW̝^bWXAqL`sJ@N JjYezNm~ڔ s#lx42H='$d.8F%Tܫ-6EP?x'-%w,%;5h?zsp:lSIN麷3'kzSJ5!}"j(nvRof/zs4lr% nm~+qn+P[zO;Ry߉a߶T6-<)AB|jYd6zW]ҼM=O̝N4!D76hmPIčt6:?mVMD3 a(j vޝjuG%)FK=w[ޣMb:4}ᚄAOsn&/[%+/=5krUQM:9Y"R5{:QC pUL:WhYv;Dv.uJ0u͒.\Yչ;[6L*w^dB;vB \vy*P%깷Cm6۲}chP`YK:IkdȒ^V5{:Nܓq46$m @΢s2v$M >;DP?$̝9CmO9+.:3'krNm|sNJ5{:Nܓq46$m @΢s2v$M >;DP?$̝9CmO9+.:3'krNm|sNJ5{:Nܓq46$m @΢s2v$M >;DP?$̝9CmO9+.:3'krNm|sNJ5{:Nܓq46$m @΢s2v$M >;DP?$̝9CmO9+mw*0«s *0«s *0«s *0«s *0«s *0«s *0«s *0«s *0«s *0«s *0«s *0«s *0t&^[+*q *gBq *gBq *gBq *gBq *gBq *gBq *gBq *gBq *gBq *gBq *gBq *gBq &͙>drҪPtT+] WEB*PtT+] WEB*PtT+] WEB*PtT+] WEB*PtT+] WEB*PtT+] WEB*P']IDdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwőG|YdwŐd٣-F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F”o Q)F^Lꭶ!JI)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&छn I)&Y,eu m =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm =(УBm ='NSE(E8)QN"qSE(E8)QN"qSE(E8)QN"qSE(E8)QN"qSE(E8)QN"qSE(E8)QN"qSE%w$v$k}v=u7N䗵?mrO'xΦܒۜ\gI?$;^;spk>C;G{:rKGnrN q'gh<gStI{[hI3$ {n/km85~{O|=Mӹ%m9'\t3~Iw$v$k}v=u7N䗵?mrO'xΦܒۜ\gI?$;^;spk>C;G{:rKGnrN q'gh<gStI{[hI3$ {n/km85~{O|=Mӽc*nr ]q۞P^ԗIq&xc.T&oX ~b\hgm?mz1 QaM3i&K}v6T6|3 PdĉZj-Sp6T||=MӽEljT\*Vڎ8A3!Ws>"};mCbYxRVH"pk:׆8igghB(,$f &|Lɴd^{:zndPm"͑>I>۞eien.NGwfuEQŁ2ѝ4Te#q7^;sw~2$N391};n)lVR3KVF i+&[eۂ9S< qoGqEqa 1GZb27c'!Nq7)xݖ}vrg(,ح>jN,mnM*e( l+ C$x{:z.( d&~ l:Hť۞7jłm㊆[r2.ݾ},޿sA3"?mx KgI^h,TVdays_bŒmӊ[MRWolnM>C;GVd$N35)4=_GHo|=Mӽ,?iC||=Mӽ#%e zT`ߕ~۞jXݾW𼨿akм7c^nigghŏVV$$4jy[{n(Xu3d\bId)=8YeR yܿkm^F ˗n?̏cw273סyln5O|ϽӋ,,H.p1n6{n!h(&cwE?zkGnzcvw$b.7o?|3Nj&O~X]\AsL1[mͅxΦnF1nޚ۞jXݾsPqgTИ[N5~/?-WvZo?qc%eb%Ν0c`dM$,^{:{e9^rqi$ڨ/km^F l*a VufZfSqlEskм7c^nigghŏU<gStN7r}+VkX5x7ʕ2t,(ޢ۞jXݾDRc%o$mlك1-pk^~[x7S3t3A RR=O+\gBݎky7e{?z^F{n骵W?}rD-Ȅsh+wH0>۞or?\3EKw%Ze/lMD-f3ũtRM)+kxNd]WGUkoN<.WGUt37y{4s*QD%T7L8RUE(QD%TQ*UJUE(QD&<gStI{[hI3$ {n/km85~{O|=Mӹ%m9'\t3~Iw$v$k}v=u7N䗵?mrO'xΦܒۜ\gI?$;^;spk>C;G{:rKGnrN q'gh<gStI{[hI3$ {n/km85~{O|=Mӹ%m9'\t3~Iw$v$k}v=u7N䗵?mrO'xΦܒۜ\gI?$;^;spk>C;Gn/n[&]hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8hV1Z8h4n(r+(r+(r+(r+(r+(r+(r+(r+(r+(r+(r+(r+(wt +@t +@t +@t +@t +@t +@t +@t +@t +@t +@t +@t +@t)$&\RગT*U. pUK\RગT*U. pUK\RગT*U. pUK\RગT*U. pUK\RગT*U. pUK\RગT*U. pUK\RJoG))g2<0gKe#O%7#䔳IŘ쏧rJY $~HvGMH9%,Gqfl${;#rq#8t_=S~9NIK8Y{:[/y)i$@N,=-gd}<ߴSR dy'`ΖG>JoG))g2<0gKe錎Ȋ 1Givx5~쏧Ѱl*l|ќc2H=Kΐ ͕4:CC4:CC4:CC4:CC4:CB-"q#"|VtGLdG*l!rGMMGc%hLj 9bNl2%|ۓV[2XQ<~*) nI%L3{;#˗2te@W|:ڝKٞYiһ%* /c'@%[ȥ@ ,SA. /7+(LWo60EeYe |,=-#[2 #ܟ"":p ]Mi &KT!쏧̔qOl_HK4U 7ٞYiC'4e7kıy1bOl2|o7+mN/LI #yZϑŘVDD&'!P9KجgɎߍBUC{;#nM?+jvDl,ߴSʆ4k7 oc'XռY  ً狗RGlȔ! ^Vqfl)a>,Gn72d0,^xO[2lɱ*\m wi7 odSZ-$A: VK^SO#&YM3.T_NK?ٞYiɳG"3n_o :WFPC5R d|̘5egxnWǑL^ИRu7[eb;.tY{:[/0v/iτɐʁa$U^TZ{;#.{Gu[&Ĭ/Eі эl,ߴSк|7Ŀ𫣒[$mCȥ@er XĒ,7s8t_`_ۓ۟6&B  hvyOgd}>hZg"vIӆ goG)]>kXbɖ[dV-P!eN7BE,Gл,7]?|# p~L9-9:ύŘmܟ4gĿىG֓SOP(^kygd}>hlr+&]Lexgd}>hE2&;^N ?#~s p-bI2H\Iitoc'*fq3%xƥ@er or> #vpx$0gKe<"l'$|g>B|oW [kY"uq#]gg:'/ |Em0O0gKe> ,KI'ҔR|ɦ|M}g{;#.{Gu|RK, ?a3&p8~g8(K) -&w7#.5d $PSYu6LY3 ,l8R d} y_1EH&a0 5,T(ғ񼳖FkAnOmd'-B#uExȻUXeߣa]J#ygd}>hhnofyfr汽*fћL]?cq&je!\rex+%yB8nWwK_f' P.v8.nؐةS12 P.)Dqflx'6tE:\1} _6H= c{?gqxԉpOp)B8nW&tӛk_8`qflx'ʵª)8vG\6goG)]>k)~l%-Prg2>fqܯ5HQ7CI8c)yY{:[/6^hP1% 9K+|%̙&2V± / hămI!&PQM6|1쏧aҚ?o69A Ik?Ch~me.~9OA ڝQ?j7F{>).@BYa[lO-#zjȰ#IV,8R d}{~o1% ~CA OՄJ^%lBs V,;V,8t_=S~9NIK8Y{:[/y)i$@N,=-gd}<ߴSR dy'`ΖG>JoG))g2<0gKe#O%7#䔳IŘ쏧rJY $~HvGMH9%,Gqfl${;#rq#8t_=S~9NIK8Y{:[/y)i$@N,=-gd}<ߴSR dy'`ΖG>JoG))g2<0gKe#O%7#䔳IŘ쏧rJY $~HvGMH9%,GqfȬ Ơ6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*blgMpCLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLdLd)JSv;ݧVfSyNISRE%-A#M5>TtSTԑtIKPHy%O='5$]/R4IsSOgI9%MIK䔵7\SyNISRE%-A#M5>TtSTԑtIKPHy%O='5$]/R4IsSOgI9%MIK䔵7\SyNISRE%-A#M5>TtSTԑtIKPHy%O='5$]/R4IsSOgI9%MIK䔵7\SyNISRE%-A#M5>TtSTԑtIKPHy%O='5$]/R4IsSOgI9%MIK&PD"&ʙj o(5DijrW5?@SFu^Xe%e~|wp>;|wkO>OSREUdݣ4:A2d(\'\aU@Ϳ-K(DlȬj ogWdi*To0H~p݄ZIYeف'lS+!".j~RL߹C&)\raMc$ i&,۵P`+n᪹cVZ<%%+.NQҾ~#GjH_d%@[+>YiJJfx.d`)j ob&c|/++&itY3%KjD\&B{m-t5DW7Tkw/K2\"syO*dg ߷҂+ 5$]/pr2U (ke~.C1-BeSH;oȥ$iR$ n4"C񼬯łd%E\mHӖɖ*L @\(Te *oOl-gI< ϙmi_VE!`,R BHX),,AS#"VE|j.SXaS5 'Lt )$H! 貌.oy7Ȅ<9!!e~ DbSQ. Rp?m2sr|Dn:J/A"$"Ԕw3^CЬlאcl#08K%bzhU{'&SXOdz5%ˎljI'LŵyGzB y"׿آ+pmt2qke~, "U`Rɿ" iUT7]_WzV%MO$aJZvdV-5Oem?,_,"h)+1&.yYlVŽ E̡*5$L IR"d†|7?ŧ%6Umi^EiQIt$<._Ip.9"BH:WrONk-*fT'Kј ;fG,R)j oՖ(Kש,me~i/'şlk 9mcxl\L ^7:ɯp%8-Li|.Bo,@ΓxȬ[I:zjY)'}S֕Z;А ZTԑt"WM2FMNK.u}ص1/38\gMVrx"GKPH|g7>Q4mn!ve~mm7e8>smʓ\8a+Z]G8ї7gZ? 3qw{:O)0^I2d//.kJN'qmU5$]/MY%gIbRtʛ6Dq̎lX"j/R4%e* ave~i27F/𻴨S\;jF؀~\8tGc~22|򞃗VŵxNXD'a|.:sX#`L&'7ej ovo++aROIeAxm4v9r7o6g*$p,u:gߔ_>%oSyOA˫bҼN?//̩"~5[+>Y>-NqN$Δb_KPH} yY_ NM=)L1f6&U%0ɏsSQT -Vf7n;7\t)<ձmi^F (^lL-"<ʚ.:sXuXS͛2tK%7s%Gz ;#ȥ$iqŘ$͖%cysj~RQy~7ڑ2d1c~0(c}Γz][֕u5a:-l I4baC Zߗ*pc)OO HE-A#M.3e~MǑhSV2l08@җ67?W|k10[,D7x2Ln67+_Xߔ~SyOA˫bҼfA&Y13 d>uMIK9Z_ŰŶg(a?6Nj ovo++lx05aN.܏v+MM:u$#^<3N3;ug7[ +?{:O)9ul[ZWw%(z .:sXL_8ef-XԵ7л\7I44Q0q(vo"NN:u$%T)B8lY-juͯ&ژX}='-+mCbOżKO5$]/tke~&S0%V>5-A#M.3e|r11cxjgȹ*c Icx`شq6X4[\˲T(DɉOgI=.kJqJ'U5$]/tke~r̶)Y n-Pa%l6nqwKPH} yY_Jd)&BK)8yڔ+QΚfwsS"mLQODH~jQY?K5Gf,u t.eaU\m:rιNNaVcL7Ŀa?1<ձmi_5qZĿ"~5[+&2MNȢ[mQSmSn8MM56㏄ێ>Sn8MM56㏄ێ>Sn8MM56㏄ێ>Sn8MM56㏄ێ>Sn8MM56㏄ێ>Sn8MM56㏄ێ>S?:LwE_"޾nSvQ6A;Wa_Ne)oRWA}Hw[ݷ{}N Uzӭxn=Ծ'tU?_R*=}]e7mj_t*/vv^2q/ ~OԊ_Wzu/M}Gڗ' 8 D(21C4bR#7Mryn"ޱ?NEp c^BnQGU:,e)l8*i, ,A{}N KZ% WQrh̢}A7`d Ta@Q=R(W8(0 <,r*=}]oi.gDBn^Qʬu TqiK pEj v^2*b>Rs?`mKwE_]~;PgzJ.yX~Z8ugQquM,ݗ [t{3%9;,R*=}]vH=rkmޱb;:0mgAAJ;,d"^XjBnN xn$n(NcDgRs?`mKwE_t5pmP  4ǗM:/`j~5*&%)bWaYM=O )(R)xnʔ4R gEA>P*6I:Lcq/ ~OXE'DRz.wԶa &Pqi7]v)v?)E`cQ9ˑ3j&bԻ'S<,9ZIH 't'[ݶ9Q7[d2lYȮ^jRs?`mKwE_eE`4Q_"%/{r0L9v0.@4i+ϴ>*D;ghGAL3˨:ݗS ց/xTT38y/*)94VP;*t<#J D^JFQBXmKwE_E B35(hfD>0g KD/?Htr7Y$Uzj((_.9fT/˭,Ne)l1*M3;lQ6A;D~w mC”;9yY<;W}|-"h釃*& f _WzylE˥o~NA|CYO4J"]aT8.\߿,Ne)l+"U $=m9ŷ4kӟZ-uI!4Y䩨0Gڗ' _nwAo,R*=}]sU'EBNa#04J`Y*I;;XImXnSvcQJRs?`mKwE_I 9v,ہbmb`ر[p0lX6,Vɧ#Dx8,R*=}]RpGU2!Co:Y) -OYnSvUH-AÁFIj_t*/vv^2q/ ~OԊ_Wzu/M}Gڗ' E]}:ݗmKwE_"޾nSvQ6A;Wa_Ne)oRWA}Hw[ݷ{}N Uzӭxn=dKMOލ?;z4Oލ?;z4Oލ?;z4Oލ?;z4Oލ?;z4Oލ?;z45D0F[Gkn }#V>۫xŸHmռaOv0;[uoS)[Gkn }#V>۫xŸHmռaOv0;[uoS)[Gkn }#V>۫xŸHmռaOv0;[uoS)[GkD#dP\Dxy'jtO嫑}?GIZ'jtO嫑}?GIZ'jtO嫑}?GIZ'jtO嫑}?GIZ'jtO嫑}?GIZ'jtO嫑}?GIZ'h#?y5|-^WoM[Z y]5mj|*jvTյkWSV֯+¦^WoM[Z y]5mj|*jvTյkWSV֯+¦^WoM[Z y]5mj|*jvTյkWSV֯+¦^WoM[Z+^^W,mj`ϫkW}[ZX3rV֯+ y\gյ>^W,mj`ϫkW}[ZX3rV֯+ y\gյ>^W,mj`ϫkW}[ZPx{okD5Bv7}OZP kW>jCp']^(n Avx.֯7}OZP kW>jCp']^(n Avx.֯7}OZP kW>jCp']^(n Avx.֯7}ҖV:9𘘧` Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ ͠Z\ &s"0r۹iva8]N-kn}۹iva8]N-kn}۹iva8]N-kn}۹iva8]N-kn}۹iva8]N-kn}۹iva8]N-kn}۹iv!7b,f(5=˾Q𾨣q]r7.Rosd.Gu^TTnK32ݾmG'Qܻ 7){}QRe/po˯ʟv1-FOr|/(W\ EK锽?.*}Frx=˾Q𾨣q]r7.Rosd.Gu^TTnK32ݾmG'Qܻ 7){}QRe/po˯ʟv1-FOr|,głt1E?&)FE딽6Bk{ 5Br;,&b(RFEK锽6cCw@duS@6&dDØYI>@@ 3 Frx=˾QI>I ~BCRUjq (to8\^IH6F/plJE=ET=Tٶs@d5 YǔrҢx䴙^*QE@rz)H"Z> hw;<EK锽IIVl܁zMIgHZ>I8yGԨv{ApM0E5 3H'?!y/8J7LF]~Tx)RyG wpOɢGiK먦n& =z;tt LM8/KJ(8ELmmG'Qܻ qD=sƔC=A@8[;B(검~N~Y 0N $weyu Tȩl0بq]r;C5&z~SSl cSE0I"PD+)O4Xs JTIav@Po`ŤjP' 98iQZNˏ=t-Re/pwDfy{Ql:drԔ9)ZB\K8i ]$7sxӢS){l_>KH&YOX:Y4,S7`Rrz*XOgag]4ϔLt ̉ښ/^:4ҋCwsAQw6#Ũ]򏅆]4@44e͝xQ(&0ƕ xp<)ن׍**>*(W\A8 rOhGnФ}e|GDDV{$3]D+)@|qJPD|gɭq0m^NY1J38=r0gr= ۰5.R}#\R&x* m4.j6;]oTVk}=ЧB!e0{a?>~M L0+81\UN?:Qf⩔˯ʟw}&uM|,D&iA)T F"۟-lDiK먦n CpvT~Nf59Ƿ}#nb9)+9B)GBgE3 t@zV9&8"iYؿ7QF/pl4>@ܴ)}uGEPH'0ӜxTcRYN<6 sd.G70E^&MX jTYNܛsҖ@|,Z`*(W\ 'Ңxĝ@`hiKG!x<$ 8|)4 ͜wP Tp#}EK锽ЪwOt7%I7e*,U2uSd O?hҗQL݁ME ZJdA>a2>(a1-FOr|,P P:ݦ<, @C/kIzk?>NTA$ :(W\ 'Ңxl"'aҕt.|I812zD RR#1Ug2yTnK ?WxiQZC{B[CvRS){l_>@ܴ)}uΩ4qT *aqcUM#M#M#p[, #4sd.GA~;w\9J%SfWx]cu^h}qx*!]N@K1< Fӵ^Y0UNQ ooi (rKb1Wmtp26\4~Ң[i*N[А|TB :oBARu ބ I+zV$'PH>*N[А|TB :oBARu ބ I+zV$'PH>*N[А|TB :oBARu ބw| $E1Bn.;O]v*TpU>v6!ت}RmCTۀbKScn.;O]v*TpU>v6!ت}RmCTۀbKScn.;O]v*TpU>v6!ت}RmCTۀbKScn.udzDT0r i0 Z`'65kIO@lj֓խ&=ZLzcVƭi0 Z`'65kIO@lj֓խ&=ZLzcVƭi0 Z`'65kIO@lj֓խ&=ZLzcVƭi0 ; <֚X 羗}Bm澤6{QX 羗}Bm澤6{QX 羗}Bm澤6{QX 羗}Bm澤6{QX 羗}Bm澤6{QX 羗}Bm澤6{QX 羗}Bm澤6{QX 簀5@SDvS t2+ k \,SX&BmOi{aj`i0vAzLw򏎨O=Qg^vtsMT&iLI˨ dӺ\'c0S} zh$mr~.Lݖwa;$& O~wG &kL8Yeqi8{X7c|XN'UJjRS?n3)Su n̬z_?0S:Ka<:x`ɖb6G`m-S܇=JeeTPt3uތn@E(p!mBቺ ?MQX ߒT,W&;aZSiLNO=M`w'o(q#7I!~&na0 O~iN3;PYz6҈aͿYĦ5S03N) /H`( ?o6}FK$-<;" `6nRS?m''SH 7)3 ~Y<Rc4..gN6QX xy[)w>^p)8sZgcja߯ɛ“߼nXƘ']jNdiD}m氿ѤD3ҚIFKqgʾ<|ݔ&~R9)I5@/+;9,̑gg3ATc5'ӻ X-J>:Ka<OO Rq29FR@mt1%S[Z)ȱ5Ba!(a rf찺{fVoTj38&%(IӀ11}Bm氿Ѥ,RZ KpRDӔ}%e_>nRS?m)OT~pQggR"@M0)JWҒj9~IҏO=œiL | [\4A3€۾_7e݅'x4Mz4=o\i;Kqgʾ<|ݔ&~Q|'0g-NP#3qJ>:Ka<OO Rq2( kԵ3=I &@G-)WNJKT'5eTL<3vX]=R{INzH#7΋8{{2fwRo5ލ't<D=+bx;/ %$Tj` 7[=U%83ӌ J +1#1T:&YCϯf]S*{cJQ{ '')EҙFY*RQ`hw^n~.LݖOv҈aaI%=ޔ#03Gn>lWǏ$N;+|ZgU?P&䙓Ã|}Pd7x/ݷ+.nt!we!}Pd7|/Yusw_ xT3/Y m!}J˨7}zn_T/oY V]GCW7 Cw}zn_R=| Bz@gv^ȧsgdQS8{ CwUp%`eez>|`O_h@щHo<[-%# wCBok tzA| A-[ Hi @LJw3/Y NĪ6?JȂUSLot87ӕR|>h+N/4*ISQ"/gzS@r(- "I&oCJZ?SƘLJҠYusw_ x拓g `txҒEx liH曻%f%nk^#g0}c㪕w=TskͿznoȿ<懏7,?aEĔy-PLPn@4$QdwCƔ|aWI7m)+s]RohASiP 䝌p={,3/Y ||aWI7m)+s]Ro#b(n@,e*xEP;fԈ$TSPC;)HiQQ+S0iTU MUSXNy)O-D(n">ɂR/x 6 CwE T-}]=8T@0tY+  R"L ,a_fd vDaΎE""KE Yusw_ xeUxJJ+G*#iP 9pꇍwe!a]/R7'Ң;Va<:HIJXcW7g<*TKK)A'<ٴq3-ni_v޲(ݥRmK 7Au37 .a.9 9=nZQ5G T6ǔv*IUb*OgYusw_ xeUxJJ/v@ Z(NӼuԶaH0-7b]vݗ_]wJ@w|#ITr E/ TNP!<5 J$wBF-B n*_Wxiюo$}b&V G&L䓲EAR˨7}x99{ai-r+w%)ǠeL ^ VIЪ8:<0y&  Cwޕ970Z!-GT@0T'5E(۰g ##AQG!fP5@J7Um!aP"gp0hBn/Š0DΥtDDJ۷3S;N,@&?>֬,G mhENcTDnƫ _9}Їޯ|}Pd7x/ݷ+.nt!we!}Pd7|/Yusw_ xT3/Y m!}J˨7}zn_T/oY V]GCW7 Cw}zn_R=| Bz@gv^ CwQ7xo\iD]OS;n-[wQl8ۺaV[:6qձuÎulmEcn-[wQl8ۺaV[:6qձuÎulmEcn-[wQl8ۺaV[:6qձuÎulmEcn-[{uT˻c mEձ}V_[w|`ulmEձ}V_[w|`ulmEձ}V_[w|`ulmEձ}V_[w|`ulmEձ}V_[w|`ulmEձ}V_[w|`ulmEձEL&5ŒcW 3\(0:5p8ŒcW 3\(0:5p8ŒcW 3\(0:5p8ŒcW 3\(0:5p8ŒcW 3\(0:5p8ŒcW 3\(0:5p8Œc<e 9oQ  q05@S !1234AQR6Tab"Pr#B$%CsDcE?¢P0d5L^CY1y d5L^CY1y d5L^CY1y d5L^CY1y d5L^CY1y d5L^CY1y d4b6a,'g+Yx|(r'g+Yx|(r'g+Yx|(r'g+Yx|(r'g+Yx|(r'g+Yx|(r'tq#y֥ r5_&XK9|b/[],@kkMmtɭ r5_&XK9|b/[],@kkMmtɭ r5_&XK9|b/[],@kkMmtɭ r4$yEMĴRy%Hf¥G W ; i¥JͅK+C6"Zw)7ӅKM! Wl*E^(.Rn% *C6, = ThQ8\KN-7Tl*Y^zzУpI*Zo$ T(3aR*Gxrq-8TIRexQf¤UB&Zn`Q`d/#z瓙rU=ny%Hf*̑DhdHgS:!tWkICD}`OTUUB&ZnP1G+;&Lj"RiZo$ )7%ݔH ~M"4$ QIQQ&?PrWkM΄X5kZ_^AsW ; iA"`iGeU)DqgHPLR+B˱Z,&.Ry%HfI(ߣ?BIHL3yzN:ŀ@3LO`kJpM@|)exQfH81 7;Pb+sv"Zw)7r)pg~G(EZo$ iCg֕ dK+C5(T ZNu*1hhUr0d_´+sv"Zw)7uE(`!vYL1qgǍ5S)r*C5UL l g)Fu?2@ ]rϙnRsę҉6֎>|ԳneFbC"D#<)ǭ hQ8\KMХ0@#mG_ s*C5@mzAt:` c(3\Tg`j]9OADIv~#垆W {Kҷ7h.r*Gxrq-72DfBAџm^1-Ii3\_B}$N(_C賬}LPЈIZYBʂ6 , = 7CQOd&Wt"ѱzc~|Xjsq(ei5!.*Q͜ E'HօMĴ܀'BtfĎZo$ iAT7RtܥG$5rfhQ8\KM M>gN4$4c^mc^mc^mz9)Ry%HfK:A3aRJ#G{UpvUQ+%/CG8Twz W;ڮ&ªy])/`p}z=£ϻLTp7uUHakqED7-'AoQ> / zH50T{I{ut/&5,&,?s3ē#j.r;t{#qoV<͐[Տ8dc,X6AoV<͐[Տ8dUdsC}ނf;^M!f-". BI+܍W ړw\(ONVΨҒ%{P ldZ !a TF6sWu(9}z=5uM G}wPrK I #ws JI+98B$r4w\7jMrz_y? Ҧ.pL"!>pq5x25x24sJ$8fX@yCs=tI/dv'>%AOI(pEj]GXi}z=ae$!O (HQ9C>=<#r>A3\p\ 3*tEqڞnOj+KR"y& p7uʢM Tg-hMf|ymijz&nc E(`rX@xZ;'iezR^ܤ wO˯7!E #ITG҃鄤 ! qg 6YĢ:4/CG7Z}!O6=~~Hz;]|.qg&k+C;<Tp|sI1Ib WL?ҖRxdnRJ#G{Upv*]'ÍP fiL"ZSI"nv[xwX*0ܪy])/`nN)8ȩ5p~;< _sCuX=W)}z=781>cbK#s>A3\'po*} G6+"eiCztSDop7umpgՖg)%4 IhbN)M>ql֪Ә%9T{I{rLӔJĞ̩qjQí6;֫ (-"rסۣctAI=ucМrX9.g&kCʇ)ezn_L4Ju> ' I0U܊SP'iIOG\.RJ#G{Upvj;b!XE!@ r=tIxpAP(y֋8GsV u8+UPDIwyܥvFS7Hi]y|.g&kM"$33º~ e2:Z@7D6?POZ C$r4w\7jMrBsC ?6CM78s[ Jcsͤ_TaD/kuhTR ʪRNqDc =uQ+% ʤ:p8\(>Iv6JqB)MpBJ wg8V`~+Y0딾ӟHvF&hLn<:ULs Ͳ7H5O=I(YBvHT;DNb@_L3&-#qVCLl}I^hjnԛ$V!nA0jSD-TJE|ឍQ+% Ur 3%M0ЌpÌ5] USs7)}z= \+UF19N q}wRJTz w1kHӆ;)]Ks~l4AG7)%{;Rn>,mQ :Ub4LeԀwLV-A3aRJ#G{UpvUQ+%/CG8Twz W;ڮ&ªy])/`p}z=£ϻLTp7vT{I{K}ނf¤FIWJK*_^ndp6$r4w\7jM݅UR^R;t{#G}w%{;Rn*Ғ סۣ*;ͅI+܍Uܠ]<.`p@}%oKb+z\;I[؀JޗVv >ñ.p@}%oKb+z\;I[؀JޗVv >ñ.p@}%oKb+z\;I[؀JޗVv >ñ.p@}%awIR ީu 7]qE \Qrz\ީu 7]qE \Qrz\ީu 7]qE \Qrz\ީu 7]qE \Qrz\ީu 7]qE \Qrz\ީu 7]qE \Qrz\ީu 3 CLma'XA9$NI2y5LMa'XA9$NI2y5LMa'XA9$NI2y5LMa'XA9$NI2y5LMa'XA9$NI2y5LMa'XA9$NI2y5LMa'9IIX]mn=fLMk3|Q#9׎JН4?Qb:6JE݆tM6f򄏥uMiK%"cY4# qgyDc՞݊bC2L%иTݍF'*_eU1͢0ׁobyz"EZ#:6kw\$?K>?*:H3<<S 5~'>zH1CtTRSl$Yŝ#u 9B9b1M8NMiK%h3g:ZGBw'mp7T@!]igr[صi u.QMmz 1}Ϫwcf0 yI)li Ϟbz2>4B؜k85RҗjKPY=F(qWhҔ54ܝ́ɽjU]3cH.j-Ze\4:D}4{{ h gOŝȑ4`#<٫HN|LTvx)a8ڹMiK%MHYE (I€Ρb iJ:;m I\cՠ[غ 1}q٫HN|"U6 zrMiK%s|%Br eSH'8=^<~'mp7w| {SZB&/Y25i ϟPD*(34`;Ii/4/!@wSo8RItENZ!%kиTݍE;MZoa!p,a͚]uȑE`5,jJs<<qSmJ].N+>× ' x73 :%F m I\cՠ[غ 1}q٫HN|XNq ;% ~N5"n ӒnNIZ9&hTU7f6W.ԗ)5>(!=کMiK% wq+Y!,iFAdWmp kݍEџe@Hlj^]4oP;%&L_C_˫ʢ3Ŭ-Ljrn)gb}k qan) )v¤j01}υJmJ]0mp7*L_CRҗjL)h\*Mƣ ,Tp4ړ v {¤?K>) )v¤j01}υJmJ]0mp7*L_CRy*PLTC֤{H'3ZOf# jGA?9ԏ|~s5kR= ֤{H'3ZOf# jGA?9ԏ|~s5kR= ֤{H'3ZOf# jGA?9ԏ|~s5kR= ֤{2I wGiE iؿ˗ɭ;r5b._&_֝|ӱ/Zv/kN\Miؿ˗ɭ;r5b._&_֝|ӱ/Zv/kN\Miؿ˗ɭ;r5b._&_֝|ӱ/Zv/kN\Miؿ˗ɠrqGgaŞ}yfsP5#q> k0>k\G1Z9|`}CָcsP5#q> k0>k\G1Z9|`}CָcsP5#q> k0>k\G1Z9|`}CָcsP4: wi,C}}}}}}}}}}}}}}}}}}}}}}}}}wUy:O9gQ@wU'OTUN/KT;XT Rz =zݠªq~]¤累4¥^jnUIS'=yN-oTu^ªO~7h0_l09+*vk}~R{AATaIi^iSK[=(W;ߧ * *N{JJ*ZEF߅T=PnaU8o}.aRsWTaR/Op5J7Uew 0"ƔB2̚.5'OTd[O'ϱ16EqL{vclN6خclim8mqN:9+*v"` K3j;HY wA]4 k}}TK!SŢe 8lVjшnNxP`hPDA!3(:#^*_\4q~PbS%GD]c~pjO~7h.\:SA/4~Q=Dލ?puy]J2 -.%QϢCH֨S K{v)c--9`#iC)^JZw.hkՅ_hsvx;rsWT\% w'Tg7pţ Z>|㨔' |)+ Aש-z{Q@wmPJ#9MqS*a9qb;Yt 3-)b~ ЪCF`g'Zkk}M(K|^\Jo@w%ccDgWzSJw&Yʥo T FZ,xi; |WD㫖z{Q@w#ZVG->#h*A1@f&/s vL)Y6>84#vbh8ɯ=zݠKGay7 " ly+8~d9]CQt*VvuU*mbǎe23NgW7uWD E!@ TE i1{f/.iS:᭰o^03Jv="I,RJȂ7xO~7h5qZ9D0Fb# HbUgN+]4S2ʌ qic)Ԋv LbSe7>iڭ˹` 9TV{%aTZŜwH@XR 3tC^^+0V%UL"@ #n&% A>!9*@Q1W'=yN֮5SwyB?:9`%D٫T'ϜkE޴UVGOx;BaM1M/8U510 x4R;DS":!z{Q@we=xC3j#[ol^TB;<^s3A ]IƨSGxת q <\?E*)64I܊]l5[wǾEoZ]]N/K_z=S;ΗK5壒D2D>!=c"pSXw'vTq<~:9+*v5Bf ZQW״N֩DpsQшV\t^m:_l.5L*{!Zw.hk8M-rΰtdS ҖB9?:Te2gϲՠ/1@zRsWT\j}Uyz5Vh0_v3N(b4L&)q)]tzɇ$kHB&6PT~!CZdaK[=(W;2!ZL^KhN`聡SHuӛgyq P')I_ (N+v5EMDòo N]RɆfw@L`mUIƨSGx֕r.r -iHf4KZҐi!/j'xCi;D SꞹŜs֛v鞎cm'TaqeW 3tCZ"Cds4 =539>ZCv4OҞ B8qa֚ЈiSvOdD.j累4ڸ ͘+T'Ϝkx8 ´"H~ Ç|#/aDSLj+Q 와'PtqIפuU-oTu^{=i1{fTR,-"d_y;>zߧ Qo=ZWڎU~{TV{%aqeW 3tCZ*U#R€%xi4U'=yNƨW^lZ>|^WIrD9vYge1Q!$Y}{,P[=(W;/Y@3쵭CHEE=Մ'~p׍s%052-q<.gjCq1&h|!4.n'OTMaoz\DmvoPĜԻE"\bW&PnIq___X;u8o}.\bZ6VQq@څx>tB~= R(qsO<*O LgPLjGwW2pҼҧjN/:!CPtvɠx 1ԩԩ#aM9: k}~R{AATaIi^iSK[=(W;ߧ * *N{JJ*ZEF߅T=PnaU8o}.aRsWTaR/Op5J7U*v {v Ҽҧk z{Q@wU'OTUN/KT;XT Rz =zݠªq~]¤累4¥^jnUIS'=yN-oIDp<;nX+i29JLR)cnX+i29JLR)cnX+i29JLR)cnX+i29JLR)cnX+i29JLR)cnX+i29JLR)cnX+B_3'K(e5?tZ¡n|SS]j oչO;sSMwE *Vυ5?tZ¡n|SS]j oչT,UJ;qyۚjk-@\#ґ~spD/Jiҕ IHfTuB{VVչc5nXoM[9[VVչcǜuP>{,gDam4m >,Y]EK`Z#uuo;sSsڪk-@j4#k2tICX+@>~m[?tZGmL ^[W ߫sB7+rDTgKG놭njnc?tZGmLi ]gSVdVqքorV0D\ 2|L% tPkhDPR6\ڷU5.2/=i=Q!Q~UCslC܌&ȋ;;$ʑ6 ߫sB7+Fлjp:!uZ܂:U5.2/=i=Q!QTHs/ST;ٸ5 ߫sB7+F;jЧAIͰ,8NAx"a9f>ib5-(v?TtZGjeA#,}gǣ.>Ȳi.ȴ@83an|=hF%cpZ% 26L$TQ@9o;sSs=MwE t]S,cs  k.Y9v Wˆֹr(x4:C,U&9.P>{ %'0XcD>1p&vw pyۚjk-@aP>|)njuC7𧝹֦ ߫sžvZPT3~ϟ yۚjk-@aP>|)njuC7𧝹֦ ߫sžvWèik-㇩#؎8zb8k-㇩#؎8zb8k-㇩#؎8zb8k-㇩#؎8zb8k-㇩#؎8zb8k-㇩#؎8zb8k-㇩|PuŽlo[vOr|?tCj#P~'H9>F5Or|?tCj#P~'H9>F5Or|?tCj#P~'H9>F5Or|?tCj#P~'H9>F5Or|?tCj#P~'H9>F5Or|?tCj#P~'H9>F5Or|?tB4ILSDVFgKqI8Rq)8CN!'ⓈqI8Rq)8CN!'ⓈqI8Rq)8CN!'ⓈqI8Rq)8CN!'ⓈqI8Rq)8CN!'ⓈqI8Rq)8CN!'ⓈqI8X*[(R;vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI!'o$vHI I%%S`z$*aUeI#>$g!"HBD#9 Fr$$IH3$g!"HBD#9 Fr$$IH3$g!"HBD#9 Fr$$IH3$g!"HBD#9 Fr$$IH3$g!"HBD#9 Fr$$IH3$g!"HBD#9 Fr$$IH3$g!"HBD*aKDmz%Kb#vJяk{<7-Bo>r[8L{EN(VΌ{[l߿TM!`~؈*qCҶtc0fmiFSfyn[78l3H|p"0Pgk43rٿ~-fC/EDZT;YlǵaN!ot7 9z-&="?+gF= ܶoߪq {ٿfl0?qDa8i[:1ogf~S[64^g b#vJяk{<7-Bo>r[8L{EN(VΌ{[l߿TM!`~؈*qCҶtc0fmiFSfyn[78l3H|p"0Pgk43rٿ~-fC/EDZT;YlǵaN!ot7 9z-&="?+gF= ܶoߪq {ٿfl0?qDa8is% 5ݥ%.wJ;hl S$c0m[%LMߪLy I??=g樁qu'cTGí+pB)*fbaֽGB.SV3XVHFcG<ѡۇHEL[*n>nC/G:86V:㕐+!CVBk4˅75DZT;Yk:ə(OY})غGL|hVOяk{<79C@4n/KU_w+ &Н䤩q +|T¢sșNy&5~S[<̙axMu?LT2o㯩YS#0n]ޯ@EB˚fiL+Z(&="?.l$0{9 `iWrUm iz1ogf3Sf ҮĂlAc33ܕD J/$.sW8"SeGҤvO]G) H:F]4^s^y^:V/sXL{EN(\*lE?DIm']B|ތ{[Bbi"%GEZ IVr)OJ"1S)OZJ/ "IyDS,|N!ot4E0{d>8+,]4^CwHJ*%Z/.iP:E$D&i笙XB}etr.%UN:th&="?.hC*b_vcGQU+yǵa (gM&])baR_@۟d[=tq=$<ʦ!BE,N!otO¾~aWXs UfU(,д3rX^_I,sG 9z9GH?ʱlﮢ_+氘"0Pgk4(D81=NJgIk:DEdQJ9FJo|SVP!7ynsFIhea Pto8v'SֵY3;&ucyT?~-kLs)2oFx>rsp2Of2*p Oje|`~؈*qCjiԒвd{F?Ft6(̈́@PMIN}DJ&pQs2XC>oF= n=Kj'̫!\z$zBqEd<aStG 9z9eڶYAq/G{a5N8di{vO"e:%k b#vK=C(*xYuvr!a?2~LUYآXC>oF= jt9d:I؅Eٚ4~S[rsU8ԥ%LmZ.ο~ؤUKZ4]q Ue_w5DZT;Y( a43s\/ʳtx$ %6^2wz|Gߪq {4CS5$$Re}CW"4WZzĪQsW 9z9(EY;/x'^X; 7tOW%ʥ*DED!Ue_w5DZT;Y( a43s %=fV}*WYIU6!ne/ߪq {3xLҕGRSQU dp4Ft>rsED]IV yUgLL)ZΑtCoV؅}YDWa0?qDa8is+,⬡XC>oF= E[E}8.9ңXt._p/6~S[<ٛ_' 8M}k>rs5f}AQ;̣jzŧ?h-\7uK}FSf82*fC/G2 ;vtP.a9@(w]Ô 7.MOE>jS.GN*E*uI2p"0Pgk4qVP!7yns6cm+RϠTKu\N!ot8[;1-%ELq>LAhPջ|TL+Ih 459]G4!󗣝BӬ_+氘"0Pgk4qVP!7yns:fBpw:W\CZΙ4!󗣝BӬ_+氘"0Pgk4qVP!7yns:fBlA:uXRNnrsCF-hKj*":{$cG|FR?`2߂[4iuXL{EN(VΌ{[l߿TM!`~؈*qCҶtc0fmiFSfyn[78l3H|p"0Pgk43rٿ~-fC/EDZT;YlǵaN!ot7 9z-&="?+gF= ܶoߪq {ٿfl0?qDa8i[:1ogf~S[64^g b#vJяk{<7-Bo>r[8L{EN(VΌ{[l߿TM!`~؈*qCҶtc0fmiFSfyn[78l3H|p"0Pgk43rٿ~-fC/EDZT;YlǵaN!ot7 9z-&="?+gF= ܶoߪq {ٿfl0?qDa8i[:1ogf~S[64^g aRNTZ)(AR"'H"/X刾z,E9b/^}Xr_|c"/X刾z,E9b/^}Xr_|c"/X刾z,E9b/^}Xr_|c"/X刾z,E9b/^}Xr_|c"/X刾z,E9b/^}Xr_|c"/X刾z,E9b/^}Xr_|c"/X\DB\3Rfgb$]c^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF8הc^Q=yF J:f`j%!;J2!,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳrK1,w,ıܳ7}'dǑuoB̈r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(r(?(_[M5>FSGReU4j95լrj1XcVɨƭcQZ&MF5kj95լrj1XcVɨƭcQZ&MF5kj95լrj1XcVɨƭcQZ&MF5kj95լrj1XcVɨƭcQZ&MF5kj95լrj1XcVɨƭcQZ&MF5kj95լrj1XcVɨƭcQZ&MF5kj95լQXd4CJz`AE%\IfvlhcVƭcэZ'OF5kj9=լrz1XcVƭcэZ'OF5kj9=լrz1XcVƭcэZ'OF5kj9=լrz1XcVƭcэZ'OF5kj9=լrz1XcVƭcэZ'OF5kj9=լrz1XcVƭcэZ'OF5kj9=լrz1XcVƭb>5 Iu(BEEB%\MfȐc=bBgHQ 1!F3$(ząXc=bBgHQ 1!F3$(ząXc=bBgHQ 1!F3$(ząXc=bBgHQ 1!F3$(ząXc=bBgHQ 1!F3$(ząXc=bBgHQ 1!F3$(ząXc=b" MTRIvyxrq(tč8X4=bFgHӌq#N3$izč8X4=bFgHӌq#N3$izč8X4=bFgHӌq#N3$izč8X4=bFgHӌq#N3$izč8X4=bFgHӌq#N3$izč8X4=bFgHӌq#N3$izč8X 747L]؈*qk4P;gD798lZv"0@+gE}>?iw8 v.y>j[8l"8J_j{8?iw8 v.y>j[8l"8J_j{8?iw8 v.y>j[8l"8J_j{8?iw8 v.y>j[8l"8J_j{8 wx wx wx wx wx wx wZԼ߬\.y>jss(eN!I>QˉHmX{u-$40I.o ӱTisH4TN_j{8<`*I& 6[?AxYbhk<s@̣0.f5z9]|hEOes7v7CG4 4Y?Q:GL|mêpD 4Hl"8KQ'}x=ʉ߷1Z+Og|oCmRI`?4NöUԒbt553Ս:5P׽ɪPIJ-pi˯?iw8 |3n^=M]Dgq5Z9pZIv-NU5I]V6M5SEF *F[up^{C`Da85\׽u=(˪:S"IE9'#rw~9'"zlS|gh=bqDeTE:qV~LYBnK{XFNKHITekD79%4SJʑaֿ$_Zp}kE ֿ$_Zp}kE܂/4V*.]ct:/R-qw!USEYR*$ R[[*R[Ge!Zv"0@.fޢEXۊjt+Og|6Mj!oz(gjꤺB `QP1o;~qÜ4ߜrJ*mNssH?TQVG'xՑ"mb괣.i ӱTis:& aE=Ce)#thmܽ-g5caҰߛn5aO:wӏ~>v=@(j.mL*wn8uJU3ngPlp*_4i؈*qk4iz~C"vo&ASKa]OÛQ_j{8@U a~yFə3LLe)'Hhu2n;hb>r\: mK%XReT". v֣w!U.)5My7JpЯp(h4UiE}|5.k ӱTis2O"=*aP>gGtu(ZQj*TֳRz]mU+A#-2"ں] J'.9Ϝhfokʫ>mq5Z9N6Uzi]c]ү~lDy6 NFSYO6(LY)QfuM,-*5~iT>=+Wj|J(&˝]d}54QeWOxs@^Ii;FS~T{.=͢7CG4S3= 4oHu 3:b*D7QpB. aZv"0@.hA8X4v2ӧSUV d}20 -wG9 ٴGRAQ ߩy%Wڞ1C8ݬDU yf]'Bol"xUZ) H:F]̔WH5%eqEO?iw8 |mti*YYSi8{ϛo0VgTCJϬVy&x_O=Z[\jM'GB".Tмd}G!Zv"0@.w GYM#ptMa'G4qxyGd< |⭍Jw2s,e W "蟴b>ptمipa8^r0o0Vf&T g z 4d݃lAbқ GJG4i؈*qk4oK(=bq:"2XN$^HnjOzys@މIu{F~uVO='%""..oq5Z9dOd*Q ~m]'X*IãVݻճLxP;<b#pT)'y*w*Ec'FE5>iE}>$kUNa4'W𭏉A&#kv 7NMgD79rhoV?F.n|.y>js8y~UήW>J}J>g ӱTis8:b 4RYSAHO&?WVHN.IQN+jk%%U4U{kMɞ.iE}>󏙦  ~4<.A0'pEe__*MW?q);>s:'.9ϛ?j]j=\:,p̕7Q%7L1]?8a5'*]AR] c>UtiMr#>mVɑZv"0@.gDnZv)PXOmqojs6KjjN?gU$*Q]dY*6))?8hTX;4ԢX7{nĖ[Zv"0@.gDnZw"B D>iT'w_j{8S{{ a ~Єj5-2T_Q?iw8 | b:nt\$Rj\FIIS3!g_4i؈*qk4ere [So>BC޵z) 2?AmE}>)VЮkDY6} }5dy8IpJYMK>kD79Vh3G\J t%Eo0ViR\-CkA6k>`_?-k ӱTis3Bʩ'F _+0ugC4mpެ"U[Ó|ֿp۴WLk\ JV_=Jix bw"7qxy͎1ҽ2~q6|Gei?,A8cm ]q ~r) Y$ Lm"+\ډK osh#yTy*t]9K)/2"J%OIS$T*|D>"J%OIS$T*|D>"J%OIS$T*|D>"J%OIS$T*|D>"J%OIS$T*|D>"J%O2FɴΕ݈"$MlgӜù osqw!Da8"kgs8@ޜlxsab#. [8;;gD0gÜ]|hp=;EN!pH79:!s8@l7C+E؈*q D?p9 ;;gq1Z->NFS\&qw3 vΈa798lzv"0B5ù oNstCp9o0VgӱT~zsw3 v.y>b[8|"$MlgӜù osqw!Da8"kgs8@ޜlxsab#. [8;;gD0gÜ]|hp=;EN!pH79:!s8@l7C+E؈*q D?p9 ;;gq1Z->NFS\&qw3 vΈa798lzv"0B5ù oNstCp9o0VgӱT(>QS)a{hYhiGUH\?p9ϙR7qCN2ТU . AzכLXSeŢ@l Ohxs2S#8eQCͬpJFqQCFQ mswaʒDwGcN1QƩgHGG3q/)%}M3VKOZN0؈*q DP.?ϾQ l];,Qty%<ytZ*F\?p9Ϙ%)f{AUR;ޫX]JD AQX7OHϩ;p+K/1jC; =ވa79@PEU9 7QJf{xr7Q%)f{AhoyOtd^7C+G1T% :WgT3يM}\[=I  ʵ T[Y M‹X(U{>NFS\&拡T-tXu-;2jOڐup5ù oNsAc>Bfp=k+bS\ZIǺUYy֭=˰tOB")vn=;EN!pH԰t"6.ZT" JX;=Ο}\|Lj. K+ Ȱt':ږk>¦*VFn.U.4uDaw+%}% ;=| G*-u׈<~R!\|Lr. Knq1Z7o- K}Bөl(-⮊MjCR-'O,O7X|"$Mޤ{H4ƳqFm'}g*`i{Ԓ}TŸi(w.2M A2>%$#eIwſ#gӜUAPNoҍfq3=.6~tHzt`&aM;ĒCF 6ЏR~=B\=|[nCp9u8vi?~BoEƸn8U׈C)=jKz*"%f㋲j=/ۻo0Vo ")uk:*A,{$3GX#|!{ Mö!R3jlFfxH;&*ĸ2N%c!zv"0B72v![$ՈVMVOeFO(^+REHFY+6YCv }G4ù oNsrF(umb!kqgHDUTLG7:M",uX])^+3b ,7 TH e%ױe*N,m:DʝOD0gÜCP647OM`ֳR%%LxTB:S5jTv{k#9=Ay*qgaG{]AH]"*&#M",ux_waB$3p3=3T~5W`l/E]Wbh#+uY#k2+wH|"$ṂĢbЪW[ U+5.is8@ޜ~2?dwR=A7xyCJ-] .huZU?nڗ魍d/m #|i+Q ;=Ҥ&%-+A[gID}[luv $IΏU=oYxλiB&(u[g:(zzȼ/ۻo0VҤ>ݔ+@SNJt 5[@b9wAE^v2!+?&mb#. s(lcE%eN 0H;=Tn6?)2^M=cH(J>݈" + ]+$RBq[WVEch֟;ù osN@'-%餴<7K> KTÕ[{稶 Ӛ:zMYLa<7Oxu4 )z>bTx_waTؽbC&] -SY1~*;Np[*aN.ʔtedoN0INn=;EN!pHF2+5 ,tZUdđ4 *>is8@ޜ纚TTXA6w_i譀o+k:yEL|XA67[0VE~.y>bnƖH#:v م/Ԫȫ=gM]^QՋ ?u؈*q D&ʗY\M Ino>!KI!L4(:e0SQAQVu4ù oNs0/"+aK5榶K+#c(xs1\YxsYwxa/Yz0t\+VLQ S[Hpz}'Da8"nfi68}j4`]ӧ\~XϚG79\uX]Þjkh}>i(xs1\YxsYwxa/Yz}|>UZdfD,ݡzv"0B73\;m¤d *~m}eEe<:j[d ?A:|?p9Ϙ㬊譃_[fX%=O}[.rWZ6D0gÜ*N{&:ȼ/ۻo0Vc |ȫUj::U-u1ﶃ>b#. sEBŠm{`ޡ*aeD[+dQR٨i&A3i~Ϭ[ uTS…§O4ù oNs0/"+`mds^xꭇof5c?D0gÜ*N{&:ȼ/ۻo0Vc |ȫ>Qͳ# URX!DSB>NFS\&$;#o,KeJL]:JJNd\qez9~zs1}YZKd\?%dZKyCSrXպQ ;>c~: / w!_**;sl UR[4ɘLuM7ҏVo1؈*q D4*t}kVCC(.wʳ#gӜ. :Ȭ. UmVBGI.?xtDgRuН-6-҈a79 U׈8Lux_waUWYf+QlUJU"UQ=ЏCDa8"nsL(B; t{)ueM}>ks8@ޜap_qEatV1{./ RNn&yd].;'ʿ1b:O߽Y -UVYhxs1\YxsYwxa/Yz,=&aQ1*E[)i-VDF("3؈*q DhERijMRUN#tN"5 A+PG/SR" ڧ%T""3 `켽w3 |dVEsTen}P+V(A~6iWOeHhd)wZrə;E-D^3uw3 |sdu'=d^7C+G1UdUkN)= .DĪQVyhET.*t:N)SJ~:N)S&)*RH|"$M#0gnR`QҸ)kw3 |dVEsTۥRapO-+O^F#}za5-DanCp9Ϙ_bD`~㬋]|h0ʬMkxbVMCDa8"nis:J <\/K79\uX]ڭ<QKQpUp, gMPMG_Jvw3 |sdu'=d^7C+G1UdUk[jT^mb#. sH kC-Di2;wE3j ^2ZJIiP~5Jqs{$t8ù oNs,HKh:2#t>RhGb-hZ]QTGipm@ܡOǿ8:PXТ?Yj1bz fIZE3x?QTߘ͓MxTww3 |%dg ~Თ 8lkJH]"؈q%TYt>)qK_-N. ϣwaŔ) ffuTn5jghYƯ\JЯ(DERgtJT8q5jghYƯ8q5jghYƯ8q5jghYƯ4mLn=;EN!pH79:!s8@l7C+E؈*q D?p9 ;;gq1Z->NFS\&qw3 vΈa798lzv"0B5ù oNstCp9o0VgӱT~zsw3 v.y>b[8|"$MlgӜù osqw!Da8"kgs8@ޜlxsab#. [8;;gD0gÜ]|hp=;EN!pH79:!s8@l7C+E؈*q D?p9 ;;gq1Z->NFS\&qw3 vΈa798lzv"0B5ù oNstCp9o0VgӱT~zsw3 v.y>b[8|"$MlgӜù osqw!Da8"kgs8@ޜlxsaaJ~!-7I(""'xU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}%_B5 WЍBU#P}xtJ>iU 9JF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*.jѨJF*./Sԣ0,ECMXIT$!+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.jѨJ˻F+.j ][˥Lo.xGjN*9ģN(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(J>:N(%թ%HMT :j"=c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c0IB(GH#t:GH#t:GH#t:GH#t:GH#t:GH#t:GHqT:qc:qc:qc:qc:qc:qc:qc:qc:qc:qc:qc:qc:q6UtX1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c03N" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zSs.)XqJcV#+**PT6`]i/LI7VcFY UţX.~y2efGLq 1/$'PhT^%y&8bm)$]&G*n2CJ2>JLq+1iTWc^I%y&8Wc^I%y&8Wc^IG0U%\R╈ǜAnaǯjm`+E ֏6{aS+YOujNFSJn`hT.$ch'Ƚmc׈#T"#]ZGSKZmc+ ߠ^ iG`v~SMkY"+&fDi%}7 p{N 髩kNk(;sQ>C[cWEI$!6lU9Z!pgt>b6Iu\i$6x`o1n% Ѻ 0m'V5z۟V YZӱTқw<7K> KTUo+zVqW;  )*D]#P[UzߥAM:U+A2>-NnD]f} !QV\Ob586hlSqEgA[FGgvS*nXF\IHD}n}>suOlqw3u_ahT/y$D)=Esk`o1nSIОx?IWOprVtDa8j݉i[WbuA6MӮzVASmҦUt$8\:樓EI1EIW['vy(Toau(:/YgY@8?q];ojwe] ݿ YP]W +QvWPUgyCsù{o"p|h`W =E]~t ՗L"m""Co]Y [J(]YZӱTқtA1q5(K='}U)M"zWKWOkWu;@١hSk0uQFOki5Vj3G Az '*o7au\:)ӨV;'uEl@;wR{quB6M2RJS`yǹUE883G: ou_vUԢ_[_bu4M4:~l-5i^QyB3d8l~d&%_q0*㉆WL6Jxv%5.0u(^JuA6Mu7똫a5N:diZM:CWLC߆GՏW>=Vϭ'H[IR#YujNFSJmѺ#iQeeݬ\dbGR!y4Ƅ'SM^1 [m'IsM!*AXzAx_T; (Tee >ΊE8M4SRxQ? 8O$MS*dqfBӲ} OJf&JvISOQjwe] Qu*oɭgR30 ʕW뮩%ce\],j-UL># ǬdH.B )D[&"-+04UIX쬁\\tD_OXCR\.]|ѫ;EN)DXyQ&~DbQ+u-'o' >1V=xVELJxg:JX)u~SWsS+${ NM'QI$T؁AWlŠ+MLҎ"5~'_U?<ߺgNUGڝWCw7JST#G][nRT]${ pi& O>⬡똫DcMBq JC;a.}USII¢bM0pPTڃ"UU7똫Y2U~7" qêRFtDa8jƫl-$ ={OjEƸn8Okznlq[ĐR8tNUCm5z8%V]I-N7EdC,5bĬ%}@(TEDOMY˴E+ടYgZ *Ej35,(;nA*z ~&={ g*OɰEN؎?z~=YĖ"k( }dJ":[)2Qu1NUD^zEDl;I~`t=ԨLr,~AF(SPx k=l\[ _q)bo.nbӰN6ǒl'vAUi!6{ZSm24U%8wjNFSJm/mY% kpJU3=VDۃ~Y5U>N/r_9!M+صR/p,%߻m}G`LOgf Ih:&Ÿ^tcͬq׳C!UZDh|ja5)-ZΑ0fJY.{(YYD~Wݕt7sv%:$"- e\\xx%;II=;$lp8J BQuL>#݉q.)IJ-sl15TIYd%m$]m!1DQB/u;$aQ4!NF˜}t|VtDa8j,߮zǯ67Nzx6!SnN-T{I-w~S?U8:3R%?It#۳%肦߫MwbCsQjwe] 4Fβ߮be_[KFU%[ғ ޲t-=[u':Uz6IoDJV?-z-%{b#W71fs=x qĒ}d¸~V>o"z/v~S?U8:P#C#/K˴I&VO tZyFiPhnz#N쫡ƈ79PU1uJ_UJ3I:d{J:D)Kty:>iASq=u_a1DY~=]IDZkqD|xZT_+ΐ¼ERzGګVٝ[wս5{b#W71fs=xx!ZM#2HIhwܟ))յ~LSCԽUS;ڍ'tG8O1Y<&UJU"0It9IOWR}*MouKQӨ6-_qjWTB!'VJU:EEи3Is\2iDij"]./q>!}4nL>#1ר o1Vǧ(X,~%t:1V=BTLm^?" ^śX&PGR̔GAI:RVRHG8O1Y<㬡qs] 4Fβ߮bݙ#p:'Vt>czβskFU=ޣpR&"7FtDa8j,߮zǯ6ꖛ*jY+ר,U}O0G8O1Y<㬡qs] 4Fβ߮bݠ_ L/ Ȕ$}4L>#1ר o1V{]A{ZST)~ZӔCKMV7GaLn=QxR`颟UiRV t~S?U8:8m<ڔ}f9E9 S9E9 S9E9 S9E9 8X[(Ԯɟ< RULtQNBh/hse\[ T! ̺*7h}(հNm>meJ*G\ML GMj?OR[&ΒRTTC)Ept>czβsi-'Hxu6o|vM *dv '6iV*.%5/:GVB@'I5`ӱTқ~Dտ5zĒ}dW:ࣩv8%m]a_h_?1eMZFŗa?$ R[U>G\m+V 1 p{ 笢?+ʺhse\[C='F K] Dlu-$c0wj@{h/ғVNFT^XKL"+UAb8'ªlˠdQ:G@Mk㌺ ׺{b#W71fs=xMYU3M;=x}+*UOOnߪpcJyǺPhnz#N쫡ƈ79PU9IJb33EN5nY)Go'YL>#1ר o1W6 u+N#.[M^r#x+)EγRdwVtDa8j-E4I頓J8~Dd¥ImIIme:q[GH!nRKL#ԎΫ j׼N,Q~:Ś xcIWLB#}ZO!a~c0nqj53߿T<"4uʲd*Tt/!IĚ/!CD6ieDt3 jnԭDD}M$yM"T uFY+Gջ*n1r9,JH]2x~'Gx~ nRo32oj#4R:_Iu!mPQg(7|bRzF=*%*b݈Wm$'Inz)q;&{Kqd$"#%q(㈈G (άId QL|2iBcL~:9{MS P,.!]D?m:`݂" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-Wv"05zS[78MUft;f" ^Nlt7rٯ0ٵ{b#W5~S5] ܶkL>#m^؈*pMl߿T6WCw-WvQo8J ڕ.ccccccccccccccccccccccccccccccccccccccccccccccccccan}gO$Cx 7o!Cx 7o!Cx 7o!Cx 7o!Cx 7o!Cx 7o!CxiJi$pR8) G#HpR8) G#HpR8) G#HpR8) G#HpR8) G#HpR8) G#HpR8)yғ*twUȾT{2XnXEN!iݼ]&6Vy5_8 oVL:\*aD]tUIӺ8bX&A>'MU֢S]bznK}5mT]P6{f֝߆m>7RYŸe=4 iiʒ[aFOH!S[T鸯UtMI)Itn.EeT#зl;f6{ǯw*pfMo8A֭:_*zWDDDDDDDDBڪG`I5(n>xXEN!ij ntϪG^an}fgdASR#2{ZT2j^+6=*u,v7X" \jX*SpY!'Y}7똫aSΟ*vb(%#oKHr==K4"IS껷/ ۥb[duO %7s-߆mտsn.Qhã W`O''S:$mSiJf!T&;$H7BirO:|{ˆP$0وΧF+ɠF5MXGH{kWax;DAQRx},֌X Ib2TԂ>tctm{n֗cxENLۡP󤞕 J .5Gd|Sm'jW:k%Ec8X"4 •ptiaopާJ"`x!)'>$^gbp1stLta8:}%ҘaM*(L&[5}DdTd *bL0݋5:†aU.ŝO\-UC*Ǝf=PR|i1[,^fi* EX-.ChLTqXRh o!JUAxPSOJdbȆhة+&b $~Y?y!D~lΡm<{0ZU:^t1TJ}*eC,6*AGЫ:GDa8f3nD!j|2&aTj۾{ sEUR~mt6ٖ[e]=+=;×Odi5JV'6x$CbV=}Eq0[:iU\C t$ݺ8bhgt k:əMo-ޕv'D o1Vǻ֤*zcc vR}Ecq%ʝؚ6N4Bxè72ʥYEbҦF PuGUR-'I^DW\QT*xVQ%K3ENLۡELU9-XAp{<u]'wE[T:h^+=;/|SI>M/NɎF򶪻Yշd:)!W]Ebդ']aŹ{zbp1suMU5EF8M i^JlEe=d *DXg+_. @zZqպ; )*fbRS-]WQ "Ya?;N§&DChFNnyeK,=NBnENL۪}5HP&MBE"SItyu?FTpV MJvYX2SJk૮2B}'XQ1EI/[u*p֙X2T{*E3@߮bg͞ud-IX9izT~]O; #t=TʟA|;"\A҈/ ƽ™cZuVP}gԬ5UYՒg?ջDa8f3s.&j_*}Ȏ+zVL[/H"ݢCYXe$8_Ue-@}׻8b1DY~ ؈Bhv'b>R)OjpU[&*؇+5akA-4$d9YfhEHsu MK,">>٦vTf+:=V'*=#7q3V"SiAjʯ啕Ssw*qsO1fMc+Y$%T&|=oHuUKv*pczβskq %QicບwՆ)'bP SM)T$+mZRTB7"fM\ĒQLYuޗNyJJIO^5:(5؏7O=5>+v*pf.\LՈT AS y*Y=2 gHp nXEN!i,izEuJ,몪RΰeYاpnҢ:ʶI0OvX" \1ר o1W~ 1T=Q]w:)'L /ϼ~TEQXsV@3671j>A9헝Q.á5D&]&H#/}:kY3;&fuMm */O2MlzcYVPug;FSo71rfEܑJX"4o4=oAS s}gIIS3qU->e]kt*pczβsyBD!z E@(]yD'|T-?*Ssa k:8>#9e70jP:DE9 v5u:CnhWoQ*)f뮝R&fuL!UiIꭢi9FUyX7h" &nbXOPT9=DcUXEN!i,izEkpӳq5p#IVT67;+UTዜ:d -™ c\]gULR8U'Pq7IhQJ3؊J+ "i>'2*2SJX/ ߆mݪC7xo EI;XAN%pnaq 7pꔥY33#:D84/Żmϳ|ud!UZVT\| ;Ҭ%mG1*qsO1fMc+ZOR)CDZ}FXVD#x8ENcQ9@߮bP)qéIu`JʒT}j=:K$ԦV uwvj:II/:ڟ=c.7yKyS]RdhD3ͬ%VE2GDT*/ԝ|J *K|LUAI:id|"?{FSo71rfE) GAMެJ[wǣa8y/k*V?cQ-'9u':a&Y3"TZ|-uPjS3n@@4o>JHS:OG^uߵ=9@ӎ J;zϢ3`"iqy/zRsɫUL5"HW_Ru}~XTTH" \1ר o1W"IJGHս`~F,;M9 Ԥ`D%dSJ}geG\[W}e<3RW~F [7xRkx_=;Cx2JvLfZ?LfZ?LfZ?LfZ?LfZ?LfZ?LfZ?) Rl֒RSL _O>gk^XDSc} .A_s>jxq7Id/r)? qv\u\%*#G稁Ea8f3s.&j_*}kIM¬Tbl.eTbǯV8+*APƶkj^e'9u':U{#P<{~!ͣH=R׻;ͺPϛRZ-VQo2ZT]A""t#sո4 R?E^m[Oo#7q3V"S׬{w67 ["QXEN!i,izEu#ڸ DB)uA$g SR8ENcQ9@߮b +D;յ. ߆m҆|l 6n:-:u v$ Ԣ\dseD?Sn4tˠ2\#7vdViiGԝcqRu,eӿ8:'X> EB&3*qsO1mpՒSK|q}I8:'Xq(5*% UB8mQ!՗1Il? RTM;I:s[yeobp1s*Ĥ3޸F%D7?hySmJ5mT[H~)i%tLyqdbE7_B.Sr9:` +h~J 5`gf hs3*HJj"gc{S9O`?^{S9O`?^{S9O`?^AGGh҄'J4ҭ(wK==[WBXQšf,0G E~ՉtSiĮqd :)tyBRJ4PV笯6ߎlZMpcTlⰊClp1rٻm03xVS{mNS.[7~FSo5*qsM*pf5*pfqXEN!iq8ENlfENL+=6'- #7a88bwDa8f3[8"48" \n3[h" &kgTgTዖ߆kmTlⰊClp1rٻm03xVS{mNS.[7~FSo5*qsM*pf5*pfqXEN!iq8ENlfENL+=6'- #7a88bwDa8f3[8"48" \n3[h" hFЈzģq(J#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>#O8)>!Q *FmD؆EC~V+H+ !Q1APa 0@qp?!'!! =U9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=Q #1SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzhFb=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜CASsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsNzU9=T窜SsMz'p $4NI-6ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|p'M$ _&M|5kɯ_&M|5kɯ_&M|5kɯ_&M|5kɯ_&M|5kɯ_&M|5kɯ_&:Hd)E9=碜SsNz)E9=碜SsNz)E9=碜SsNz)E9=碜SsNz)E9=碜SsNz)E9=碜SsNz)E9EqLBSVjMZ)E5hբSVjMZ)E5hբSVjMZ)E5hբSVjMZ)E5hբSVjMZ)E5hբSVjMZ)E5hբSVjH6Nc$36kO ,s&9ijZxTdu6_1ͨ&%¥K#61jIfmA1,֞*Yi;WLs3j fRMl'1ڿcPLK5JGZlca9ڂbY<*T:c vfiR֛Nc$36kO ,s&9ijZxTdu6_1ͨ&%¥K#61jIfmA1,֞*Yi;WLs3j fRMl'1ڿcPLK5JGZlca9ڂbY<*T:c |a(b@JS^Ua$i!ØIfyk;M|BLQrp5"frR*PeACݏ0&%9J`F!+֋'Urm2.+Bt{_ , y*^K){DX!H^ |`RIMu3[n %i;rx/ 'g!LEas~Zi4/;7uty9Q1,ܛ%̨++EYL+AKMGb&l1RȑR7Yn , н DPt[.W6_0 7>4枂@8UϩIfy0ccUj1n_J^{5Uq`.DGhM;(eXۈi4NUijra4@: 2-QZ>QYF~x$F)I7=ôl9L*T;0\~Fo`_Nc?<ɱB@]H+ ^I;A IDIqJLs34%R*G FAI]IYʄijr$ᠿw{?9F*Y˪c nͷr1~ hAO^MucMv5VK5 5M08&9&SxnN^erbY0{Cr`?@aRܱ“r*i6P2 + |O Dx)lsp_ &:]y sRcm`ai#q.̰r1,4@ԅ<$ c&o;H=7VZi*i$S ,C*X%OVӑ'UClBk|ca9bۜԤ3<Ѣ1"1҇@6bm@&W*&%"ovaSA0X:cru!RܪSݦv-P hbԞ7,+ vRcewSt1WHJ6(mܰnZiZ0Od hunCW¥K#Ad++>C|IiAEmC<׼& ;Wu)10Pu*rʟDˉf妐oJC5oC⭬0JWv.W6_Ԥ3]r 9ۭ61d?㮹p֛ϲs\vMg9\r;u3u.cNc:\i'1uˀ.@n} sZlc>]r 9ۭ61d?㮹p֛ϲs*^9|r/_9=CmApK2*ǘčN jT.R#m} /H0y$;U'jTRvNIک;U'jTBBC aHh˩ 6(lAȼ ։X)#29|c>|2~1mIpPeyz|uK6j\q@vTĝ wdSrI8czFǺ#Tt@v9\c>|d祪2PDxt8\q@vP&WT) cBI )DtWP/r}WUڂ\U$з 5DA`4 B)@&>C4`,\qxiEPn#ZSnu.p"V{;5Q(jGFr}WUm:ECHU{ .;\ MB[[i0ADn {D&dvG+5k\ֹsZb~?0it<68rn>3Fq]lC@0*h3 m۞9^Sϲs(꧱:l4ї #۪mp8m E;"Pď%eYrLc @n9m訏2AɌ(7(5:?[Ro$/8yLc>|%7hwzhr@%X2rF `ԍnph a4Wk dvX\UB:@Yy#vm)RH #1Xb DEYcNҍLJ78Ǖ3:p؏-Y# V2}I%䓾NB0A!0j .g1C#FR+v`ʩo`B/́wMԖ;bRQ*IcNc=cAxv, 6I l?n(g!x' 0\;K,\׎7z 4{ptܡ-M \#Xqovw:;w(a%Y(4>z#i%@h΃ׅ%X q'1򮁚؀DO D17@m`/D2r,aҠaA6Cᷫ g2Km'տH#ChX.B;0*xLpCΤn?e]Fv~`ܘh#2]aAޚ6K(#@U{ @:n8"yRcRQ9Lc>|㦯P {6n|,˃v[ipCJA%CܹfJjIb9 c[Hw9srg`΍> & Xg Q*ʢ)H U3+({Կ9Lc>|&s&^> #x^q Z7iH{]#e6Tv7ם? P{] IpCLTه W<)Cm= RyPj'1Q5\Nʇ0\(,{nLݻZ(!E‰aee󺛹J: c̃Af ދM`1Nc4ǃĖ!D`PHWYuVPq zWӸ D?^)% Qfơ.'R'n@2fpP.LE/5|r)RHv} %`Uv-CO2vM A絍 4Ћ8v\QZ4]p^!=eqT{75-R\7q!Iy4G.Qh xMp-Exqh͑y0B!1#L ㏁iXx?X.T 7{?L9srjmz+gcK=Wb$1t9a LZJAp^Q.b0 |hIQéwkUD[dȡ% P75J A)Nu bWP.G코&M i( y*ɨ)[^) Maj1i$z_\1d>Q&13"DZudgytz]ˁ ɥ\ZB0C*tCf |K!@rMp;Z{ c${<9۹@@;#l<X<P8$lU]9\c>|4j!MB_ X72& 0ݤMۻH ; KhQފ 2*M[g`\E13W tz S0@ 0&.VZQ a@]|9۹P ;CA gg5 4e=L Yf,Jf1A`T@v1d?㮹p֛ϲs\vMg9\r;u3u.cNc:\i'1uˀ.@n} sZlc>]r 9ۭ61d?㮹p֛ϲs\vMg9\r;u3u.cNc:\i'1uˀ.@n} sZlc>ƮwPZl2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&LHJ` L @ @ @ @ @ @"_Q@I&P+/jTR^Kک{U/jTR^Kک{U/jTR^Kک{U/jTR^Kک{U/jTR^Kک{U/jTR^Kک{U/jS;I} zFMT5RTJSU*jMT5RTJSU*jMT5RTJSU*jMT5RTJSU*jMT5RTJSU*jMT5RTJSU*jMT hLƎ[ٯI… (PB (PB (PB (PB (PB (PB2A'elTm9RJ*TRJ*TRJ*TRJ*TRJ*TRJ*TRTDdlTm:TRJ*TRJ*TRJ*TRJ*TRJ*TRJ*Tp'RʦRa{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷{/쾷Ɉt<+9IaZqZ]i/ƤrARZ@.NcRXm9V\V sZi'1,6+PT+V94ԖNA*WH֚bjK +դbM1d5%ӐEj j1usi"JiL_9IaZqZ]i/ƤrARZ@.NcRXm9V\V sZi'1,6+PT+V94ԖNA*WH֚bjK +դbM1d5%ӐEj j1us˔ j]eN vXpy\aEݫ,˃LP w** PՈʲU4@9 \\"p ;X` :X)fAD@ * M  h#h<6Yfw G!1d5%tG@2ctXř`G: _h r"RI)u#S+n|\ Y .}A7A̓xkJzǕ$ҙ|76bI4O9$ I%S5jPz":JRci8 -J PpnJZ0WSi' b)$zt C~y\%zvE9/B&7vS75;z1/N Ʊ-L_9Ia?FDvi7aGp;m~ێb`@ÔEO"I;Li"(xTK`bY Jpq팁ݻ:̾8~'䞔k!MzP*e>N@TH둣 j$Jtr Y'{(\VDvT0n17*T7.,.HV?awzXϓ0xݺIJi$n>N@܊S<2!Ȧ=^I;Yyjny1d5% TE']" W6RA$+0QnJ&WI' Spr.R O R( hI];_1d5%'V ,`c,/zAP מRA$+0 '[Ѻ4ynUB^I8b1w"nO"xNF+ &Z9L.r^B2q/ƤRLQDk Us;}Nк8NU)@UP#|VJeez0m;}NS ~]ӑϋw@W#v @soWI' Spr.R OH4y@*rl ǘsR Sky刻] 4aJŧ KՓ_(E ?.Gy=*}'BN@܊S<;3@VWYT_ i$>zL_9IaHIB O H!5@J:7E ?.ҁCi3"BtK!Hm%^ dž ެg~,+N]ȥ0ȝr>@VUEn;T&5IBlM 5^%1d5%KM0b`**X#G CR?wC gRp_+ ~]UcRЁ^hR˼ETH YG3`I0|9ryKUv@0QL,_}}59Ij\7. ` %i!S*t &U<%䃟3hmx J͢Gr8Қ q)J)CD(5x@ &(h 4RPJ)CE(h Cut4 H'b>ORw˱!G@: TlC :k'p UXRQ)$La#/Kx1jAPKl5n}NB~(Gs pc)-l(fVY#?`d;.B*i) t0( ;j}ډ&C&Qf^I)(C"yŠ[[Z4yPЬ(7qC&G̐Vwc)T>EY)$Ocrf\v۷a VsN+^ (iL7LO @( ʖ+i(' EDZ;oG Rkӟŕsg"L@ 'NjdV4 $w&0@ `<- w?,eşD@ ziiPMGSt/4׷[U瓕sj]RPҙ:ԫ~MɌ<^d! _ϢX^#Aid׹yCESd+0 *VK(w%}URK{'Jj DB`h7 JGt 8wn|Kgx$򒷶Nc,tCT %b7Nh 62$V[xl ="hĘF|)[mxi1 =NZ&h<'*x8I~4b\'Jj+êF_YDl%A'v`#;pmP"dBۈQCq7:09 _okྲ T |Уlp.!:{*3ִ^NJ,E)JXߏ+{d>24-V!$CI$`X](k Wr%>xXԤDV é&$Y J1T7Uq406 ?|tAx(ud0/8!layr%8כT7ܴ*7m_&BaVDjE4MVAFJj pPH\R9DpуvqD[+{d>Iil{xTFxwwC8$%p^ZSWx.Pe|uRNh\ (`}2;u7r9ĕs$=ɌayO!q4\Ab@hYTnƦ7Ősg(i7pxlu+{d>Iil{wHR< HDOz"SIcXI‘͛c@(ЅUαL: Vp#6SK{_L@Zj`.GÙOQB}-]b5ې:jЍ;lmE@o}pʍ&)h$2f2y6gBʃ X"e&@2HtO dY)(8{-$[ 3HU"]TuR.EHU"]QH#F/HXnE4$[)RPZ؛HjvNVajDhv&; Uִx#OVثG(xSIJ)[DUy,{i$%Q}]1i{`v pb\Bu v.y[;$>'^ҝpMova{҈]ܣC=+Cn1P70hB 5MJ.SCyTY%5zPh h! a5Ѱ)Nyg1tq]PxLHŔ$q,G7k M۸MT{Ixtu1<“== bXg|$ $ | I@CQHkt U06z-Ga}<\.OՀ+!QO 7'ˠzoXk, nucLNpfp8 ) GREǜƥq^(XX~|IK: Xs'{ɼJ4I`y+pݣ9E,%xEPJJd=Z@Ѻ$ =s?;͠&W6Arx ʝ4Xdj8I,ŅoF8^ Csa 6ǜƥq]z7yFXCiF /p'9s n0(,kE$q,G7ê^o7H*{/svdЁW@6 7!cG,%x>};0EBĀ즠UL(K @HaWPzZ.l<0@VIwq؅HJk62+"1oP8\-W QmFMAa7"JJ:5mfB"1Bܧܜ]Kފ1gCsy\E 1/P8 HK heR璒## 5!@6^}[ =0cϫ9Kc{ryK^2o$sн0PB"GAC#@VF:f`hp b=ƒ ֦s#^&'j&<=&" 0 *'m-(4*ci5d*̜ƥs1N_55 yX8^q,G7#){sɼth撝 ;TƸaԂx#@2r‡@;pJ[h :24M$ !u;#vEs>ӘԺ|Fckr/<3$q,G7#){sɺRQzE%@tNǰIAXW}xiPQ#0[7U؁x#$@#YE#}^J¼6LKPOfq8#3!PhN1)5ˋ /.bKVNy\vCV76@@ sASk3- `i( $|QHXnFRtȱ숑n"Z< 5龯qrY0#!b9vD0@(莸Y\e]=Fþ/Ɂiϸ8\>b1&$HsMo@mcMu )HM$1y(wC gq h hcƜƥs1+ y9n<>_ۑı܌&O/[w-wqx[w~ zq$1,G3aHtAah.A\.OI6| +!$OdWvLg7:0״|Qa6uw&DCƜƥs0fƞx5x9K^2n"9P>S KcA쀂b8% I;MQ q⁕I Kr 3!joJ9z6YlS 'l'sSUH#; D V  PÏ9KYȩ@]uL)<7ʢ`0\X}@XnEcLCrI$pi~5$4Si*p,8"@4T ^l<Ѓxi+%[Ui K-{$[ <MKAS]i0ʎpQS SWT !j: II"Farx4ËAAAOp0wkx> 0o!D4檐y+A ' lE{t&/r3Ժ NGsZr#65.ӑı֜%m<.M9Kq,G5!b9O kNcR-9KibXfӘԺ NGsZr#65.ӑı֜%m<.M9Kq,G5!b9O kNcR-9KibXfӘԺ NGsZr#65.ӑı֜%m<.M9Kq,G5!b9O kNcR-9KibXfӘԺ NGsZr#65.ӑı֜%m<.M9Kq,G5!b9O kMcDIȩ?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'ЀP-m-RSJ{)Oe)=RSJ{)Oe)=RSJ{)Oe)=RSJ{)Oe)=RSJ{)Oe)=RSJ{)Oe)=RSEIE*OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI)?e'R~OI!fuk E y?M1/ s<<<<<<̽}}}}}}qqqqqq@>P |@)P@>P |@)cP< @1@@; >dPP C2*f 0 |@@*0#X)"PԈT`@@X>H\PPd 0 |@@P)P3<@P=@@ 6X@@@&j >\@Ps<(Ҁ |@)P@>P |@)P@>B      l<<<<<<\ 0 0 0 0 0 0ȽP@ 0(@T}P@ 0(@M4T 0 08}0P 8PT @Jp sM4рx h @ 090(P* @pTN0 0}@KAP@q 0@x #*@@D T l" p0 (P@ZT WL}n@PX @,0D @@9[՞48v*)Ujfʥeǩy#bT3Kq|k û 2iI9N@{2$rPNISH%,Oܡ6N)' A ^.,< !K"sí@ (o6";kF"ɀRdnƇU*#DRԲԼ؁$#F%GeQWG}7YCJƱJ--)uDf4\m=m %E\>#$&0&/͓&I#CQ^R9 aW%^x5ȩxH~"I0i{q)*MD(%InF^g>F^g>F^g>F^g>F^g>F^g>F)J0F?g #`30F?g #`30F?g #`30CE-HQ$H"D$H"D$H"D$YrH.6H#d6H#d6H#d6H#d6H#d6H#d4vS:fiyC!}>yC!}>yC!}>y.g1)|ix^+%Ax3Veu^(Y^+׊x?fPix^+%Ax3Veu^(Y]ѓRxwxw~zA}ۼr#?#?#?#?#?#?"rC5gwWtpDݑх%ύA=euDcuZnwjQA|Dܖ%ܙ_O?Ӵ"JV4v"V$ǘČ=(vR+H(4'NuL# B]7~!RD!)Cf3y.lF=T>UvnZl2ir;gwJnK'ɰ$%4SX!G8?,6kDGv&#P^ .D׮u%;tZ]Hg)RVd-QPY]Z& &J$=YMNr`ʜeuDa&DAYNAurkZc Ef{TB<%ޔ;ol[uwy]Ԇ-Z1TI0Yw#CLzZ%$9999'D WP'JjW̠JMZ(vx: 5 MLh(Ti7Y.w΄& H--Wt`&>DR w#L"k見]-etDHDalu*6:UYWK(ңLĻoBn?E.--+h$ʕ(J:.܀ V%ΐs$jO*kJazRڬqT7=e|j d]׃FFbᲀu krڞWڃ3֎IZa &/9RڬcBɠ$2䋧uAW(_8}q$fdFnwFYIdNK'1%݈{_z",gQPua\]WtΑ0J+XW2I̥DR6{Xba"25Q1@ Ζ ̅ij'ٺ̠{Ԅ؜w3^E fG8E^%ݒsWvo)l;MosI)6TRR 1G4}< ettEHKc~A)[]أ2(:\(C 7.쑔*B'P$J7˓.ZH 1jXHS$};USBཾqgĮ`QJҳے^TuȂNR^61 * 97fY:…V+im۔ـc!1]Ie;V] a bA9:MIR01¢ vrJe<ۑՎp"JW4L3*JOʘ 6 9ttZdIe4Mr`1i1j-Jb(]`f]%'*JG D5kVz.FdTh@M`8GM tDԚ]dK(UJak &1r)(d9ڪ̖J-f)@+4ZT$Id+ $+PYU]1HBZe%d:J[/IDN@`֝MUs*XC4Xfڭ;\<й̵Gr''vRP'`-,tL''1a(m9 26jf,I{ . Jg-2;fl?MʠbdY esU*%ZfKhPUdF!#h[WXk5.^*:5-бE *UpPY_fSw RXt~Y7n0w4#&b):e\<ĹI@ w˶D|j[W˶p͇%*wc3e>:f n /Vuka`\US>EE'2FЗv2 oHT+ba&`r,(-X'+;e `f}lb_{Uv%]; Ògٲ <6luQ9-Qnݝ $B kKВ/9c7 Na> alĦN'Av T 3,qJ9#_,fvl܊U -֠^֩l BPj=7n5V8Vnh03K@%l (( E;e!JMsCLNTM X'& ,)3@t'r_Wx3;6Sfg-XE+ 0Nhɓ"Hd-t]̵Gtw)*dK`E?Vj# am˔V YzIh,ԐwBЦ^+@l9/Wx )d:;97n.`B3BYħK~H` xV>&VxǪ)6DGK]eL20A];J+…U!)x_>S+ITXRXȑ@r>+&I$=݅X7*ca" 9|Oz?z?z?z?z?z?A!@!_j#w̵G fZA3-Qn7PaTy0e<@c2j+Dbo"9_Y|fg49HͧZP-~A@ sPaޮӄRxny6"Ng#J=P` |?W->s mfkp0>&9}-|ϙ2y\׸wbZjmq[#ߡ(pX*Ń 5:̰h>@ Yccc܅E+sBa5_`he}QeNZ&GWWgp"eߟ9KX5de-@Z ca#YQDKjjmI'@6oX!s`ժu4#9*Ow+Ն5`Kƣg3\=aYs8R{’I|?2& M?- 태Vf[:|"`ȅFg>;G:R&L嵟:T ˧oE Muh TԄꠔNq7Gw>bXRz%0+U>yB3 ώykJE/&K>ac<ϞGv?-T곔f6eߟAFV̦آkRnr3'{iN$]'ˊaÜ.sv`'_lЌs6yk@ `HFF=Ul"FGv?-)\"Xr[2aY_lJ('t4٨ifEOHd͊k79 Mr% )rH R0Nbw\lRZ ͚n|u-y-DZ53|;lϟ?iQ̗/vHnr3"KL؏9v?mZ>&66hFsA< 5ʚ)bH2:k(n @Z^@H-+֟Gv?-!)0?g F̀ zĪR^N5A3+\[m ,eƦĝ I=i*W2T EL&1]Z(b#BdBK͚n|u-~)V7}mkwgfeߟAF2Zfĭ/[Yhljm&P}8946 )1>)Z؋j4#9ܬĀ( Ʌyx2]S&Oe}!&Q:j7fT#?"Hvl7.Ŝ`NNRrLF-ܙ,ҜTKb IlgMgHJx|̞pFa#bOK͚qY(t+6hFsAdxӊk8١'N+-fg4VG<8͚qY(t+6hFsAdxӊk8١'N+-f*I:-Kr˗.\r˗.\r˗.\fܪ TYY@SN%Zѵ"L*`;¤QC㷚}ki2ϩ,KO? ӜTԠʙ5Y\?AY ѨM_gY2 -CDd[oA^Q@@X`si֢TӖO-H<& (^Bv3Hb0MʳP˔X)pÝ6@Xm MMz-\r+[jv[QFs{Ce鲐\F 1&3HN}X)3 e1G+ &>Am@R~=sA8&R56)n zJLm)2%&N(>)ѐIVj[) ffJc'8;P Rh#RAPAy$T dQA jPRUZUgLU}M}—Ґ,kBj;_t\Rr/%f2"4"\ŲӐ T4`%3IP)) E*(H@D7g*uш6P$KoY]%HVեibzYhk'5 .jT\&3nUL@/dgV̒˥2h qQTԚPglZ1<.YZY{KN9ESƆ&Yg~oܼzI3>E *sz)(d h[ʆaTZmخlΑ9אJpIı(e e,nR'M5:0!X@AJA&)tOTˀc5taғ];~/l>5]#bN\< ,al$V)WZX{"@R%9T[  /m65Ng1&[`kA-c@'{RNMLjmۊĉUnvN_y/9{g*/TO :C*ެ׫&BאMp HQd `֤wLug̐cdR2la 6 D0" |Mkoe _qD5B枍#s@kl#v^|*}li} ^ I6boj&zl*:PIIrlE{B Ek, mtra/ Qr\J;m7W ͑Xȗl#PX-iC%]PV&lZSoܼzƘXb͋QQNx ;SzuON I6I#R4#̄v]Z+!ԡn(72o?}M%H֭+KOC<9evxHTe9 U" *BSUaN T(5!iJݚXR@[qIrCw+;" $ՠ~ȑKBB*)^cHS@VE[B{e3gv W6# `?o;$Ty"3IvH RE@g*je*eUcMAzh=4MAzh=4MAzh=4c>͛Y*ǤA zH=$IA zH=$IA zH=$IkM)fJRqqz8^/Gqz8^/Gqz8^/Gz^*!1AQa0@q P?⩊d#1]c1]c1]c1]c1]c1]c1]c1]c1]c1]c1]c1]cPa!-G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~G~BfI,땜a0z=fYa0z=fYa0z=fYa(NK9Rqz+Hj1Yj0x"gYⴋVqf/Z|VyŚ+Hj1Yj0x"gYⴋVqfvĉ~>(s,NLC>\c BmH* j0wFITE6g{-sXX"gNkj9O{9twZ{[+x_0 aq (seV5;&j*߶4 YYHg3l\K l\@T3}V7uǻAXABZֈtW#zs,` +d7ޗvӴuo)ynT7z{5%wۦP`$k墄fs,`֟wF0ALnR7w_ݸL(p=gV%7l=ǚ%إ"Tˀ,%$M]+K d4-IVThSdPy OԊ@W#uqft ֟w[)I8Υ.H:6s9zj1Lqftn`>}lqMl-eT[֑t坳&YSoe,@ RfC:닱Tis7Z{ C$01p1p1h2K%GeGd24"TD̎ S`J7Yj0wYcY/ 2@IaIgJEҢi[֣4qft@tcSNH$x  [} 1Tm˥Yo5%d{s$EIYⴋVqf/Z|VyŚ+Hj1Yj0x"gYⴋVqf/Z|VyŚ+Hj1Y/hKBA_z=|_z=|_z=|T`Ш A 0` 0` 0`` & PW.\r˗.\r˗.\r˗x"JB(1~c1~c1~c1~c1~c1~c$$ Rt 0g;B"Ю4+/< 0g;B"Ю4+J1+Mi_|FW)YZKLz("gJ]B(g@"5W^#UxU5W^"Y YJ ˞sywFv8cmHP`Vɕ!&^ @ް4+ۼi:4pIJm tૺ IIR yۤ{;*$*՛hJĴrJ(EYJ[miI rQ̃s;DL&(œ&Lț)ȕA)U+^@Llߢ PzMCB_Lz+ Vc8P> II/=Tr/ \MPޭ1+:[S]JƸX-ӉH.xsv:Q*+;BtaNhQQ@&@dgu/x&$flidML0V@"CƁn*&r/p)W.)Zr ڊb"%PJ"]prn'2.adOz)pkR-*leV֒D EΓ4+GBI#A*3192eM7Z\`- :E,&QEj|D܈dS@t3PA4y ZP6Js Mq*)Rf N$Lܖ%Iei.qyG"L[ 5}`rIЎ6O $`X9Kr{7Y[ǥJ"[tb OA``4+K|‡8f@0T-U$UA>R#$oCX }}P`3"ͯwݩrHSes٭쨐Q`K.` OSK<0RNV0wB$Ю4+/< 0g;B"Ю4+/< 0g;²      "A(#QxE5^#QxE5^#QxE5^#QxE5^#QxE5^#QxE5^#Qx |z=RTC!Hz=RTC!Hz=RTC!Hz}O&L0"`D&L0"`D&L0"`DA}њ|qY#8;qZ N+M|qY#8;qZ N+M|qY#8;qZ N+M|qY#8iL~orGnq=΃rƁO$ S`܍% 3Mlf8vFi<Nk(߸*TGm6.h175QkcEw~AlOV<3*in&nǤ"P[7ڨ+p(-lN] 6ͷkWrv y|nh>HJT4A:~$ȵK&+?[k!6AC8uSݽwjyc7,0mʽl:,[{[Z]efsb$`l' -Ҿ#&2g&xlUu-> g>73 :X^:Rc?uxd'`C']h jgu٘Y+kdZ)e^ۍ6|xb"!dSQ.`foU3eM -m[J[t1QBa o|ngEce9Bl?ݟ^dۓ6viK !뻵/f0sfU`uU-^];z֬:k;bg#70ꮕ6 8 W>Yò3O\+غjDs|@Tltu;n]a|˱s}WMsl>5ت5{oK60 9E<uL{![ҽ %$җ>Ik;u;n]a|˱s}WMsl>))=bՄtmgj>7c*H5/՟{#F$vܻ w]w;ʽlcfo jS%ŝUD"neո|n*u@hzL-!E_wd<]y#mM 17=cguN2mƛ'ٛlMn" qg9$ 7)=t>] dpu;kq.j|C]w;ʽlcfo:|ò3O3snzWAqGjaw#Q/h17(7yڹ0ްh1inh)JxpʟI2======%igK/ϖp'g>8ۊbqZlVp'g>8ۊbqZlVp'g>8ۊbqZlVp'gb(n~Cߐ=~Cߐ=~Cߐ=~Cߐ=~Cߐ=~Cߐ=~BRVi Rʣ ^1z ^1z ^1z ^1z ^1z ^1zN:)!M2D$H"D$H"D$H"L^: YcSO5?cSO5?cSO5?cSO5?cSO5?cSO5?cSDٙ m-DdJPYADdJPYADdJPYADd|`$τ\IꝘ3rJ`zbjgʧq@sn@R/R # Ԍ/R0H瀰F&|#إrs~ydJDb0IpͧfsbIMM(J՛7tl# KՏӿ+) 64XcJ֫= j&5'ܯ) DT: :䞨)*t"֗a<)I?đ_agNY$ 1jDսvw6H"\V^Ts*qc|b/xP$>TTSE'D&ETncf=c\Q|RMFW*WC&XsF;%z'#)R5 W J}#Rd\euApPs{sVjM2HtZUo`rVB `GE+NXA RRr;|5F dEhT`ooj1hh(٭AfMj,v5ʛSg EV6H$ bWmVj~h3/Wʄ-UVjs$ʎS(n%X- 9AL띳$b "TXFц;f}.6ZMQ9MxĆIiJ0jW~ 3{p)esg*n-kEw9d4Φ6[M`@"ck[U#$\LXki9:dN h1E8LS-1%3ad ƃe큈TjC5w12 `hË%V@* t|ũDb6RgYJ; *Vեiiv @.]јc5XP)昌ļM +Xԩ`Q-J¸#H\ęŒ ֢E'((Тa(%7Ҏ@PZЗ%>yd{fs_ɖ5 O,u앎 VKvNZ܂ #VD_ky` g~Sr2;h(TUUSL Yvн:\,̶ِ͛POLIBwT!@W"6a͚_{zJKYHC 2I?, f[[fUͶ:_WbS4$BU8,ҹXT &;Y.=/Bnme,&eZUiUI"m $ &f]63IDb}E $JS')?3a Ĵ$yMsy3 (G%6m*vQ؟!~8>h|L` q,)yk'$Qȏo&JlUi.g)9%'C 0fO6KIK1:Yek7Q+)AfYek7Q+)AfYek7Q+)AfYeMAAS.Iy%4^cIy%4^cIy%4^cIy%4^cIy%4^cIy%4^cIyhN*qJɰ%6l/'5kן?#^~Fy5kן?#^~Fy5kן?#^~FyS,ڷњl yO!Z(+VΖ%bB,;fK˲a(w(@ T:y,PV(g;lv$LRf-s6Zv Dk>S:;]h%TMN_{HRs.ƥ;2^]`m9>;@i`|w24lv&vĔSOYΕ/ZH>k%ڌ hL~0NšŤs<`W 1'oA&vbou$`dBٺx6dA yq @dCa_ܻAO5y3Mh4>!8Γ{fsb@e LVbr&1%n|׃fK˱mFGV<3;I]96%b2;O{ &vchU>~$.}>{s2^]rIӖ#~J$N11j{J}i;OQ(^{olnmUQ=Ȩ )@Ez[+=^ /.@TU ]H:Qwܛw^J LY6٭P 2[^( *cD骰٭I"v4kg<.=J^i&CJ%NdyrNUe;gGi=V{NQV{NQV{NQV{NQV{NQV{NQV{NQŰZR\=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g=g$e6svQ1F;(ecvQ1F;(ecvQ1F;(ecvPXĢQ(J%DQ(J%DQ(J%D- !1AQ Pa0@qp`?K+~߿~߿~߿~߿~߿~߿~h-QTzoO~߿~߿~߿~߿~߿~߿~kŨ=7߿~߿~߿~߿~߿~߿~߿A$0U >߿~߿~߿~߿~߿~߿~ 4vIUn͋,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbŋMH9沓]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]g]gG(@ hZʅo0jΡInJt>,<@&$*xGT 1υ: Qq¼$B˱]۠Ę2HP$!UI o0tlwowcTQApF²1ۄ_`X @4gI2Ш(]q x"@ uM^ģ~S4=SWξhO-V?)N+uCD% _BAQRW`n{v4y-GCB\IA&FxX̶%`OC1]Z}[jY 8|hg% Vق Kyk:^9މQtr8;(6tk>˻`H-&3aq*9luwx#{ra]g 1MJ ;cVd%i@uM^3U /i1H.S 0X`ؙ- -\ꚼfqcLZDJy% Ϟ벅U y2Lj J Fm%=1Y8>3Ud,uJDIJOha `&³Ue^g0%&"-"貅ߐ @0N^Lv`K`^3N]>3UQºX(.nܪ"0Yt|1.ʾj6K jWG,>.-N$<]@@PI(+sX$粆F}aVs;a\uW_.EB]>3U ],kiсڲ,~qEۆ!e ~g= Fr2l#Pv1ĦƳD#k(o .#0X2 ?HAk< * @ [X`LO5DNfp#34.嗡V6bl3tz7S fhcrjLf@5x k10iHoK(Xr_j_VVPp`_̊9p0 eU/ꚼfsTM@qGzYBÒ>3U .@)de7[,b\!p_bꬼ& k& T$'ꚼ&uã\0kǻR\Lx!q6Po [BɊaeĽj9 Khw}3jReꚿC;,PK=8>3jReꚿC;,PK=8>3jReꚿC;,PK=8>3jReꚿC;# ְp,ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|^))VV#tGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtGtG'>VD+0]yŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbŋrEhduK߿~߿~߿~߿~߿~߿~:#̂}b tT7Ç8pÇ8pÇ8pÇ8pÇ8pÇ8pȀQ G@E jիVZjիVZjիVZjիVZjիVZjիVZj騏Rա` @ @ @ @ @ @-͉c[ty 0` 0` 0` 0` 0` 0`Xr0KZ p @KZ p @KZ p @KZ p @KZ p @KZ p @KZ p @KZ  p7ϮUx;]u]u@!A- jHi\E^M@f1#jtӛ*x9I pl[nݻv۷nݳʥbM$q88rBdǾea1ON%{3Zj g9[J\"|p8Fݽ-KXV$8, :g) UWwZ[h#[xi. Pmc 08"K(2]*.uqM>[A@B)s`"2;<rw(KgiYZ{k=8W43l_@*q8FtF/r\g^@a7r3^(M2qLfc e# fƢAC}D;|d(GX+)Au1~1j̱o3Fdd14E6bn1CbO}0Ì'E$/ RhѣF0+>r.T!c Fa@ `oDZ #` FEXe x8;g8qGgŚ_ylbJ!-2`3P͵E^3AԎ)*(J D٠+(<¦ l_]`f.SP8\B?#Зcb]"e!- r(`h=S jiq ac5$hZLWk] PͿ !c%4V2B&9* &p4ĐvCA;Ab~pCS?.uU$OIB"ųu'AH˖6)z8 u[; Y׵o1nC)f`#Pȱ6jˬ)Tr02w ձVr( ĒŠ+k(_C]((.qe@Zq+RAm$EL 46% mH+gB#,-89PVWnS.BHLp%q .8TR "qM( FnKlX((oo`b=Xwbd nw;9;/O$(Y,18FN,h 'N+RLǔ2sET ' 0\ X͔#2IHLl8Ph|j,n4\6w LpQV.TV[\nKo\x6N!{ ŊSq|ꬫˈ5,x h`]&u^qV2~!P,GqDpi4Z@8.usf.YƢ3ҷmg!tI[mLtud\ 2^@8ӵiGEМ ` 6Da*AYRkPrQqK Y@cIRZ;#nE|7F,c g@0֟B؛55mb/ {kО@B0ǯAv >Dȗ  k2R?cp r$TH$ LGeГ, іR&%uX4a*% `ᅰ_JAEC5!qJ6~eOM AT%tbOILpX ,.T9PUUreNH\ n@Q"J_oIP  bQ6X $"H* d 4u7|XR{xC4`(yCz CrBl,dlAs7n`88H @4}*0%l34BP>da ,B ¥ch p,zǏ61VHY)7N ,80p$0o=b!`էH{ IB}:HS}6@ eD|qj:h͟]JZj&kdX-ͺB-,O.#߾ Lb 1HwS@Q!X br  %W(0I9`D#M $ޛՁ]/#%u[P KA5 GtznwBҤHD=^YnY!,($, @ @ @ @ @ @$ A)(VVۜPxJ1wD$H"D$H"D$H"D$H"D$H"D$H"DyW ҁ**o߿~߿~߿~߿~߿~߿~ߌL lWN<SK͛6lٳf͛6lٳf͛6lٳf͛6lٳf͛6lٳf͛6lٳf͛>̍BY߉xw3"D$H"D$H"D$H"D$H"D$H"D$H % RhocyիVZjիVZjիVZjիVZjիVZjիVZjJhcydɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dBX(/X-.^zׯ^zׯ^zׯ^zׯ^zׯ^zׯ^& ]ʪb.6c>USQqs沪5TŔ\m},oUSQqs沪5TŔ\m},o.7P8G!'X{4B[΃93SދhG #H G>!ṙfCI !AfCɄ׌rPUxF="qUQoĦ]\*ku\V"U)+u{%%U-J[p&d ;1 /&E s$ǚ!A.K50Hp d7ջXag2VJ'(T84W?6.7V&YKq-IQu\WdfWN(`F ]!Hc a +;X}Bj^XXhw漥FLdB:svJ&2pBtɘ;lnY )p) f).m>ֱ-;n=..#q0 Aķ'1d*+\#H7(x5R%&@\H-A!uM Ҝ*f6;BVFLLeNc@G miPEX{$YgsĢdMHʸ$$e{.t27!UPL(kKp!)K(TsWyy3 aBKf"3~Jd8>1(-Ibėe㢱KP w @׿%WG8R OpI!%H@fܫ2xF_6K#s0kaX1rTF Ewh(̖idќbJ49ESpG6.#q5L`D&@EU+9-3Zn%@2ds46KD7w~LqDkI e$.P߹!b7&Lj- GxŬy}s!<dƢQUo6.7{DfBanfNX05 #ߍh̜z`/$Jȫ!wDeդbN>BCV1䌅&;Ty$HO'>$))S潶HpC' K1.UnZ(XD99lNr䃈 04L4 hQf9Qa`0} J"8^g\[y|+[尴|W>fȗ}6!Ak%U0ؐW*z"Y;/,&uȕ Ք7xG{`!b.veƈ1LNb&]clDrCvȖ|.Uj^y<"MlHg'/YV KP!Ȏ ~1`0]x7䀂1KQŢbF2"~^8=}u` UAr^K %:kؾ*69th^Wv >e3)V|2‘}v[D|d2t`KHk8PFɄ0\F;$ / s\(?[$+'_;F,<&y6SVrm0XB6W}Zldt`2c RkxPFȰRs@;&0/ 6.7{6|a%,o5Xi'2V;8Łťb=WXs( (w¿5j lG0ڎ( JPY/@:{ N<6D5Dqۺo'XG/E_e#/9OHm LW B ,D|lvvׄ0JsPwǷ2%>Aelo PSl`_G*a Pv8Ï?5dX"Ȉlȷ|UP0]J8{):2Hߦha'UNE8g/ Dn b=Ȱ* Ta|u1~t#s9~k )I .pRnT" vVp"x m,B6&,A6.6{u]1k(Y*Z *P~iTRр>Jy3/ RG\t[jSELTHϸN!F,C @8wh+uQ1{:REy~͊6D ҟ@Tw5ݾb\=EL FȉխQW4cV*}`HE8 @kl,X?06(pJM?w&bŋ,Xbŋ.OP5yߚʪb.6c>USQqs沪5TŔ\m},oUSQqs沪5TŔ\m},oU5I*d uE:QNTS)uE:QNTS)uE:QNTS)uE:QNTS)uE:QNTS)uE:QNTS)XRWm%|@ik\_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_jk:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U:|ϣF/U: VW[}W[}W[}RXVf8lp&hoZFS-|]Ow M8 gخBN`.ފ dHBݻvۉ8`@c7jb[dMh'+85_ Tb`j[Q (L/J؞DCčd *a8S)SU^<_#m4SM_NK:%HB& .dTR"BK'i:a! }]'8{Ge" X;NsZƊ]`BԼ;78Qy#>DJWb;,b&iqh1>]̇7d볉@h VXd,[ EY~cfm>L^w#!|(" ;@{(XM*b$dnPB"Y8>G-fq 4)+us|wY 60 lDq)bDeT$ef,J-лp-`U{: -sk]bPVlGc$./Cot–w'8{),g82咼# !Kv~   ɂ{^Bw ^JY\gf|GOZǥKiCPX]Ы1Er3J:'ʭ#IJ\|#Sɒb\Jeac6X%ۓpX-)jn?̋ܨD} Q ,÷ٖ#= Zfq\pQֆ ǘ.{Wh$g4 1Tܤ<'罧ο0v\j3LU >ɿ4 <(c.fɇO >Q%Jl]_^|Is[+bHX@«2;'8{ $K[j J`;Du?BBXј K$oigb^BW 3BqO4Lz>sϗ}+qq^ԋ.}mY̩48%tjd ` nyxɀ8lGܨ[%W~@$*5?M:&$Ȏ#Rv`02{{OFLSB> P"fƉ7-!l"sš\2 Q5( ;L'dYL1V }Z/$UW-1AIRu&AW;F/USʈ5"Aa/Ŵdͷ0%ل3{{OFLQG4AZHUh3"ȬIz̰\|-yp q"ԼEgPP`xck|\Jya,Y,P(r ,pkjݐ{h!+zLt9#oX/ b՗ Nqa,H(:!3an#IH:qH2 _:Chp 4ʼn63$¡㡒>E$2ldj'e(3bs!7o B F LH bEe^@JCT/X)xO z>sϗ)5!KOJcSrױǴ% 2M7@B ů0 :DIi~,^#S)Fy.i„ձwbu Ո+t[;!$KUEkA2Ml\gsדs_ѸS.xġ#B$p e"@JVJȜ`=2?D{؜(D'uVŠacBlŠL v=EꮱˎhѐƖ(,(N)!4ٷa!^<Psϖ(cI4v#S)E) ec O3:ęr4j m${||>[H/Hp;bR KӼjb[<'؆uNqbT[R:t=UXL, OzܭTqA, 6&ɦ>_Ev*ar $H"Ic2\8 w ,oi$0Ly>sϗ(XyX $Mb-Ri'R\=My4b % j s yKN2\r51zT++xJ8M>C_䞝@"0 ;lVJV0FX(,N\L႙+Jy,$y{OGL Yd>TVF21{؜hDxck|,RČoQQZҪ󑩋o{$0C*]*V!d8n)wx˝`9)tō@2҂Q X 3ɖW}| z>sϗ(M2Z`uX(BQq"D3x.Pd, V*[W<y/1q @bԸ3"[Kqܡ**{{|< 912VMCfgx0eT[^(^QBAZ }5gi (> ؑ)3&xx@9ŎZ7D/5''Mĕ#=vϚ  Y`>qطn؀Sg(\ErBl5jը4c-m5zbO[B-k{&UGXՄ1-^"]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{OF>]k|#S{SjR6VZjիVZjիVZjիVZjիVZjիVZjիV b 3_~ڿ?Wj_~ڿ?Wj_~ڿ?Wj_~ڿ?Wj_~ڿ?Wj_~ڿ?Wj_ J*Ǐ|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|帘"ELR\ DڵjիVZjիVZjիVZjիVZjիVZjիVZz<)OwaX` 0` 0` 0` 0` 0` 0` $\&?XpP8HV$+?u À:aBG#XpP8HV$+?u À:aBG>V !_aVVC,Hꭀ3htO{˶4h`% .%[yϟ>|+Aj x#IY88 Zڱ`eR!3V@q80WKkHib}?E⬫ DJL/,ibT<5J $Pz6_ݠqTUkףB"vo.U 1cO&FGph RP2iYd,R!V.ڭ\idRSYmTg`,lEUȶ þR-ZOpsQjqeqMw  6P-4)CIȐfA`hv1BȍѠ-/*JgƠ "K 6|@d8pclqI:zp MM7 ϋcݨJ2/79/,g0a*$|kHz`>.`._kd`tf G b`"8df٤FVCX0bc QCJ 8+B"A@Z(-I ̽f30&F {rJRy-2ǾVf($(4FZFYճ5w9|͂B׋Kz.iR Y2}!8Fq\^G oJ10H@vS,FߜgB_cZV=4(p/xwaOtY.fE.7/Gu,ZqIO1S) $7+[V{qڡd [[#tK" Ӷt81X`|o(>\8{%?A :@b ,Jba1\uܙFA@K͜\ًlu]3r?#ȍ <Ť':elkc)pF]B@ [{m1ja4-t98A =06/vT` bVʷUv,vaH@Epb}v.(2} ͆hG`&ad(٨IPad>Ӿ!"QLXW3ģ@ K%ss8mfX܁J|dEȒ l3)(e2+HǪbY~V}ȴ6K9@ɋ{0?x2"c ٓ Ssp >p/_p"bT詸 `=PzFBF3Pc-7 |gK*ItYXOCl;p1rX#{潒iS]w5JU ^x%G/8Tt }k8QuH,[X2ug  3&:܀1'Ħ$}d Fד Vp VtofI]A_}a20b3`@Xy\FT3dʸu~Ƈuw*m/p] C/x B5rub/h]&4sތHNO\ʋI1`-;˰H!5>C4:@(Rb(09LX,,2` {Vzv:ή/Fdr9*%WU`8E6s졖ed1|Q])Cy.౴, '8h,]BeG &`/$ )HrT.!!ąL Uv0(Khax $F`#;ǣ[UF]HHJE ^[b@.O8CӇdͲ?>7AѸ+t=;gWw| lecQ3伓#s졎z,t)3zKjݰe<_DB& &pqR8bf0PVgvHL)..Smf.UY |͛#g҆1`laƹe&I󘗱1)OY2/.nˆm([:& @qk|e=X'DT;D0]qR]89d0#ɛj]O`Ŷ"d/+j^/F6.+Iv_BG C|6$BY.]qJM3HdKdŒsV4Dxwk*R1]yņ` P򠪲v-j4&_fG m@/.[:W6)dn<89Jg łÊԂ3& ZRNYyv<73s=BC%-@cg텬jmVzv:ήOm/*ŐA"csvL#17]WAsvbCwB2kOIٱAn^s<NkqZ0U0nc*Wզ_ [#싙j Ȫ_nU$CŴADѣ!"&"v|zeO1ض[2@NY  U)z#%.:_+q{/~qBl8AرǚW@DiT`,Q{NR1x`CJ.a k72`6b$3t;+ 0I$WqJM٫H3Ooe Ƅ 76рX Ir<ģSR* jD)*,  ls Ĥ7 (PQ X@hzt]Kjۇ 3H25G^@:VZxA!P?1 X'pu]Ɖl'ejk'<=B88c7--/Ŏ8]BdPoUZLHeV #X ΏFCQ7,75:ʲ$^ː] PWr̤k!c~Vzv:έ5?Uc]^b`8HR`ps8Yeɹrfgg0P3D1LgQ)^1 bu lr [ rlVont}6œ&B@@BYk "I/pMWlPpR'l|3" ;&!1Y2"X9g ໔p [Lؤ 8.eR.{)aqh%%x>bG*g_P.y:Bpx)N#0Pbs6-ػ2i%J S /D3P~*]P#³kHUy0UǑCΧ2uv$ΏAJ*̔X<@`QEQEQEDw/`vm6<)%a4#YdQ"r3M.ztE qnAX" I[caBUŝUÀ:aBG#XpP8HV$+?u À:aBG#XpP8HV$fW\&+*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JRԫ*JȐMinaWB4~G4~G4~G4~G4~G4~G4~G4~G4~G4~G4~G4~G4J娐 4h·C~G~G~G~G~G~G~G~G~G~G~G~G,Єˁ҂Ib`P[ypappl-1.4.9/testsuite/portrait-color.png000066400000000000000000002544341476704353100204060ustar00rootroot00000000000000PNG  IHDR+\gAMA a cHRMz&u0`:pQ<bKGD pHYs.#.#x?vorNTϢwIDATxw+{o#!DRbV[[)--U5iըRRFR_Ğ!"{''j4!RR,(KK@YsP}:T@@UM6 Pݯoɴ!C{Q0:H<@uwd^γ:te]&5_K\׷+_s'rv'>A@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@iZ>ӥv]ELɓ?3f؀fMX,mǴ퐶ӶCڴOi6I4dL2yl˔q>YrE`tϊ+f <8 -6mxq2bDFȑ1"O?.PY-Ȁ,bX1 Os\,{~fʔں/y鑼4ggq(/20+~=+lOׅ*={?_?b$w^7o2eF!O8/];wg?5k(eo[*4Yrϲfe;׿+2c,44kտ^}vY:[KsŹu0͙=RT7rfΜЌtdak's.z>[!YxfK}9K}9;.}WdxGhN.w=+ B|m\,X8 ~wo٫W>8?1ޞh]6eˬ~VX?+΍&Ьzsusձ[v=>z&kl~j-p__zK@M7dzzC'gS_4`B<$Y:\_'K1C/ QQӧ^?fϞ- 7~}rylqurHϯJ|Ey _.jN5b5P/+@(k:{Jֺu~wJM|6z9PGާOOgmjy7[zdz҆9Pi *G=G!j>(}K瞜xbv]|\@Z~KϞ:kԈ̯nK%U6(=? ʡ p mј1cDiEr9yGYBZ0fُdҴ4 BN;zs:(mZ>%Sys1nqD{pC:H2g6m$og>[?Mbʁ捱bE[lO^%ؘ^O䭷2aB&Li.=zg,h\3{*<8O?m@-<6g~/?Wӏ<DzYgRbYbou@:>wjNC4Z7?~dG=9ti]4"wM)1W\k>sG䪫r&dr)i{q{o ɥV.V4 !3G +[͙]vɽV"W.^&!#36ﮋr*1Q.0?xm)/\{W_}oY@xleLY/llYgeesi(ʬiӲVg;ԪE jc7ֳWșfܛen7 zlO_C 4k깺v饗:_Pky$`>d^;q*oSN)|nһE5肟W>oog߶SsqvYfelIЬTCC!;N:U@m?s3lhQGeUr%l 'dҤg݊4}Rn3{VyL^>\׌6gN1]t*$;\=3fo?G?ZhTԱs?s^z)뮛_2fロ /,|=,MOܚSvɡ+#2kcZOUb W[maÆUr҃>N>}Jo/ CsGzkS8{j]g돞7;w`^ffIPs /׾+TrC93M6sf&?ɏO]vg7?ɜrtP' 'Icd /^oqV K #tnV#<̞=A_ロ-~3th.lرybpPffOyٜpm\N=WG 裏~l4bD̞$7ޘV7-9[ rL]9`.Ȟɜ&+fp_R8\ꪫ:uTN<#8te+Paò9lEƍkv7vlOb (pΞg幷flq%JsudW<3`Zju9?=s책ybWe)UwK>a9J2aP)zlvXSk+s=?q0?%ާNKSil~]Lt%S՝wlIA[oVOS="Ec|A^i7^9C%$e)zy˖_|2,#/Zk5׿uYdbǟ8Q@ :JE >GrmM6گ(Sգ=zܹs[ '8{]ϽL@)?w.ZO&`N>g4h[5{gQ: +wyM2T-~_^}]vOs);9>˭]ȓ ΨM3T69i8et)z~m6GqK.W]uo~-Z|g>͢E` ћd7咻l÷ʀde)zuQnw}s}rq+?szi׮yF@ C>[2fRvicqwݻw1Gqĵ^۽{YfI`آ[@+jk0 6h F+SsO=G_~?fN.w-[.9sn |wJ^_|$O*` sl.qR9d뭷D,{w1n_<)S TWwz5S|df,s.x9v6OhzW\9+;1PQʾg53w+d $9X6R<,-/袁o=nG{|g7^7,frVvy 29e43&MZͣ qx[ Dtر%\rqǵj 9~#?ѣsmb*Ƣuv=!n._͘W% ̙=ҔT=EEG <߿w߽;|=IZ嗿,v+HCȐM;͟8me $M6ڊK|' PI[mՑGd 6x衇 $:{v1.[\"f@:es39 ZF=s7dě9~i2 zZ7o/h(g|LN{}} ^7+n_६5qLN:3<HÜ~j5ݹnUO,c.Zl[6Ξ]vg7Tz qZ([&3% u}YڤmioBKw۹g90f $ynA٪e?|Ƨ9{PQ!Ξ_>}⬳2amz`v]o7 2j# $5;l| R/Ξxne뭋b|*պ9~{E}F[vv&,S8{ Q$KS Rccn893󇫛l-riv>Y=GeRZkbg:5?4nTN#[MO9M6AgY9*B=g ̛o >3gJ_gh.wXwX}[98aU䊣0Ip3M6Zҡ|ɜFJP@_={F?Bۛ#չҼ0Oq9e/يP@>:o_~)o9jl5yyi}zo\isPˑGVb(oٙ5#͘W̿kM ]JbluN=M=LCȁfMl_6;?W+lyC9r}?˕fM=X{\tQZ\9ЌsM!?Ïu2NB;);)r45פ}EVX4_:_:gWk2~`7hK,]J5h)hJK,nJgbd 9l$[')[M˶fE|㤜R<4mI/ kl5˿j74T|a3th;wRj_t# aA5倻V+D=_LV|nذ|{R $&56f32aj h\29Zgg*4Ogm2kcrX}XBPcθ%<ޤJQpٽR~lY&L:Po\Zecma@xzaSZr5RD\G+Hkn^: sdϿdʌ&OyORs}t>Bs 7̳J kn 'ݐ;|7ȕZ~yd4)l:`^~4YڦMm6?vӭOZifso2Tg^ϑ4 _+J= '?QGUhiӲy l ~-ӭwzK7W]>K߻}N;/[gFitZkN[T1, 'PfV[;qNƿo?3` kfКp9תu~rEZ6r Ӫ"B6-[nn:Pw~br3S x ?cZvZK||'{ST)sҎi]74-Ro~Z4ـ=:}JPmu.$+$ɓ馹6Ks+4ת[SC3wfSxY Onys&MʦԎNҫf= ewȡ9o F;G>x}ᆹo_y$묓k2Pn?7s>RH*$׿kP7wYԁ0Bt]XT)$믟+:Tb&dDu B=@RP]7^+1%d2mԁ2V=v.:UbO.d,us0o9׾nHΕc9:@34mm]$ @5RP͍7V;qȁծ"');Zԣ|%7ݔ.şgؘ .ru]Yw4H=@Y}|sv-|ٳ"2L*3;ݺ>ь~\s*t)'[nIO4eJ &r$h%f*C[ңG6} I/ŗD9zJYDo6㏋}l- ei6H=@Xazkz*|W_͆fH|h-*1% @j)jgذ,\]Gk>ua%&zaPsԴ˰aݻ{,묓W_9ǬMwD9zڵ첹SDݗocw.UhsT+5jРv[Y 7qD4YzZ؏*=\/=bPsԢemeE k2E@SmPp5V^~TNs[8T)5g~{/|.w3D46dU W/u*ۅKҺM{bX̶pyMZҹ[D "}ll}d8ןWm^h,6r3>v߾÷֍ǿtn`_Ҳ5UsԐsmׯ=6&orڴ{f=~Cf4_ܚUtGs|ul֍=sԌ%g% #r1ʱYa̜w˶lʎOׅ*:#2K꥞&nKO9t\Y͚~yPڶj[f-3!OߑλIl]M%LMVUM=@7ߞ\+I;ʾZ5P#Zz|̣7'+ ^Br/nˀ2gճ3sz^}מJì&Sͬqڕzۤpj9٢2p$>Զ}Y#ˬg+u/? og{DT_./ŗKZZ5WکZ,nˠA4mڽbG͞)2e\&~ڤnvҾsڿ-}MkOޞw;T;U曳b\ڤ[t]{qQ$5V,#]yv1Ps@il̥?A=T#jz*O'R P=&I;fN$9J̙?$@-QUʣĭbƨjpٹbf?q$=E4_'OVavN+w\( jzhfL͉f sny1IPs@s2!:>*g zQ3^IP?s@30\ytn9Is43#S'f]iӮw\wbuBOrC9hffCkұ{]%ˮ-jpO'ΰ?g;uK=zfw:d/Ȯ'7p)+{\ut::ˬeYi٪vչy1Gޣy$i%_j['ɀ՛-^|$3^מt sԈΝ; `L"'屛IҦ}YnWӾS7{f^|8#Ɉ{2ҾHsTW\!u$$5=ܑgUIVYh>gEπtR46f̫ysDQ#Pfpdjx(zjȜ~)_~]3:}tݬ=3fd̚3L̈́bF=Yezw2׷8m\ɏ E=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPF=Q@isPYӐӓu۴n#L&$ }-tK:JQ@%̙+}LS3cjfN{3f̏|Ynm?]:L;]N;dсYhh!i{+y(y8y6>n|2m_&_ݓ%UUe]HSյKˋ-5t䁊B?ݟWϘWi4f̏v֮S_.}gҹ#Ui;i&ϯCߴ<_o|Af%c1sNɗ?u4\];\|q}򷿝ӑ 1yl ?sgW?%/>vQAzpό^ _#ɹɵ+O4%+?vJMvOs! 24$$%>,9"69>suM=0ƍʍ-͔q(=]Ǻ@K_&%m.'$?MΫNN~(2w5gr!~$3'9+9"[LAcrB#'Are+>%Y]Y7PgKe3T>sK=0/]w_@nONMJ X_/u{.6K%V#3s1G;T++2˷ _x ۊsE=WڵKǎw;wv׼͈ |oӒ247O- %RG=W2~|Q>2_|fm? C*~ڪ"MC3z4n\ Ct&`dޜמ,v ާM;a|'8xU~B\Vd֩|hf=WOŎy#C5k[ȭ+ M=q5'-1̗NNcaelhm/cf= wRgv.%RGsH=԰늼jȦd 0_fKg8ҲWϵ^t(ld\=Q#Pƍ]>p|yZk+yiRۘ}C^c+ha#z-J=S3{f!#\d 0_S na1C+ɬBcR/깺Gŝ=Jؘ_;. 1zv{(ԂV >"lR6#zV&'c(M_s2ȇh/~$f~ |XEvFtDz瀚t ۪MwVZ 0޼6F8d bFwEznQ_ۨG946+ yg F_ɢ[jEq 1 UQq\>Jz+X̕d37Xܙw.peH obf^ȍo_i 3գ=ҮtrteIŤ FX୻2Rҩ/J-lɩ %Y/zTP=V,]92_j"f!mo6ddv1$y-B[Sw3ujO/ddPre2_H`%mڥputZ0gvS~;jQE>[='%',WNH/>/,:;9qdɕ?Ξ?LƼ9 x_zY~, T7̔ Ӫ NvN.,~G_&_#P䑊ǤPsu92ロ)S5uꇿ93]W;:,yvҢł}3g3iL34rqOd0߹sӲUY#C6ɐM8=.p~;}1CX:9,9R=|5+ujvr^JmLT+NAg͞M6#4ӧ7$1CfWTu@MUsKk!+sr99p`Ldj^;-ž%f?;&{ǞnpQՙ9s2n\ ׄ 9,d~ b̌~:u\̞\vr}Z)i,ޯ@}kRn9|/gΜݻdg=ц7iharF+CӖPi33 u,fLPZ'HQ;䆤#sƮlٳsq`tuEx.b_ǍχAj~<}TKgevGt3ԱvIM>ꤳċsez;̗ns̡n}>I9f9G1u|(\fQ2gf;ط)3ԽN I-=mrNr2G=kla>:<ԦΞo=0;'n4fI; ^$(pE7Oe $ݒے kb_$${:̅zU=dΜlqF6m;}UHc.I9 ~ïbAb>=!ٯbdS՗ln)gu֌+zTe,:uS&>YVJ |D/I*˓K^$󤞫/u{٫f3f%5e;'$c^Wk,sf2meŎs\TCcIJs|lufδ FLݵwLX~1ys{[8K,f`6MOVM\\,suT}߂;>VԈ [ [w=w2s*vV ۲ɽ/񅮽Ӓo9Z/\} .1XP &S~N~DV Д&ׯ(I p/$MN6 ?i8 EPWƎA<2W^)z.j9 5I9y4̶X&i,Ev鰨fD/%%]z8{.Iccv5=$ n=Wc?)i.vAXO%O5,.z3mZv!Qլj 'Q @x4L-p^_KU ̟W$w4 |) 3M=WGOϔ)brb*4jd jO)v ebrXlrq3F%'_Mt/:spQ1C P?#uI2W.̌"]Y|+1ddz5l}W}]gSՑqd13ݒ ֌2_OܚW5Ɉ?;2?LVmlCcR]Fۘi<鷎 ?9GѮNǎ3",;zdL|_o=K۴Nϲjk2ydꔥ+f`nLNFUJ YuMp@3cN8!'$oNˡJeK/6Je ӽϼ7xV+ޘ7浊v߳1麐|#/vmw1s399$kHCrtrSrQ2q\Zw:wί~^Myc3ɍ jg-J:}3? i\mH_qM-gX5y"'h?307/&D7_%_NTYA};s:(E.$y7:,DwO׮ΙI2yr&M /7]ロN/~aQ@)[z|WY훟˗r~u[W.<4FVhsA,';"IueR{fܓ8cK碋r9|g|rYj VʀYz,TY$-Z,'3kV9\tzOYk*o`~sږYiU[s0:z[;tWS :H*%V;xaFrU&QϑdȐtSn=?Y|cYoj +k/:WY{7.W]K/Fȫf%&=},^ ضC~zM}"/wdo[;yRX]O |&sj}7oKܐx+{_믟g9眼b^~9睗k7A7z{[9 Pr%UܠMͽM䊬u%va+; |ܯCꠛ{SɚpGss,T;NJqT _9t_[ň{,`pZb۶WUGvyTNoǾީhFڵgĈS6?(E%Ϟ[dyS:v-p] ߑnOevRKS,oZu4k˘e][Ҫ|; k9EӪ/cd3tY/OTXN1{F^|fָo&@OvH*|Gv?'oӒo&/XK=G3n袴K\ e M3ӻRr\Z1gvF)~'4$y9"ZIJK #%J/YI6MX uJ=G체m[j*+rվUN-DlRϪrS :H@dvSek&''U<-iD=RѬmUN9Bs}wf%T+1Ş'WzO|;~5s 1I{+5WdOɎ3*ޚܛnM#>d5+1ь5JP5*pff%+_nQa3g}[?RNvrTZ%>χtMNMIVl&'YuG=GsעEN;--+Tx գ]ڻ_Zgo81>Mѧuŷ3$9"XNN_/Jp]c90gqU`UWbw6Tv_w[][O0o[7*l-i y89?5&g%KZ'?KKU*XE=Gu8J9"E=K۵ss<[uH(S6PC]]qnr%RGsT}*9"Es˯W+PZ>My%^ZK=% $7&E?PW2,Y\tHDKf[(B=Gr§pT/nշ]k:s<<Jg9A $ grkr# K*/ 'Pzo>zHŎc2j渼xfS(]4N-r-ɐ_3+W|P'Y+B=G2$nŭPEz.^{M2Sw9`^<+';Š $I.L =W#-ܝO$Z.uA=G5YjbwT>E{ױ[f乓˲鳱$E]RGKnN<ɖK]PQU ~SAYzn46w=VvIYLg | KЫ..K޲hjzjһwnX |NCM*s }.m,@#N(v6=$9nݝ5VrESsTϞQP5:vM +@gM/Mr{nħb}Z{+&ٵ=5)Ig>դGJ+ Щ :F_-Zg@qܑIvꄤmaESsTS_=եύ{]:vv{_)[c?IIW ZN{2Ɂ rSsTw)v|TBϞ{2wM=T?>Š |)u)b?KƩ&9tkӊU=ƕNs*i6l]-]}o;i-J?w)mƾQY;u')HG.l䍚m[ܛaKƩ&Es.+c&K=|T95kF^{$N^:):,J &Y]qz֩S'b`1C5i"ˮ]U~Df8zx n ?-Hq ;i X:5N=Gո̜Y-'f2-p;.,g^z[W_ ybh!KOt\w \SQ5nubL{c%ԋEszM; +dFJ-s4q=7`A7uqkSQ5:ըbtp%T.U!#O,|Isstz`SsTg /;AU~ke*p;/c싏H%WjqM&?WnKfH3ŽqU׿.| TBo>)[[z5KȈ bAbs1NK&6{X:5N=G\vY᳸J;eJ{왹b2}"I Da#? mXҩq9!TbgA?$KXS弃*/^8~6.n*r׹Ң)5Z}3fdsil}w,d\bjޞŎϥ~c{1sz.9)X1Z/P&<7-v6IPh=W{ u7jTN?=[negj;{WbvoP%;ό_?]*N+~bzI}]j,i`6=M=6.n}:2rd?#3jTlCe-*'UYebx圼cf5kOc joZ,PצW.,vKE~hy'N+r|g:\;6}{ǚv>d6$+V +XP߳)WN߻̜3Yn^Wkϟ93bobPߛW~KVhg!+g|/5#W3wTh+mY#P^"S_)vÆOpgy)(yYZ&Y4i2lX}pZG.Yy嬲[.?>=OkҤuׇWoO>#={~=zmL?5n\z*>#2{vةKϞ-Ԏ}8򞌼'g0klwNcwY32=TtҙSsE$i2I^I2kF&Jd k8unnaIuGr|l,,yy'9?[2YLb SsڹԜ]9ǥm@㜌{3l.aVuk#y߅2 I b䄤3nR;9f7ԗuv:>Ⱦgb>ԵW/ov2 i\z$W$?9gdmh3u;.knC]kl e-yia_1RHH.HD=RQ;.#Sm;gfzu|7[C{L|Y$i$®W9jaCu]v][㻹FtGȈ ,d:V9Ox`q4îϲk.~2Z;P޽7YH@jlY?&WyV_srɒ>xY#nȗVsčiA2OOѮO(iNHDݒk/GMK-{ɞsMY.Xo䊴/ \^Y|?Eh)iUhrGzZo/KsEXҢeE;;-[9@Ы g߿uaygYhpVNLOjݵoFgo_C˷e.Çʎ39|׬Ul|c_N :H@ŵHvKF&%s$MH;̝z 3k娣"ս/;ͳȐ!-Ej7~.{wVYsۜTv;!9\'56d䉅i,-a%)y:9ۧ]t>}Yt,Yz+rYk>ˮezf䵧T˔:_~$i6m;mǴ},dZ" /Ȣs14m**{7$#'w d~39I2tUWws̯-ӻwzJ+ϚkOԢ6*Yzy HiJTi N֧5$vJ9sƵM8v2Jy6znh\rsn\vxj~}~^;׷2U/>UrXK@YsPF=waZovNii ,6v`J "*((&% "-H,!s<,53>=3p 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!O `|*O>>lm㠎PzҲN<*צcnj)c-Xt*us(اI] m49W;;U!XWVjˮۋ=SټO,t,ojGD@qZOT"fz_I.iZvf\آ[勪{ޣֽqhޡ׷kc!1K/oT#L=5ESb*q6;4c}q,Mc/t}p'_8 XrԯyJPd~Z̩w:Yi=}mw'mIŷ\9l=Q"ۑŭzn*?x<ˁcVlgt^b~-GU:qkjH뎻&,9&LmIkv*qFO~s;4]6Ro,d7[[j\#E<Φ4szWfmښyD["_^آ[V*x4GW/գk%r{y:PR*8'>ѳ3{ z{;^VJJ4_ֈJԓ$j+z'iDmm?% 5h^Q5aМ c(3Gg3tF4ҽo+O};W-.Sܣ?49zȩ#{56m v}\_a'v zӲ?}}P=pEds'PM}N7j׎؈"n=юlok&^τnDA<uurdz5_wQtF*(m5 ys+ȀYXkޟj5m\c޵9z*mCrs-zso a\]򜎜gy|37-@7݇7N\#GE{͝QpzcPJ[i{1 TV3hIVS`-uXm9@%m.}΁yUjW оcږ}GHև?N pE^-[E<-{pꝋOװ6~PWX-,(ԡ,㚺G%}YzeˡXU5fRg9zVgjz=m;W}/>oq[J%(2iV}nQ&^фEkJiGGU+4JQ W^ҒvL)ںBIgۤJ9LJx;g{m1_*VGBT!D-bt{uG{.n3_ߢ{j(:(==]Τ%>]ft4׈qճ}OP5SfR?МUъ#ֳR x7i+55p<[լ7S ?ت-Kcmցn1RbsݝuGor[/b+IDATB5Ѩ-znM׽&5PB)U[C%J6=\>Wmk덅z};_?9\ť覛4oȀIOѫ7i ^ľW>jqvR`H1bB%Q۵7{I?}od*\ip((ԛmzv-?_=Y_?wVH^+۔x@lܫCJ%@dD1fx񲹓o|ez.;^?F Lۨ-(2nԐdsrm> +zsy[ͮ(^6Ohďn_YQ.#;ÎjNj&4-_v|Pl3V0m;H%J :t,!Z0L|{j-vp7C[k6*AObANR3J-{X9`V^ڬTEU kն}eٱCĈ혥^~XB-Wo4ӭUx[+(АnҲ(FiM[b| 5K;ΣW9丂 !:Q xک7u_,N=+U J35j\*_gh$,ϕ"BŪb>>z'3!HhC%,+2fzf_mF5⎩[7C%(2iҎit7ԳTP%!2^d|뫇>R6vd*(J֦h+[n`')`G pnv`-JX_b?.;;[9gG?rhN-Zh*AO{oz$豹 +Q4a:!_?30Dguӎ_Tȥi%D<0>ŭUյ4nœJ`擥j3L;e-5>ųozbyL-i;EKF GDyvG.Ɠh|CzT5oBiIե/mnCf}wG0gq9KG)2`V=w".{F?7%-d<ږJ38~njӶTru NJMMY^o We-]r[u"[ܯj\keeQd W n zWmŧoEg腵,]O깒"hGEEW SNAovõJ/"I~!x jy~# ծvﶷ <,3"Sd?v:bw@$x3Uֿ?R tEֿH>S VϕG[eĸsW |9d@fwF6,Iy/i?}t]pS&[#a4v$)?"Sdk؝JR~ ԋ/Wkhr]xU=+[xJ֙<1ⲶnNdT18OGx4pҼ5v8}e늭fϋ|M|ńxf[<[H=_-."Sd5zG_^.p̐$5\cVjc{u̎QP2smg\ggwoM5$ .9&K#o9}G9aRX-nGˤ0e,x2^=qpIuVɺa2.c̎oYRhg}<mdo]Z<yŭGRus{׵jUx)-n.XբEt-."Sd#ة'N=.nu f֒"\{Msv5Rgks*׏_M}H[?rƱLfTxc^\?R3~zt&[Sz1"=yŕ ݺiJկ_E)2`pIѴFT"zs}W^+գ%?Y)2υ9ieLsGst<80TD V_<- a{X<'igllq 4yotŅitYC)2` d=\POWzyz.o&"4P 7ɯt?\\ɔIspEkEDB5m^xA~;XEE9 > t -ݩ9WSdpx5DKxsW^ct9W~G3jsmӚrDbآ@Ex瀢{z+{%~LnpKWb[xΣ5jzeWZm\с;gz\C+4(Bv2SQly17) I%?*1˦ H1ϙ8X{˼{\5@1 *s-_ߣ_iJ\]ٸz"نpjyӳ9vU:,ucBm)v5*,42,uIZ49&^ܚ@~Q|'񜧳'.ݺR%tza:`sa23;]A]70vb@}O>>Zjm=j~.bowz|ea_?jr^0*0?zy'S;&%ԡޖ#Wo[e/ZȦvoQuxjp]ٖ FFsL`k ;rMU3@mC<}i1n4<12x9V0t̔veGCO?Li2_QTNsWS[)?DkrK()|#n`:t(v)pMsEk"JmFyB_i2*֥#VVSnWY}KRNZ?~En P;zaxiH аU1Uwz[Bwa&8f.:/C1fԋ[˄soŋtMshՒ;x΋jj+6/^>orJ22K]9fLdNC<ׯÁ6UUwwы7[KTm8daH Fg8])-Ʊ˷m/@|&RugA_GS[)ЅaZtzۦOs 1ϥ;]if'^姏]RstNG<IR*BEkk;?n\>R9f玥w\ǒizV1Vk+ _:kygu,Zwe}{ʞ} sUCDZXSyy4>k7 ߎC\5F]~X۫Q/&:@ij+./+,T's1}Lτsb^ɮl.TPuAU0):в}L 3zN~㹽G͎_-x 4+XTݕ:~>*rRى'B.`xn!uomK4;>YvWn-?i׊Ӯ#1CtAJ ,q-j:$,klu_({_J7%U;ӭe970;>$W+'ӎ]a_͹  ˍأi5ۼz@|B9d􃞿J9vծV`Uwsp+/)Guءiu~@m˶58U9^\t;>=![tDBڱz-s9}7<MYiv}(_7[Ȱ=*ׇCf_Ӿm1ϱzx5rQ}|_S|]e &OW͎9)|tDu)9,+s!l6$'깐@IxnUy2SO?%QrE<71/Q_&g%l`+׷2؊[nrǻv.Qqi ]x#%wk;8~15xJ.op<-bV,Zgv9RڱFvUF4dZ\C7APU7wz;9R[ڵVuUzh"5L=\O&?l`Pep/߄}GSC~vӈ.J;f|rz{iM=\lݾZfу1tilpMn?mU.=l5>Q\=6x.,#OW.iƿ*Pfj'K͎?uY:ލYOTF:ܓUZarI3iUKǟrL fe>qwoFtVj񉪞g~T\Ja ujK48E8]PJpF:\ ^l8~fn `[-Ivk=QrC<ד[h'gGnkvstӖx.*1xMnhq\].=IGuD>z98jM:+hSM3RU-c(<k^_Aj'Ym5S z6>QQq , ۩YUhӘp!_WRV8 %l6쵣W^3[K;Wt]'P?47_+:9kqMޭvqzԣf0>si^ \\}zv1 %½.6GMy< 3>\-?k!&׍#u\IRWzU:7]hЦp.~=IS @<6bQ:?ZGBgiWג#W(-p=ksC-`\ҧ4}nUjW*dmMԶDmMԷ0j࢒L'F%`w+TmLԿR6HGfN_d}|e)#s+]23]ҕr[J5bpQw)SAҜUWCJ 9pE)L'%n0x:EIZQuSY} uum5ʹk%^<*.Ձ-FVn޼2pu/n{"A `P3*ܟb@US!ӡ`v,Osp[mbK G%xj)Uq !xn(6P6Ҏ:?b|5jR͍7f?DadsiHwVEx-{N]~Wo+4w0N7VX*jj][MRN{1..ڊXGx{iu>QK&ݯ4Bt{u=Z[5)Բ֎ gJNwWXޤnW@Q% -t_MR Oo?=x*(tV6R#]]m"p!ԳzVR(7V|M]'_L]P P,sp˨g%asެIiBqˊ9Do)1js J>QazJ=rho‚ԡ6V*1R㎽Pz&(񜷊 Rrx\!jV1.vӛ14Vƒ+I iZ-ߪ+>I5un΍Ժx ͠L<( xoiaIJѶ4оLQrs|e+3_9?>RBPJ!**,_8WxEww ~@[h~~@+-K'2,edP‚~-: ] 10x T,ڇB(P 5 Cqׇ<*82%S!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc|ӧOBH,*6pRn(ͥUN濾׾L3eh1[ jkee;hqZe4-Vm;8U<]6iqx]BE_8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8xp 91sc!C<8ƟJ(r TH5@! fXt,MJNWZ%?KRA sÈMGY^QU+2ńd<%Lv&םZSTr:8W!ZUU#*P?TB sLINRae%);IYM{B m19OP.JγrU۵'TGj\UUըVVXe+>JQԦnh뻒Nt ŕSvUڻU\s*/Eyt%[\];7 *8K۱U-Tl+ŴRTcUUH%|O "/]IkQn2{snum+ǼU}פvyunN ձ"mj8iKOڼ(~k3`iY}DiV-}̤QJMj[kLX^Y?dz]w^*T盵pŴTLKŴRL+\1͵)9J ] `7J>R:^[R 4Я;5u-c.h-n3|}5il@uk>E,مVUSmC=< k.TBMw[ne]u6a.ьJ`ghqz5upRjߞ2Z\|5-kROU쩘ãPwPF3unR{D*O,_ul 5=7S|n%hLnM%T}2+3UZvby gpUCPT#{u5G{otWEVDjͺ PVr\>]S GkdS bu۫tE{eVŵW -+CqP ozN oQSRVS4s~ܤG'kNpx}_/,~49m5 jܯ/+[_B#9U~5yY+Ȇ:oP'“pMS};z.7P_h:Mx kDK%״ uDuCDU-\ET^srfPZ޸z: ֋uY!/kq5sZ <-Rle ZB*LtTIygz;97pQ}}⣼nÃ4j Z!^>B_O5z 9%-"}㩄Kxi5Àu_G?S׷89H?S0oJbO5yI\- ow޿Oun}}5U PWxA{X/(??*ZcQ2-/ʗs!Sa|oiUJ$9nC5=x|}wl5B[f*B{ddR!-us o*tU 񜋪كԴm}QC@W51N$tWUgiS*BFV:@\U 괸 q"C4iA%jJ}nJֵl+KHMk.-!AFb T)jA+jv(STf+9e@DJ` =HuyF^1=4I|((PrpxPEb\ ݚ%[\]͞u{ [B] agh]HE*V]U)cw*}2v+3?MW~|(DD*0Fu^ku6Sd((cim}w%qVC):}h_MWUں)Hz XFS(2J;Pn(רJ{.+E";.J2:Di[S{UW}q"*"(jȇYx8_=}RMA\dP[M'S=GwSV_P]F7wЅFj VZ\5|8pժ饗(P >iŕ*iէY#O?ܱKtx_(-CzHW4$un%w$}퇬y=)zgY덻lfGuz\E룏tT2A% C-sp JcEDG@T{Tkg.uL_nA *i ծ@%,Ҽ!l\o,OUh}I^+Z\͞ڵ{O;R*5Р٪@[罤C(0P< v"o UgJxW{?Q ' 3WkM_T2NEl]<=;S[k#8tIN%C:32Eպ`ZḘK9HuK-&9yjm|Ju/Z,xz>GS U9lߓ 4K+O]-W#Gj`*6 D@HuYxppj4RuoD7Qm+3Qjd: !XL>KP #g讷i~VOOׁdg^Kt^XC-.FSK;0@mPcT5(!s@ƨTU;aZ_Ж1㾖xJh (G% ZYsWnj;EEp5٪QJ 5beέJc r8Y=8*V8͌ʽ,Y.ޞ̗Xw[-I6gSwە$ehT㳰zZlhdQ dsf>l),s9UN 7G7yOLJPz~w=P>D|Sj__qя:bAh4nMeg05kF4+###d*8Oǩ4ߌ)wb{"e^R\ Ӏl:e_^7i4ek+^kv@Jm-.N h{[:rڗh0MD-U/+՛ZBy!N.ym/+™1Z} 9\4cԹR|@o/%ڼE__͎8ZZ;G K'(H'˟(8jM5fQ78n</V9{ZE5R5Yp8{⹒>emt\ "I!׵xpq+lhq7kRUjowr^7X,#ԠZE-:ܬ疪-n8M I"{UY*86@opįNgB$IG<ةbwFy $xM *7*-NyޅfæO,syI&?=ŭ0⮰ O⸲BC5i|h6m@loqӆ铿Z\S#U~6߼ZkSy -tgCcJ=A5-+[KU5C=ʔ@z(7fzY3xDeߖPmmmG+[}TVSco̽ވxQ߉vL_'y|18= 3p[}miqvҩ-s%չxF˖)*Y|M]Nmq^⸸ZeK+ת۵5-B* :"++4f)sEM_'s}M5;)0̷3pV^4?-xD"#{f:9&VL-.7[/iqsV!Nktm1򳵬vyŭ32lAV%p{)R6M_55y\GʧeÞ7L_mU.3t-[Kdx˞`/ 5mkq'.ZuŭV!d04߲.:p-R/#o}I8~\ꆗ7[P-r?..6\n#]-@7ܠ?0ⶨU+-Yr qe=߰z@/ߠZ-J[Y=gCi J3Rhq+9Csl-ն9v\i%ڱJ1sWPm?{VϹ &o-;[\ViijJ۷űzbb;ZլGKOkei[=WC[Й[3ϥ%+/C8d-Vys߼d+[P\Feacx8yfeи)Ws.%bLm.u=e=.nmc֣?ގx2?WoKTaqq+uM >K Zp}U)Z6n}Aqqk+7ްlm|sׯhq4_^uqkx"0\o'֧yŭW9TA…"=2RBb?&b(=2 7EK1GiU-N6{tNpxj}g?g y;@*^]㍌fpmԭť4l X \*W, =iN<o^+rJ0{S '\CF,rKaT- 5:5G($9fԨ XQ)X=zխsp7HرCmhƌ8V*:ڲўzJ롡Te,.B;COъ8VYx(-mm}%o^hdXk9+(4WhU ˈ'?Uj߰79T޼?m.a iqOiSuvP{+9-srݺRF[ >}R՚ٙ[o 5KjR6<親pvpVVnIǯ3q㹬J'@e*")|ΰ'/]ه_2+;_Ǚ*y((ԍhhծp?;WC*\LE^-ЀWoʕ]t-n Q~~)ZΪzueo3/9xrFTӵc5u Jqkh()ucYj$+:f֮=;ehlw\ qy׽b G$l5UnPW b]E9YJ;}m^W)/S(7E˺ eh[٫"*(a.-wb~Xmc IPW:RVWJ^ŹD@ ٴON}y{3ڮykJua#*DPkk6st$U=)=õ[SZJfsnq;??M;Vro(gOi*W\s&0D ;a']M7)%RRl_Is^7ucz[I<ɭ&n<'opu^ܟBRu`7x=?yBMŀ׷8hB[6ZAn]YYEf9/beK]~UNv|qǶf㣟.\Px7pQqɺllUoR8L,O C YWi~H{VFco￧OHߢ99d&~!%j6QG)}K9}b( TeڥC gTpcL) P 8^Jx^PDwtҦ}Z[onRgsպ6+NlhN`$=֎pwb[}Jx0%_MI[5gETokb[VZpF8ܟoC'z XT's{B4Up믫|yF۳GQTVpe8|MuKw" (CNgWz.KKDUrV*p7ϛ==EUjPrs||2%ģ!7k3G|JxnW[9wq IU}?IWNI]^=cf|]fDAF7>to P\{U\/Wk٪ޤCsG%\M|ߪoP(xʕ5aN+$Ϩ_M}ry\p3.z.yv Zy|tlNRauia#}LIRU^`:6ԯ/a<{OQz &iC7AU>)89Jڥ#{Te8B"D($B*_S1]|p'sɿh3J=WI WXEԱ5WE)69uU(OOR{vxd %+7jX0FM.=7*ivu:]v(iRXʨrCUi* UjuF98u|m-cT7j;[/GVPh1WoPtK̡YSc-ԩ;pijejQ7>Z-Nû{EjoL-\tʨUXS\ñ GVeԊ>:egj5j*^cms8vxpW^<}&MRXe:4Zҥ^mNWN'{W^tfwշqx2-𤋮[SUa|H[Zcn x]xɊz^EO2SjNT:TYlx||qkr볹?iU_e7m9ps4kw@(8P&4Hધch[ z4r~f͢P yٚ3Z?NM/ Nݰ#܅O)/y>7|G27H>@<O3WGQJJ԰\`wia-Z~箿&OVpe>~+ızF]߷tqT;P~=e&KxB*~A*s.)JSA`Vm?jQSmum~1@uVVدPr?NQ^H~v}6jܕxp6MJJuu1%\p9HҲF_Pj>Xo, ^ITdnI=Μ>PZ>K+/Ǧοn#ߖT\_ڷQ{tkSĶ)9$~١UukqݳY lGrЦk' J ;X۵4)92s4G].}N7oF\O7SjzHQW̢wu-T܃ xEޮ/M=Oq;C<X`:5KjXnU+=~N`B *3ȉ/H~>@<X#9]7>o˩zSu=hdYLdwu\o޴cȲp/n=Q e8|dl\W^2apFGH]٣%s0zn硫m1\\qSZ} j趋O΍4c%\Ea;x6ʫW7;ʕž,+K͚qL0yuvQ ݆s0ޱMKݤL?0çVV' 5i||,^=O(N VffrL9= fsl VmLŭŭ4t]Ҙb.mHk[)wfvNn] `ڕd|q_baCjgZ3[w9T{ `DAΎ.=bX,iy4.Ҷ=npp=W,s)+]KX!sq+.Msђ[gt `ʾc~,e#4ŎK5CONnp\0gQSX j Te18Wғ͎O<s P'itA<9wjv>Bܴ(gr`TS*"JX)Y=bZ9isx0(,ȎYX@`-9/!b8iF/n%+9(;f cLsmBk `&ss`=\fxnj cjv)3rgwP{.;My Sfط2P28|\{g6+| Ob L)혈xBM.3;~q%̀;1ŶQlTx.;I|P-9+,9/1cnR֚}A{(f)9+1ˮ$* `T)~ td(p[7(GR_ASӋ{{ώL 9X#䚝Dn))s\HP$5){TH7ۄHM{Xve+p];$PGwNԛ{{+ \T-y⒩ >yfced}x|Rl|FOzhMu{5W7ON}3.#piwީѣŷjw18~۶JK+_)$Cu@-y/ioPþV-*{nخI W{Zu+m}]}GutGJoG6荅ҳ]֩EU9I\ZF֯wov1x@]|.U~֪ϵsWz0ޣ)K8_YI 66-MG/D*|p cCeh:^/Vh6?_Q(Kq?G84{J[Q:V}Uk28b=궷oB-Ɓo a (K5? ߲DGKD%jJQqB*ds%D<{r=+kR_Ն=='!$PGE+%Etm˴sv5Jf٦j]ߪ]1;mzumvY( c$ZRZurn~q{ketR 'zoZ;x5F]uyB;\}UW‘U5QjSQmcNVLgWbӳv?L7k7Cy'T*5xF5+KaA cDx$8P-keuOFukwqK+ޓ%|}T=^*nEիԼ\bcG`+\NmT!'+_}zrHD*4R! + TΓk|3Fiط>U}3ƵU\[5}MgkJݨ*<.|ZE/S*{ూN.<%+9]i:v'2诰 +,X VTjSP+nww0 q{o<{(Sgz(I:r r&[s\bRxG)>ʽٙI1!q3&jH5yɱ㫐$JA}%K dHu>e<72HRa=NJxp'=djÔLZs LUʯTw2z~D:2pMyBinMz3&۷(ѱ^]u)cBi!LP~pzfx\G't.9 ,@<SѸںJ^!7Ү)޵ɅZ}A<Ո=sVL Ys0Lg-C<1st*YǴxL-JI{xW[FϭD<B!S{3FsR{ghɕ:oZy̘fdߒ=*dKZR,%EI;_I(J YC5dw~}b>׹ѣes]{u(%Ug%T3,}C Ku=3S.F<D>^C%<@O $)5Nk[:/< CKr]xp/;QZJx35.M%WJ~h#޵TZYi\^#wW|bx-_:VMJ6v~JsIO1Sd;wRgh}N胡9p#fՙ*z 'Dr1",;_JbqMohh]YEީT;SjS/%2íp#Q_{E/WAz9ӽ}j裧܂+:@+fsY~hE6f$h-ڢz=gzދe.;;ӎTZ U -ӴaC۹2"\}TEu/YО1J㪃.k \yգzWB^rj?4:[3՜j_-WD>xL^թ}\X*_G*k>7;T[+qspkj]ڥu][QnS>n'?++1`MPzV5ڪ@)9T>զ&Q,҃ ~tI%s k~IʞUwS _QJ)8Э{}I 7kQ!EڹR;W'UjUͶ*[Wx)ڷAǹt=ekH'rt~|C)5kb![-Y~] uMR~U?F%&8&Ah]Bsy^-~U&*Y]%DUyTii: qZ%pK).MgVJm}\*t3IgV:XWQ{ H'SI5{f@*GT~̯RUJWl =]GNjAmM,*drL Bdwn5!NsN?Տsm*Q-S/.ݩ#;utnS% Y22Y'gUQM¦oR~K<ϟ o`+L ͪ"$cUd%(1Y)JLV֙:g冷$S{Lp\kyQ@9 QPs+0,Wߟ%$)9QWtE)JӺxRO)]:'u.W[sk+)g5WRPNF(0"IiIJMPJR+wXGXG+'([#;psgQS4EQqS_(%'JIKԥ_R*F<ϥxd@_H ?%l!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ҥ~ ȦgrRlCvRlAo<N_k R08.V瓔?r/OMP1K%H qPx$%\``ѣG`LL UϞ=;U/Z(U YETR k}k q,%]k|VWN&(:׍<ͣ@v-s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5s5Y(>(I)Iq+YC! ͡S/ktj~e͚g??usQVLҥKΝ;444,,‚bcccbbc{رt?OB<:K[O:W/*<t S*YC%˫?SPDxϫyU0BY`e $):At9^u9^t>F;jA:Tj ܼJ*~+W\rŊx\x__w޽{n{UJ5jTJ2eʔ-[`h$..n[f͏?Bm78΅ R*)%p)3;]Z_]:ĕ**ĵڻV{{UO ܚ:e*˕mO~* UX[ͫ*[ʢ%U�4Gޥ4 O+RHv 9cw޽{wI{]dɬYuܹ>Zw:tС[Θ1cΜ9 Lq#smfҠd%S wTG)q[1HD:OvV,;?SRm[m9UܔGhz?n:Թ6TJP9H=D'/jzY)UTիd\Ɣ/_|O??;̟??11J]BGyw޹rrիϚ5kĉfz7:ĝxC੒4Hջ7q)4]ERkJU76[On_^T[-}WAAO/\)ڂhz?=҄J\[0=DP\֎`N i!tദ,;+ĚMfaaa=Oz)S-Cܹz}3&,,s#GW_}uϞ=ֳ??{5jT֬YyEؼA(o G)GZC=O꒛j zr')'~:e_6o2x^_&ӝ\+xo>8x#""e6jԨ?cW{lÆ vc 3f̮]>^y7fC5{r9Eӛ[keL+YgMQ֭[nvŋzqTQmkp1ʕ+?N<9<(# N VzP Me/ziP}bsdWjgbZق Md I=5WZIv-bŊSf˖ͻ4$$믿nԨyo~}jra[w)oޭQk 4syi#4BhO%*_^xj-gCҪU۷ObeՄI&֏dر#F{=z5e;TdMܦm7qm:D)n [u ^qemyEn0z7ڳk]]?@6}ƍsKeW_{ysjՊ:Sw3I9q[LcT|FjO{L3ϴw'J\s3/?v5'OX@+V9rwlzf@VzP{畅 ㏋/KyxwUaJLpK)Iҩֱz΄Ax =ϻkz^gڡ%-s϶m4hEȟ?g}h`0o-l\͛ s:PWuj.Cz~~tQ4!Z yC4gvG+Oĵ-LTGSYF/221ҰaѣG;Yʗ/݅]I !s ˴jJ55|PyQ~i=+J ਗ਼ߡ- \G 3a`sŇc^Yf1Fjܸcu>]t3xξrK7q_ly}Q:"O7<ψfrQG%"p@DDҥKJ) tٳO8wj[oڮ#ݴXvQJLpEGj܍=OSXrTzN+:ceOi|77Cmk+L ?*Qƍ5kF)tҏ>=PBSܹs7٧}uTgS 8ĝR^Aq]@ZF n0"cV]E)weF1J3"M/RQ*<^ݯr/?z7l0]L6͙Gh݊3?RY(ҕ>VcGk4U)z:m/FkدSe)_.ThB|QqG6je;T{te?쳾\1c|'IIIf.A<眽Aj/k 7wĽ:A)ncST*qs_WQE*`^'jmuPi{Y||!}9L SRm0.\`~y>^ |))))]tY~}D(W]:cƌ?0::S]}yw>n͙+VDrIkݻww/\дi_~VaZZڌ3RRR~mYv ^W_fRCk~!qs5\6>CaiPGϓeX^Vrl YepjaM êua<\F4]:ѾbƳ?l;#۪k0= #Gtl7hѢB ӦMd6WZuܹf͚jQF7}͛7@6wy穧r<#s4Ј.Xҕ>I̵ U(u!.+T#T ;\oKu0yInXzk짗bd}5e1;Z\~HRW;q=˟`cHzzϞ=7wN:թSgٲe=ݻ;\ 㹮]>ڸVZmٲ%F2}۷ 㥗 .B+zEP ,Ӳ_p|m_BJJk<\ٞ}F9ݗCw<nX+LKGhx{*qmsΨ\hZΥUMv?~<-9s\,--G; yZ\NpppL3ѣ/L"s[Wu$IyVkRd8;ĭ p\v:q*JdJ;S>\;L5tSh_K!,p֭[{yKܹ^z>ŋ;ӧOO6t/9rȗK8d /ct?_I7.P/ sT>gk gQWMg~1r߽)W?5 UH0ʆ?_SrxlY,p̗_~9bĈz˗:f̘ի[2iҤK[d~[@@@-֭[͛fGo0p nsuN皫kzNhHn|ύN q55}*{waPYWBne7wbt8"Ov-{^OuөKu. %v|]0ڂMZl< gM0gNWݵil|TU@Z%6yJh+j|NZC?P /gfMHҧk:Ac;˨|!^pRG}TjU+lŊF=M6}wWNSNye\}݇uN3Wg%.:s4\4 HA懸5w:54?eUcgXD<z׺*N'-IR6o>^Թu٩ed]п?7Ej ᤤN:߿/ߣG޽{GG۟ߧ}sO>\/_6k,Y4h-È2hR/3@Sbnr2'SeUOa~;=SRRSu/(ֱh/95>tF6n}"IYk6λ3ʽy!aϟoӦͥKԭ[O?u#p?l Xfs>6mk-È2h88W͓n+A dpסnWy3q[K =wIJqҕ~xuu{|~FYt |b?|Vw9z: cAzXc_;w|uKof͚;vp#2~,Z6N:ٲe3wxSV`ٲe.ܟx.32h[9&kH<>'u\l gB&k:i-b({otȁSث&9 N>/l^}R=Jw^n\aE8/22wÇoӦŋ&G2'[ͭ:k/_H"2x.n5ہRO=Ҕft߆jXEU3@G85I!`V.ŁSX%S3YJ)0|/GM':JMS7>r5 K¹ 67>Ϸ’>l„ Wy˘m?\ڵ^d{N._hLRJa]e<__x=}~կqu!.|=W 6%Bkxqo+ vίiWss*K:`>Xmq9o4 Z;0z?E6u]C<)4Zj|Ajչ3x.Lw*]{_fϹ:\B = UWhߣ|b\-c\4Q\ztu{\wn[Cm}'cΣ1CP"g 0~tttѩs:wՖ-[5^r@n }BT/eKkv?1{ Mds+8 qa_0euWsƗ~#窨7>{uP㱺2]j<.KS.ƩDź4YEwo'+gErJK}ۿ BLs5f:ۺucu6UT9\*\Ҕ^ԋ 0\72fϹ=ڳ\~ꗝ} am+^Tq>)K{2xR{izRM4>:hCGF5) G<>3\Tz^*?Fʵfm(K3܅ 2Y-֌ktRF+-'%񜻙)iJ3*V:#!C\zߺ&d)lw3f6V_omV;n_p5~AfIPI=Os*S#MnJ< k~?7ϝ?رcy۶mF'ieTf6}yխҩ۩m:@LlQF6h57#Um*n8W:^څ }4S{ZL|VwRuFx칣 6^/>Yfux. B -**R_x̙3گVsϹ&ZmҦ7snef"C5"=!&mU䦇8_=ECzkֺMN5Kg=*Q5;2Mҭ=BozփWn ^58?iРAppٓ[P ݾ}@J*׉PB-m"FjW*B7O}泫Uz\T^KC\B m"FWz.BjxR|l^Fl낹C V wRڿzD_tV/x.>]3x‹M6F_n]mōsaaay喾Us.VI>ԇU \Ӹ[];gr5ϫ:7~nC>Ps$UXDߺuk\\G*ܡC.O<sFZ mіu{gB_AsW`Sgw+UWe^]2:ĥT=+-\]W0-NkzM-z/g_d}=g ЈPgnq$~?/V;q?~2xPY?էeT;LÖjiNp̞s5\ : .sm"Rypk%ʉ 5 Jj蹍3?Hȭ&ƪ|-2[oh|_V/g* x2+-U,9߿wFXlYfs'OtA }ȂW(d漪W21s`V̵/~ B;)DAs4U7_='W{Ǻۡ#wi#z[=(=EZfv)h5r)^'*OT)zfn5fݪ6O@L~b c0xbŊ?sʕ+3ӂxٳ))N=qDzwzs@Ԡ?L+4A!.:UYǺKS{ZYZOr9K4+¼vvS&肖r9\b3K\fe_|hOMFnuVIIIIx.yIhTUU׼=g}c_k{1~^%5R-zJhx.>pes+J%5fVԓ}qCjK nM@VT~5z &nJEڽͶB<_׵kbΜ9e 5SThWҏ0w-j[WsݰUP !Z*Z\\{7 ϷyC}yͿi>g9{.lJvNͶ969rdݺui!gΜFŋVsrs, n/ʝ[$agw9+=lt̝t.M:\>We3xZ:Bnshs% ^pKҋ/>=K瀛QWi*owum*ZVj|=}bz4ꈮ~m{Uwwh)8ٲe[paBLwv{υ l=j:4]7C<ܔcY:*^c_P'}5g]|jqL<'O}\4I϶έ7g̞Ϙ={v͚5Mrʕz(==݅md$&&msxgopR@ QiLp Q(uܯi<R/:|N'.8WZ~MhMᲰ?';pѣGGEA{ӳRSS\*9MTU:IwvMt]˩P/ݛݣVz;WZ?N<"2ϛUѺ1n*gb< 0`ށ6okY⹌!UY(pctnfbRgdQ9m:TYOUQDHihpK;5OK]٭6=q˪51sv;v>}]ro߾&"'1s=wގ:5T:Iuvt7;$k+SL8~}ή>EMIMCguRg.lFJr)_ W\VBnx^^z~#Oqnf:KKKr k7>>3/ԁ:GsO"wAGNvoYK 7+>++Vo͙Ӊ ۿsVmܹsn p]iJ{Mb!5Uv"а+-SRu6ϟŊEq.]ř"9OFM=:Ε+["EZ(s*a=L7VYOG?zԙ( O9Rs25XlY2e+==_~;w4ڋN,czVs5Q[#A\SVz.y*mQ:e|•d\AnrLxХKqt /̝;t/IIIF7tݼpmkf֛kO~C4::]Kߑ|ݢ I_(݄ӗFpp… ֭Lwg7ne npm5h-ղRgQ^7,^I^/MO;bzN= -̙ӤIg|ǜtD#ִˊZ^zes럌s ~~~fСCvԩcܳnއx).LWRjJk&'ͬλ5x vi~?55+ 3i9xӧۙ?ުU˗{혎fje˖h̞Us_ɏ.k0u׏>N3Kh6,%Mݦ*&O!&Ag(-]r46{L_gΜiҤÇG1z=n7.գٔRW2PxwRKbu&n>}#ϏZ(/pw5wcZLL-viFG][gwdf_Es*q=Na=)rtC?~EGO~AhR[հr Jj w<أs~=O3ơw mڴٴi3plŋy9R^7Egu.”Ut^wv/&GOVTRAEW-rgRyfnS5k9=t߫JLs{skC=&MrhHJСÚ5kl獶oV5_5bRgW(8'/|j=soUōRNKOU߲i鏔uOe0^f#oڴi,[ra"""[E<DM4~թUSd+P#~&7W|=zq5Xޚ]x_T%<&ctaBFb׆y{rsTqwc[;GjR :ҵk?߉!11C-~֦91ʕˣ}ߙ:WTE;upH͉V=F4?Se~҄W-XY+`;Xn˭ڥj{ujo:g$<@_ ڵ[t;ls̞s7s$mo.Y h^]=gIsEϩ/T.?CVs)NS|*XxsΟ|3\|||6m;79w1p I5h! yDPgW 4]=jjOC)l^$OfS7u켵cx []wT.OaY]/ stqΜ9Y81 66e˖+WtONNt钹Mdד'O-W"tXj.zg.$}m.r+,R/T)W5щx1LQ* 5{шtϺwzMי}'[%>ŇGh߾ܹsbbbZhfw+¡C5^`A+'UP!s9s&99-!4MӒep zOFϥzpy} R/Rש/[! IzeJ#okFG\k_55{o7I(.;_۶m:˗6mn:75n4&s>|ϭb%,8S3vL* .̵MA5l:*V/5׸2$-颺0oV꽕 ԲZVsM:_(ET/^cz)o hv͵nzAANL?sLͷo0EDDd˖-!!3*\2x]] P એ&cSէJ= *Nck\8GEmZ*=Tޭջܧ*K-j ˡ||93T7| |ԾSJ{d RJ?u^Ȭ-[~dsGiڴiTN)5pB oN"OKTTM5EyoUdpU5q,*2=_K#N벹^j'=cWv9B+KT\R˖kXI ?5o|wf͚=IΞTpa㹢Emt镈h ~ɏRI8+<3sg5пbyZ?I (;_elVՌ4^!VӦM.\5kVںuk-Ξ=51ϕ*U 1ʔ)c}fe[Cw+}&"rVoJ UiK8y:uT]7~Ri; ZUw} I{jܸE֬YӰaCd~.XNQlYe|7fv=eljT}Ϩߧ_6)_Hs}+) 5lpٲes%Kh"::#*w)s훞wsnxk&m? 1$ 2Vj?DTH,<t~W!!N-3gNޫ4mfqg*U\N|2[.!yj6EGu,Uu.h9Z:J?uHLunի_:[oգGd*x\r΅3eʔ1?3e|ztC5:FcS皨JսQ[c{0ܥB\ɋZ+Յ[.]@_/hnNkPQn3.ǝwfϞtG0aFSVcRfM3{.cszhUPjvA& T@1~v"B9Gguh=Y$$U5t/C5RƛT3\9)CS!ʫW) UReŊr2ӧ4haW޴i۴ic)bz+WB9EZOvDM*ӺKf̫p2'gf5Mîʕ+X"wn9r~;vX\+VRڵ5wyi^kC<2QMw9&MPRnn)]2r~`\HL?o_̰RJy5QTTTzu˗m4~n݌Թ ^oeUZQjd(Ic(nfe׼T.^_BaQ "##g~GJnܸ1&Uzʚ;zUZh}iAW8zO~5j[d0OzZW7Ś-˗_reMwaÆ zɫV2~… d &-Njjm|.J_"B}ԇR\ "RT 5í ЛwLJÖeˮ\@;lҤŋs5#rp׭[oܸ˼2x>a Sp=Edj~xjj}ií)տ^W?QlXQt+W,XtG-jݺu\\/TuѢEϕ+׳>6Əo2KG<wB'>FPzRr*daקg#*tOyt *UjժU 6ѧ~ڹsD)l||_~iCvc>}*T`SSS͛.3fhF~hUR&@[nk rp mRڸOp^ɒ%WZUHozgϞ)))>UO>h!!!'OsͲE3f隬\һt\b[{='9}z^1q]-?)ͫ꺍˴zf1Wz3%J\hѢ;0a}.%и&kJոsdJUCNI%4$pZѢEW\YD ܹsڴiaa3^rrrf{7o<̕+W^x or믿f#7uhU=@܌?@c=YZrPgi0z.k;mdP"@=9ߍB.q"EZdɒUr嘘.׻裏f۷o;w6}FXѣwy3fL2e))Sx/&j.h@(5D;Vg^բtnVmx`Q\L U5AmyE;'kX;;㚲+'.\xʕJ0a3uqǎsνW۵k}s:ͭ_~ڵ9xZMیvUY?pT ?h%(9}:W&G'<[Gj337XD^VJ~=ka|X?K.h<$H%bo{AB]I)\y8`+Wt,U[llܸ}=]tYxm߿o߾_x`e˖-SLٲe5jTF 9x-uU׼K7݀>j0Qn5۔!5+cUZV* E#`*Ujχi] JIU +$H!:gJU|-JUnw/GpLV\ &8]߾}'+h"}RVmNߙeRj5xPgFihͫ5UJR*tQSGҁmסdj]ٸao7\Mw'kJ-lٲS+/_yZj:ٜI&q'6T*Bܒ2*PW:|RQ7j+K.PHBs($PrYKKwZ6X[x].]"X4dȐu918tG}=*sBuxs2Ys>Dԥ%vaʭ'd%R _>۷СC\[)2o)j6@4Wզ̽ 'IKCoiQ*Ç_toa9"cO ^>2jzˏ:\k9$=]?R 79s^SNLLM4EUUWRj.{|< <î5\KR ܩSxߩ^C</^{!۩{V.3lb c|Au׾ST8qaÆZvm۶mSRR&?^unU])5ˢz5Ρ47sI'5M#?SɊB1ؑ#G6lx85kִl266+k>B_+j0!PYf;75T*pxQ^^H%ܤC5lرc~"}V@<o0ESҔf  J j˫p>;j^\q|~[wχ)[rzm߾sOaɒ%Zj:xlӽ<+?`ZKUAjʪ*~_s+;[KO{*7DV*rȈCu]|yjj#ڶmut<[z+A {3":M~+wלTN;4*q;:\2%!!o߾OJJc>~xÆ _yt~:9xx ӽWjF8A/}+=*MȕR4TZE=;S^]v.YZj?Wasló:kO~toU,-;rGU }'j*;X]&k~6mTj_x=pݭ[nӦٳg^#KUdM6m>Gg^EC^P/QɏMEШ*:@OgsRRRMVlwy'--}ٳ RҥKLd\ pxsd WqZ>Қ/!FW8*w?5FŔ}rD_l(sC ֭[HHŃ9tл;}h.]s`5tٕ!=D ?5T冪;T 2WRs}Li>?tn;xPWXb I%Jh֬Y֭[`7} 6$''SpĻjDTW*IJUگ:SG+/)+l PhB۔JzC:xFJRP)"T$ R`+[)(U IOTB+:v^9>guHxC͜9s̙˕+W|˗+W.aaaٳg KOOgFEE۷O8AU=)@UR`*.i~m/9]b 7o޼yt JLLLOހx Q%-]iJar0v zV!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rX~  qQk2[uƷk=C\E[tB+xx?((*VWR*vӋYm`VZj "kFʀDw@ [Ze{}X7@~!y8?N N,e*j>^O5RLS=^f|E僮ڂȀuM.U*ԣ+ *(rM€!y8?N ϩ}<;G9MpY,::.[$ g29*uOr%^02p:CjЀVZj "h..) [Ze{}X+$"| D/4q#2B^H ̞s,]%JyҒ`?P@6{0QUAd@ unDԦpP*mjQ{|m`k[(G$Ј%XPD/4q#2L E8Ҟktԇ'\`.h`[驲@VZj ">xc7/V|uM.U*ԣ+ Rk64BA`:q~(k&?ٸҘ+q{ fWs =*^{& sLH:d M~eBo(ϳ6\}>i`#TtUWE@9my$1{bD{MsE~@@L3fOkW< y<ʎ;x.-:C}7ؔ_gn6s"pz:9my$DIq'=&~(JݲbbF妎hWS+Ou؀^y(nڄbP.4_:&0=zR;ꉶךbKG\ޟ 5n=&Pp嵗f>eV*?]*$Sb'l@R~!,QIv;<h7ؔ]h_\vj? y xպ_t9my$jV=+[  AlŀFxaX<j## {]lUu2aXMƈ' k9?}M%!r'JkߙfX T@J)A{Mm|s3تez>p)бOLG8{+' ĠܐQ tTQɮx/-5Ė+nlL[1I yɼ|hT: b3)uUa6 r~PJ7yɼتez9?}M%rQI`O {]lUu2aXM&9my$s'o=*^{&Oj}@fX9?7[]LXy=b' Ġ[^j3y, OkW< ڄbP-5Ė{MWS+Ou؀Bo(ךbK=&Sb0$+t** BШt** BШt** BШt** BШt** BШt** BШt( @P* @P* @P* @P* @P* @P* kB 2+2̳̊",Ȭ2+2̳̊",Ȭ2+2̳̊",Ȭ2+2̳̊",Ȭ2+2̳̊",Ȭ2+2̳̊",Ȭ2*G/" @+ @+ @+ @+ @+ @+ #3+>~t Φ[3{urћ*Ě ?:f{gS-Z:h VebMy|3@罳C\f +E2&>ez΁sfo`֎Z3vBX@^a2@9le7PGW-JLI0^fhu2ٛ(u݀PhV$W~`̯@34{:l:FnRS+h+?0CW|-\Qm/9le7z1|>Gգ` am@Z:hwy__W| VebM='G|nx 0W~`̯@34Y6K UGK~Ʞ{gS-@?p罳G*@-EDit=:Fn춘m]uU.z@V)ZTPhV$vnkb7t_]H#AS`ndz!+>~t x}i@` X! #hh罳vR%* u+ua+Ņ;'Kitw8g#cg֎Z3vhr~qUfk=뭊XYZbf_dxJB +E2&9v?~@yy8IbӀWf+8aS_ޡQMKeր+?0CW|7}|hK|hJ44Z{gS- ]؂shh&v@si+Y{! *ӈurћG6MD&#],X]lUu`UG6Y"lJB +E2& PYi qSyd|sfo`!׊5CeB`֎Z3v$ՀY`R r#}XT)Z)4/k@K#k@ZPTUk@ZP W~`̯@34{:l:FnRS+h+?0CW|=Lf h7`T)Z)4!+>~t Φ[3{urћ*Ě ?:f{gS-Z:h VebMy|3@罳C\f +E2&>ez΁sfo`֎Z3vBX@^a2@9le7PGW-JLI0JQ!!!!!!!!!!!!!!!!!!!!!!!! o$'R lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lc\lb+xfdafFfdafFfdafFfdafFfdafFfdafFc 6Ȁ0tl;1 ݷRMFVULd@S:q6PVYn۩mJt+iͦ2 8(+,F7mԶkinQfTMbf#`4ҷ](ji*|N& 1C u-i[em5YD>qeeوm`4J2c" 8ӉPlvKm6FV[MVm1=7k5"4 8ӉPl=y? @0tl+v@X &^l|.Yf(vb6Doo On=h7zD9sn\m`!zH}F ^ ~ʵb$Q -zhZinQf@c2%Pe)> /_ǛJp n! 8Ӊ\sSb.Yf(vb6;j] .t"^%Qxt^.\̐An۩m~MRF4Rmbθ4nzL`4J2c"ǧbq+5RxZ@m"kVO`@Fj/L}-TX>.`I%\.Yf(vb6,mN v*z8@>m`-}Ϧ<K:GM9$sǡG>/4J2c"14IYj%JE*vFsS ɗ ISS d8( b@ 9: sA @ 1Cw\ On=g0{$A\_8%+bgc AnX _s4R:K>A͘Lk9uSo#M+uҌ6Ȁ2M,RxZ@6\bl5=FѨ>qepUu@Xtc%VY4U{prvӦlAnX _s4R=}(fuyK`jB|inQfxߪ4p^O"4 t'ϑ{tʊ&X 8Ӊej`.z ^(6 _LSg+eوL!yHDoSk㙣 ''lD~_^f\"FV[MVm1O`@Yf(vb6AnX#M+uҌ6Ȁ0tl;1 ݷRMFVULd@S:q6PVYn۩mJt+iͦ2 8(+,F7mԶkinQfTMbf#`4ҷ](ji*|N& 1C u-i[em5YD>qeeوm`4J2[3800Ì3 800Ì3 800Ì3 800Ì3 800Ì3 800Ì3 8C2l0c830c830c830c830c830c83mW"l|l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |l |xX_4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4ѹ4єņVHnv ?Ϟk/o >ݨ@=`<^Y"7H"}Qی#>zx 2Do$DvG|X{|@edH= Gn2s z@ڎd c#y '۵=3Nj+$FAOj;qMћcG| i X?5x6Dg"K+$FA>Ƹ5auw]0-jMjMjMjMjMPn*8Oj;q=G<Ͷ =9ɣ"A/P9x@{gX$5(4Ӓ[\~?`Sc1G&x 3EüaMpL N'8[CD>@~?ba>ҥVHL~gx<@ߗeKRt]/9Qڥ>ݨ@7=+P:mHX<=.uym:8E(0Ӣ=)u4mظoH?Hw&/8.×X{|@l)i9gGcTV~L󇦊 T1ԸҒƃŮӘ`  Hnc^Xo0rOj;qT[h_>~Nx2Q<ԛmR@VD/4jY x6S{5 9X#>z/Ŧy0 ]AZڥ|i*\PHn~WU5R7zY9Em6Pw#\`3VH:Q+l@tR@7y:]HC[^Gn2S#2U܀P:mH'Ŝsiy=`\+ĝ5_ ?zOMH8tS`Nj]Kp\ujæ@U;YHn^NutT4+$FA98Z4Ƒ+ڎd_kR6ڤ58G.e G|W߀ ]AX;v6qq#v퇟Ts#Nj&ͳebJ s]s/=.Y"7HDx Z* RQGn2/VԛmR@h:]>Lh2q77aӕ=3ҿR ~h0c8N&yjؾTu\?X5 S0'ϕ?Qۂt |iIptWR^m@edH= :C;7yiJ9ڎd_kR6ڤ-uQ.C(8̎rt=3ҿR ~h0~ODgpOiro79yNjM)yWvGg@I:s:NHY"7HDx՚KP5'+nv Zm@(I$[#rϩDo6j{`8_~)u4q &|9L4 9oyx@[O^);9zCh=ٹ]%y*LzI`a揄+$FA98a.R>ݨ@*ڀP:mH59Kғq/0`=3ҿR ~h0S9gk7Od`x <~&bc@y1rd ٖy:dhP§NfWGn2-+BWpO-Յ^ڿ GH z{gX ;nP:@ukGq8 :+Y1x {~ru G_~ru< vGhﶋ1:- >ݨ@=`<^Y"7H"}Qی#>zx 2Do$DvG|X{|@edH= Gn2s z@ڎd c#y '۵=3Nj+$FAOj;q{gX5W%DFFFFFFFFFFFFFFFFFFFFFFFFFG'g`}g`}g`}g`}g`}g`}}=bUV(eXbUV(eXbUV(eXbUV(eXbUV(eXbUV(eXb 4456P0@ 3%1#$2!"&ppU㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;f:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:-6j+{㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;㣾:;#fp{:60$A" `HD 0$A" `HD 0$A" `HD 0$A" `HD 0$A" `HD 0$A" `HD 0$@; %*{GE(F04Q `hE(F04Q `hE(F04Q `hE(F04Q `hE(F04Q `hE(F04Q `hE(uKS= `F*0Q 0Ta `F*0Q 0Ta `F*0Q 0Ta `F*0Q 0Ta `F*0Q 0Ta `F*0Q 0Ta ^,%f@kH2@ 0d$  `H2@ 0d$  `H2@ 0d$  `H2@ 0d$  `H2@ 0d$  `H2@ 0d$  `H2@RJ-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B9';wKgWkW-xnټtv%y6%{=B=YP X?<7]lTj\ײ)ldQ_Q*$/b$ą~tv%@x 4j eO/.e`&.$,^fͯ+D'1?f4ƐCs$8[E0BaQGKޞuJ8omXF 77"|ZwbLr'5'v*]{jϔ%Fڽ%DA`y6mYckOԽ\Ρhro{>w{xnپ֖swxЎzVuk$ԏN7mb]_Խ\Ρhޒ(v+:|nzz w7ҼdԓHB+M:3vѮ67n`Ia(jI5.Uv)uټeX3tB3yfk۩GNQ7z-|^Q& 'UMzz w72Xv|l]m,bzgJ&[;l tvy fVM#wKg$M};gXmQICcf""@!^fͯ^{=1ȭ*T2r]n{^u Deu<7]la}xq5}tO4mJ%;wKg$ؕueI"tV7mMI:iLg4i"4^=Rup{:zoE yԣ혶O]UMO䖲9zԣ/3yfΔZK5ʭosEs/wWZ'x+OYfjd<]Xsɔ^W,κ;R2[QXj[b۹a]{jN7mJ_]-ɮEi2e4^=Rup{:zoI uw =6D%d FO2ĕX#d>o;v&ɑΙѺ:'qt~]C-ղ<CVW+.w{xnپ4o7aެlRݻPF6s{Ҽu_ѽ]廝^gPO^vW[ޞu z=:u@C ;wKgO%ܫd7+wY[>u Deu<7]lHCnng#~PC;wKgKWHgI1/lRJT1)23yf]\Ӈzp=8~hZ=86bץ{=B={]nzz w7ҼgJב'n`I%%^S| Wư ޳QWTVVzwk7z-׼]w}}'^06w,?w>8Dd~o;hn{^u Deu<7]lI׺< ;wKgO[bpG./r m]Aq M0y6{/[ש{=B=uZX~kko! w7PvMi?M64`~lMi?M6HK.;wKggRjȶܟE<@u#Iۉ9'&gI.ARO$L97?mrOw%x=Hy'6eIɸk}y+ԁF9/lrNM\t]^>gR4I͸{crn~{J {:Nmp3$Wԍ'sn&^䜛'}HΤiE<@u#Iۉ9'&gI.ARO$L97?mrOw%x=Hy'6eIɸk}y+ԁF9/lrNM\t]^>gR4I͸{crn~{J {:Nmp3$Wԍ'8>m *Ы[Bm *Ы[Bm ʖzmDs$EyGb}G&gF8D*$Q TH"AED*$Q TH %zOwm}_?o  Y2$ϐbZ {:w3m wj¦-m!k~p3עnnOwOE nu[~%#1"I$̯R {:o .Wsn&^*Q< [m/w{w}}7ԩqEqxIȆ` zwԍ']~m鲋uO|$Ȟb)-gE:?GJ,97?mz*_FiFgT㓔 Jm+Y ۟0 C1AVF=;ԁF阙:5S*8("h(!) )Q͸{cӼ*K.2K-_}W&gFd'Kk!(k!(WlSzXX,}}'d:Q`YS`I]nm,wԍ'93Juy_ۉ=#fe*vrC I{NM^szOnC}}'sv(aEw~K@u#I?J=6eJ{D|br' 5(C&Jjҥ-E>u2TUfK*ROzA[976eH?O!|b?ozNM^_Zw=OOx'umg Q0<@+H-Y Q')zwԍ'ڼ!l]~q2Ǥ//6>m,>p3׬WF*\eϽw7ܸ:AS#HMd'Ks#ઝ,-J7ߦWԍ'ڽe`! jL^A.Պ {;aT' ^ |=wpE.BqY՝m+ԁF,^ '"[ٸem&WZm=76eJn7M"$䔄$JJvYY97?mzp#̙4ф2zwlIs#1!NB^ZVܛKzWԍ'~Am]01q.O" 9 Bh٣Ӻ0u->RRLO(̕ԙQ\1J[:Fѭgrn~o!_uG}}+OQ g'$mazMs&ƬeCgx=H}' QDgrG6eMمBl&MO ], (H٩Mta#{w%a<#)Ƽ0q3ۘ9_N {:W)JDTZaBsn&^,Ҏ T'ZʋЈKW`I^o^SD朖yV{qYR {:QC p[* ^"m˾wZ%]`+t۶nDzmOIR4ٮ0P.nZ`K\E[~i)W}}H8TYHg1`Zrl W@ܩF0Q"D[ԁF9/lrNM\t]^>gR4I͸{crn~{J {:Nmp3$Wԍ'sn&^䜛'}HΤiE<@u#Iۉ9'&gI.ARO$L97?mrOw%x=Hy'6eIɸk}y+ԁF9/lrNM\t]^>gR4I͸{crn~{J {:Nmp3$Wԍ'sn&^䜛'}HΤiE<@u#Iۉ9'&gI.ARO$L97?mrOw%x7mL3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3T!S8L3M2| %TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8H#TR8ٳ'LZUB*P xT+¡^ WB*P xT+¡^ WB*P xT+¡^ WB*P xT+¡^ WB*P xT+¡^ WB*P xT+¡^ WB*`ɃsK }pc\>1 }pc\>1 }pc\>1 }pc\>1 }pc\>1 }pc\>1 }p:l@te a*YR@,)dK YR@,)dK YR@,)dK YR@,)dK YR@,)dK YR@,)dK YR^T ())!L eS(BBP2)!L eS(BBP2)!L eS(BBP2)!L eS(BBP2)!L eS(BBP2)!L eS(BBP2)!LYR)"%JQE:)QNuSE(QE:)QNuSE(QE:)QNuSE(QE:)QNuSE(QE:)QNuSE(QE:)QNuSE(QE:%Vn%O0q#`G80q#`G80q#`G80q#`G80q#`G80q#`G8䊒4gSIwZl\֮y'Vҹ'pΧiй%]NqrO=N%irKZwEZOJ9{:KgB䖵v:ƞмE WN0?+m^I')Z(Zۺ/Պh` QĆՆW:ƞ 4"!!O*LNd (N +:d̑xvQC06DFdgBBҼ_GqDjgmֻZۺ/Lfe>2fOEoJZOJH8/AiM:$HVWY$cgHm2K=gVҼM*&X/i8Dujي*Z&ӳz̗ f%Z^fuСh*ZQ2_=nLu΅s;3LM[Dua~Lm eX imK7بyvm7lΖd6]I[ۥlr%:gVҼmv܃C 0Cl _e4eWLa4ͧu^Ysu;O\1}YҬ+gVKzkgB19"&'7K[/VG(}Yek/ڬF%xֵvBX$ԹN'ϒZRjdC0åHZ^0gVҼh Sʛ.|<Ēgܿ&x9{:.H$.ouN'5iy#!YQ*@~溰?V >iVlCj](KiZhdf>Qw ERe)Snlծ4#MLSU&!apu~M/:~֮}?x9.lծ4A~H(SL/$:W9WpΧiI]B2g䄋=h RV MwZl^?Շ?aՉoXVjc_GZOJ_W_ˆadBȗrwlsئd͓s&ĒR;򉅖'J2?{]֛:a~?Ճ?ʟV,WkWn较'%:ƞ0ܿ$K'mCciEZюr?6t/Awh[Ed63_#Zۺ/>'%:ƞ0ܿK'pKFEmYc.TQ*5oQwZl^?ՇN[l6*@ޭa"["֮}?x9.lծ4A~(V Y4IeȖrLUxv\(h&> VUK2t4(н#|.-l'v~L9?7yv1u{g|έqz //IKq=K:>S[L$鼒}+Ou|$ҙNIOQGy% V,(NIo2J?YQgJe9%=EM3Z$9%ΔrJz>(gҴIgQGrKx=)}7Pϥi΢{:S))(o$J%E)-tSSQIC>K:>S[L$鼒}+Ou|$ҙNIOQGy% V,(NIo2J?YQgJe9%=EM3Z$9%ΔrJz>(gҴIgQGrKx=){s0;s(bߜ0VL#gJz*z>A/n`vl`E"tyT3Z Y_vGldvGldvGldvGldvGld*΢a/>;;SC4#6_pZu&\JG[LAyƧ7Z2S~mSW="Iy-H,1'J%*?*9^>fc^{kʡJ) KQ ՟YQR0 PtL#j.toeCg5"gJe&[ 'y*}+O"\2 #y_U<:>SʈiOoHަSmLq,ZA9 m"TL@0A, oȷҙO#ul 0YT ERc2l@Y6$ zY1ȧF2r"IY?+|,&s^U Vm4 AKNx R^U VeK*K`QC)nk+o;+8?^3pzk:>SgUˇQC).knݚ?xV/Mo26k#誰Iᵳ ;?NmˑsSQ=jA-D'9ٗkg=oQ30=jM=綼?qM@=&tEHt[n:cYQ6kt#!.oS)ga5kQG5Δy,FKU( k?u{k2皚ozN(8z>c "%Y`ɑvx͎]W6iޯ=PϥiF;A vVy_괆 &Ҭ2D(:>Su᳖SJ\l#2–Q,NHd]Yl ]r6l-tS*t"(:c"`]&҄ KJs"VʧK-gϜfoK[~Hs) QmCcvյ ?ί=PϥiSoe~7m&BI>O#(O)FM2~ GsaEYmf3ȜZwo2'o{k6΃U{&֔U)(owo[~6Ym,E! {myT3Zv9 ~TkR ",(OB]oS)RR,Do2'o{k6΃&B}vŦ=U=EM.Mxň[Vds^^U V]ge~,ZIt-+ %eM3ER<:>Sк[|.?T J(oI+Ht-JF [L^%M=; % /d P"zζdV;v&L)(owo[~i L,ؽj҇F綼?л[\(v OCPZ^M&X%*xu|uy]O1$CH#\lKoLgJe=NpGfb&(e\WX"Ÿ=QzPϥizvWXҏB/ru|uy]\_:rezrҮ^tSdm*drfIY)SQB4޷J<}+O.3VVxAYQަSv3w˷3ύo2'o{kH lr]^6./q}GVx3Zv9DM?ܾ5E)]^ke> :%JZeg~>5Δz UN@hdՇU|jz>]ƛ& blV-XblV-]҂jwSg /X`(gҴBs=o;+L+ kW"&ʛ&?M=pݖYe"!T9(u|uyCPD WH8]Ą޷v{:S)2vWbqN΃y`WDR'1ҊE 0W"I^E=EM.Mxuy*}+O.3 &zW|0'ݏb5A*ju"\rY5ȳ= uL? N(]J뢶8.zؐn1"oY -yN%gJe=N ]:t򜋑)(owo[|m{myT3Zv97uT|:>Sк[|dOZs]!ŸG<2y{:S)2vWbLj7Ia=&Z~U=EM.Mxuy*}+O.3e[geƖ-}y?ʳ= uL1LA۽9Jd~EΔz jrJ_a~F%9 &G*"O5v"/D BŴkDKȰe,|+dٓ)(otB)~DQtIdTbب* p=R<?g87~B tpI+͎ rpnM8PaM ʱIxGs",(OA"ܝA~@֞a"𖓡%y(,mͲ@p~ش[Z̷ҙNIOQGy% V,(NIo2J?YQgJe9%=EM3Z$9%ΔrJz>(gҴIgQGrKx=)}7Pϥi΢{:S))(o$J%E)-tSSQIC>K:>S[L$鼒}+Ou|$ҙNIOQGy% V,(NIo2J?YQgJe9%=EM3Z$9%ΔrJz>(gҴIgQGrKx=)}7Pϥi΢{:S))(o$J%E)-tSSQIC>K:>S[Ȭܷ9R«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<*«<'Έ˦ȩNNNNNNNNNNNNNNNNNNNNNNNNN6K-&6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*b6*`ɈN,8ľľľľľľľľľľľľľľľľľľľľľľľľl̃F7;e.aL# a0&0FaL# a0&0FaL# a0&0FaL# a0&0FaL# a0&0FaL# a0&0FaL"l2Q+&K|#a>0F|#a>0F|#a>0F|#a>0F|#a>0F|#a>0F|"8-dpvX;Ki`,vX;Ki`,vX;Ki`,vX;Ki`,vX;Ki`,vX;Ki`,v2>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\%?rF>TvOSW$cOgd\\\bÎ` 6RB#8hXq&!Im>@SFu^Xe%e2iJ[ 0FyKS3?WbF0t$^%(v0!! `CB0!! "H\λEك#^R>Rd15M5KlΑT-X\Z|W̻ko!# ^D)7nD)M t: "uܝ1J2v{~h rɇu fI&M+Yu;j 0H+n᪹cVZ쟫̜uTQI7W[{9\c'GuorySV{d&df<W#.졒,,|/re 6Β(YƜ۝1LglI[j%!n._ dsE<糲~+q0NoFy/^|fsrT4'E5#{!&lXɹ^ ?#%X8amA\Ж+4VA¿mFLRe|WׅyUspRKx .|==yL#+@B #u|$r~ۈ~ۈ~ۈ~ۈ~ۈ~ۈ~ۈY{Qix/te-YUlYI$J|wVCeDDIt>Qi.FSI␞l'>#a2m6%BLebLr%tAzqHa5k֛AA/ B|X:.[z= ̽y F:eM,("t,NMw:dz~F0bAI n"o#uy.]yk=7`_ʻB rɗ(AW | d&zْٓ:-Ed(ItȻ+ *[a%G'[|.zi(}H2m%}#P4scYm[v=oH%Jj un/-Qz[m__膮e T'tP%%H wvz(I*xrM[^F". 䳍y wr&4h)Gsuo!-&l&z$%YR/"YROj'>p1C"8-9eC{5* QLp.qF+e6Hp}Ys&JtE /βk3b S_ P7~S?W)М.QpggyEzpd)\87;I<]:fdregkzT<W잟ST"M<\z.KsqYuhm b)䷌ ZJ\8]y#?\7|~"zf>cY5Fݺ.q)\'+(,tV{ĉ)rnbM( r$|%$Kb?y,mV^V]3:˭&G CX[CR5u~b_\=oo+=zozF7R"\X%}VT#3g0W/]uobsWk98-m}^g:.Ku7_U&hȲmvʕ.Dox}ayҨM 7e:\}ߔ_|.J/oS?WvWn"zޚEu[ig7h>1C pȉ8g?z5|/S3FSds`jψ *ee>3oQj5:޳’zvor{S?WvWn Z|Ud+$Jg0W/]uo)5lB Uwg4X잮Fs1$G\s7t1C?'KowJJ<}"OxoM&L3GK[rP} ڽo#uxnoEgOEu[Bz&L&[LmW |Q䇫ճ&-G\sM :݁ʊ+KKv^R2:ѯs}tlM=od6$1<NoW_ɮ7?)쟫л}7Wy $JHMmCc^ſ9\tZG[վL ~eM"cR'u4R9tй[|-&t yAdxϰꢒBRWIM1SNe24H ǒ߆tg|nl{忽"7[3Ogd^^^(u%)3+.H{\0]ݽoWg?z5|/!bl"@EU[Co98K$D[üRq2/!1flΎU_ M1X}=zozF QG ,\tZG[վG6Qz%V0[ߝ}^g:.K SL+,{k91*c IuKUZju&MFzkv\J)LlϔvO]ywWRňhvmsriowV]*2z[$\ĖX$x("*l1 HU9tй[|PQLݛ!gcd&\bCket8K6Lpǐ Dڙ3HUDH~jQY?K5Gf,u t2ᰪWq5ΜsbnkU# =zozFpD)z&sriowV'0yXw9R`}3?z5|/$bNAJ}MO$e*GVAJr8U<'ygd^%Hoh-dLEWZOW%rBBNY+4^2RșioeBH'x3bB9`*`y@Ӊ*+ 䯪Wvv,%?d7zpTTȡ[),6jFQ$XyUmm|l5B(ο,AE?h X~b,AE?h v^=IKWRD4}2b٦ 'YRce>ūD+cڸ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}쟫3+>Hʞ#9~J#}*a1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1i1id˃1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 881q1;wcwq1;wcwq1;wcwq1;wcwq1;wcwq1;wcwq1\n,?V?VU  14Pqrs!0235@ABQa"#Rtb$CSc%TdDp?sU*i)hxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxYYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYwYw土ŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxŐxċyjCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCH"rEg \ Rhͤ8$0|&_DËHq|>I/"a$L8$0|&_DËHq|>I/"a$L8$0|&_DËHq|>I/"a$L8$0|&_DËHq|>I/"a$L8$0|&_DËHq|>I/"a$L8$0|&_DËHq|>I/"a$L8$04BSˋRU)b&a`C0!IX$,|f>I3 $L&a`C0!IX$,|f>I3 $L&a`C0!IX$,|f>I3 $L&a`C0!IX$,|f>I3 $L&a`C0!IX$,|f>I3 $L&a`C0!IX$,|f>I3 $L&a`C0BSνˋRU)bc$I3 f$,2IX d0&a`1Lc$I3 f$,2IX d0&a`1Lc$I3 f$,2IX d0&a`1Lc$I3 f$,2IX d0&a`1Lc$I3 f$,2IX d0&a`1Lc$I3 f$,2IX d0&a`1Lc$I3aKH"jD. #D6Ԃ3 4,2iX,d0Xɦa`Lc&M3 f 4,2iX,d0Xɦa`Lc&M3 f 4,2iX,d0Xɦa`Lc&M3 f 4,2iX,d0Xɦa`Lc&M3 f 4,2iX,d0Xɦa`Lc&M3 f 4,2iX,d0Xɦa`Lc&M3 f 4,2iA2F!$lDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvK|_N(Is$dPf>Ȓ6\{[f(^ yZ#2H4̿I BME֧$([eu=CВ2IX^풝?N߀*-?8r_ڞ1C/H) Ms=%u3؈+8։re']f,- zN_SB|{[f(^ 􏑜3RD\\£%E[hMs9 _,>>KE32􏑳vZY{˹3\+O7]eAuSIIQsHm#W)a_%L-5f#X"0(\*l~~&.F ~ڪ=c1Bg|=+qJsmj>lU2' 51M!c܇_M'RD*" ̋zx%P>F )[x#2#~e1ݚZE B_RqS9''NB|[R tT/y$uƿ׫;D_2m>αcNʦQoX,{Eg?.HC)bc)ݮUЬ!'=#nBE eҥRN*_ei4#~J}{wY qֿ_x/r+IHE:$_i\Ҩ2N{Tw$xzG?ܠ,lK]m\MRCww_%ȴDz=ȭPHl)*UU ^euҢ&SMI]>y+#5\ֳ)30~Dc-_Z,="h#EQ,'BY em쥦kZB"33RQۮLY(VOяk{L GheE3NI(H8zz6WQv R%));6w%_ڞ1C/H)%JEUPϞ"Z#&B{9$uƿ׫WJW̹.х5 HdQoX,{Eg?.FI- ) B ?F~a5}+$QFD88XʢaD=P+f_9v$UD\W30>IE32rߩf %JX:ż(WgG^Lss洏Yg9w]QF|{ C&הIIu[[gQNYg)QoX,{Eg?.H e˨˴ (3w/j\W96((VOяk{L Vi-~TsWSf(e)5(" nҎ*lLUhrx\]m5<]>`M*"JH$uƿ׫UJgXA Ϛ{=k#SSGνD/Z% #X"0(\H(VOяk{L [FG*XOo:$)J9LιиB \-)A!7 Qj{L =#,D D^Mw&*W'0-،"Y ħ|,PT&G^KW.dk=3^{WL%HB$UB'-TQoX,{Eg?.QEpeU+z'ǵbHKJ=^jv̒Q8󗴔!<*IFGjuf_ڞ1C/H4^*9Ŵ:A,DhpIxRc rI[gXr&>zrECk)Tn8f(뙞!I *f[oy]k :->Kb#;Z%( aD=P(rQ<-3.2Bg>sMQ}[Qj{L =#xg4C"V»hc Ϟ]-w?Kq|k}D#Ru./lYORg>}IÑQlGu[} FYvKQ\iE z1oix3>NL[gGs5]gۡ1eOgY0 *T5P>L'Qsߗ~%~%JI8ܾ$d ԲQI8O=DUL u >9$uƿ׫'n ˯eeߞte$"JH}QEG`qDaPgkDETP!'=#Q 4E)R&~j"F A7L mʕ)N'xzGA6<9$3]*Z$p%[\^V#>zr'cM3mwuTYfueP0*TZT|ĆĿ,HlKBĆĿeK,sD~ M,R^F]bĆĿ!TL;(myM|ϳ`>؈+8։r+-"XC>OF=3/zG]L4Rm&5+fE)4PB+)$!"R[DD\Sf(e+e{հ'SC.Gq|IfVGb#;Z%( aD=P$v>=iJU(;P,kWnjnH]L;UsܮIIHEh=b^#Ѷۭ 迵=b^:'-ا.C f!%vzXXe\%< &MkKjRE9eZR\.j?1(pc2럸Hm#W*(,="h(2*=c1Bg|[gм|Sf(e#xB-Αpw A4y6YM*KG\ki=zT}QEG`qDaPgkDETP!'=#t_=օt_ڞ1C/He8wL^KQms48Fr:C4UdWY*2sA@4Ld\ki=zT}QEG`qDaPgkDDE RAHDJF,*3bʌБKvI-H4֓nD'=#qAr%8J$9NO0Y1Lg}œo1dwY1Lg}œo1dwY1Lg}œo1dw1BMJjRk{䓑j{L =#QI)CZ/K E Ծ$C0wiPډ/I .{ֳP%DX됱&At3p"'>zrcə$bȊ "+,?@oq?KMLy,HE`qDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V FYvJяk{L :/Oiv:_HlqDaPgkDPxzGl5V 2U8KMQh!<8/,E8㈼q\"˜q^Ys8.qye8/,E8㈼q\"˜q^Ys8.qye8/,E8㈼q\"˜q^Ys8.qye8/,E8㈼q\"˜q^Ys8.qye8/,E8㈼q\"˜q^Ys8.qye8/,E8㈼q\"˜q^Ys8.qye8/,E8\DB\3RϜa(C-#z:I{o\˜qVYs7.qYe8+,e8xo\˜qVYs7.qYe8+,e8xo\˜qVYs7.qYe8+,e8xo\˜qVYs7.qYe8+,e8xo\˜qVYs7.qYe8+,e8xo\˜qVYs7.qYe8+,e8xo\˜-n8ᚔf| DbiԥQYe8+,Ee8hm\㍢˜qVYs6.qYe8+,Ee8hm\㍢˜qVYs6.qYe8+,Ee8hm\㍢˜qVYs6.qYe8+,Ee8hm\㍢˜qVYs6.qYe8+,Ee8hm\㍢˜qVYs6.qYe8+,Ee8hm\㍢˜qVYs6.qYe8+,¢c]St9;LyסۖZT,RDU8HiT"rqNUS4ʪqƑ9UN8'*DU8HiT"rqNUS4ʪqƑ9UN8'*DU8HiT"rqNUS4ʪqƑ9UN8'*DU8HiT"rqNUS4ʪqƑ9UN8'*DU8HiT"rqNUS4ʪqƑ9UN8'*DU8HiT"rqNUS4ʪqƑ9UN8'*DU8Hr%I)QBDaB3U̮/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88cTэS/F5N88M#m>R]DJqQPiqtʔϴXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjXƩŀjGC0FyĤ!"'lϴX(sq`,c9łg8Q 1F3X(sq`,c9łg8Q 1F3X(sq`,c9łg8Q 1F3X(sq`,c9łg8Q 1F3X(sq`,c9łg8Q 1F3X(sq`,c9łg8Q 1F3X(sq ߓi$RF? NRg8qN3XIs 8qa',$9ńg8qN3XIs 8qa',$9ńg8qN3XIs 8qa',$9ńg8qN3XIs 8qa',$9ńg8qN3XIs 8qa',$9ńg8qN3XIs 8qa',$9ńg8@4LMd]rDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFYtO]1xzGl藴;b󝳋ށVlDaA`[+gD#vΉ{CF o98lp_vFY .EJ1dxqLw1dxqLw1 UDA#}Hr/%~ >SlSl(ğP C긂C-Jj&G2JR(3Ih;b"7tIJf|8ŌGH2bQ#X$qD1c(,e8ŌGH2bQ#X$yhGR~Rqw!WbcJK)-"M/Q<͇|Cm)Cj(>ư%:NR/b# މrH-ʈ߷-t@^iOh)Ƽ\r6^p2r(l y>3M/hwH >EsDo\.z>jrScy<<}WyL򜀡J_Ii/q푕c䰸/b# މrJ$wv*#~cO]1xzGW&u KUU}6C"K1xyϑF`\=W#ށ\*?Q3ZUٙ$ۦjp~b qJR>䐸/b# މrJ GQ%~ >HQ!U" tih>:'ڜWRJS=&8 ƙĪ{MPĴ oe.KD#7fݘKvNUoGq5z.Iv6 [)Sµ#__|[d}f I)/PF *Ur:r[B툌", z%wQ=8Ӵ⎘JDF|Xs ~`Q,9G?Pq- Njd3O]1xzG@!Ίu EY%7L%^H<3iiI) £o/hwH >D)P˰Ņ _ֿ,/X_ZPa}kBA"I/(s)=^&B"qw!WR]*q)_a_oQB )"-Qf#o#T:3$}EgXK洞"eCd(b􏑻lw?ov YS]kR\PHmϴy]t@slfiHޖ*(ĝ*/9w!Wh?(:GTGy4jQ$}EgXK=XwtN%R(bF,lT&-e}!tK_Q/hwH >Tc#l~kj=`Y߼O BR6I%p$]|q0\ȮJQ ^cN`Q- )H˜a+HnMy=TEe6$}EgXK*NQEFlT:2$Ec̀t"ܥ=d$8Q:_ZԼdO]1xzG᠊;Rsl -(/e $'9N8uE8ZO¯=,3 J-f 4FlZ/CK+\5t@sMPf{rT=F]-wO|x,]|g9n/)顎giJU%å2 A +)JVٙ=ࡊUxP0ƊKg䐸/b# މr8Ͳq:!L/;X`h+]-*Qrj'.=#qJ"ـA.FAT*9>قuFlJ"2k)'!$do1'?g%^|O:tAyԒXReL]!֣b7CW$r-4͹!*fsE>PMӨi>!툌", z%?}gsG~gzrZ'.=#qx{?a2-)5gLmZ\lT8Kk̯$^|{Gc+|u?z("{?&ށ\Pm$=xVa*hkɜm׽ɗ0alI=I8RNR>7R^~ID#|uI&?9Gsǧg[X9+WS)sM< iG=J%<^I|S=z[YHޑwU.Mq5z"yD 3: AiIW:RS: {ޞ'K "0 -$6I- 2=0nCRۖ\RlO W%BK\,R Z9:y:*(b􏑝GM4:Fue}$-8DNKU14R!ilْ[޺Y\QK藴;b([mE4*YYJ^ˉ'ށ\ԣ,){_UGZ7WLS~)?d.K6X=A? rQF*T/QH\ݱVqoD\5i2:PI#+,ǫQ?iwH#y^5Me N*ĦNwSB I藴;b(Z[9YioAǸ^0 .z>jr42r9)WQ' E  m{ :?+Ї΋ ,n/rH\ݱVqoDY$K(bP'J/}Ks6?藴;b'z%'#T!z?zO9 eBEE7CW#yʖ -s=J95@W9)SLGApWzsl[FB3gw툌", z%(aAI¡胬FE?$~ >G-үyyO!} LtBTҕy =C vo/hwH >NP ξ*їK}۹>Qq5zy=e`)yv􊪇1yR+L. ؈+8\.b!4'$uy8e=1)V8)}Tt}DA#kJyUMuJrJ'.=#iAyJVPyD,i•*.rSm/F OH\{CF o9g]֣L}3%+0;RI~Qq5zrW{o^]lRRA:Er2`陆*D19@{o툌", z%h'bH.Wn&hҏKڮ(qP CJLRuO8}%P)Jʥ)1a$gO]1xzGip*.0v?YX.5Wm{h?tU֗$A~PՋ*&-uRSv1F?qgK1xyϓ5A?5=㭈9E/2M.Sq5z4I%>E_'fKVUE/KuORtP+ =TP +,IWEp_vFYtB4RR!D ד%/|z-t@^Jf1ϯ&48(*jW2SaDҶHS%t@sG?e&|q߳!! rJw/_nSq5z/mSoOQV088HAJgX~*(k|"}Y$. ؈+8\.8ŠE+yW|aNE7NLdiLo1Q{?&~ >KOFm/]~2m+=Y~Mޕγ ߬>KD#7+4zG.tK]CkYJ/Uޖ>Uq5z%+c8Urgy>b`Q{?%}EgXKT:`o,L/KD=#Y)n, 2U8dWA~69kJ qŗRxbk%%!'~ >Lp%QJ t9+ei?6 WDΆJ.F?lir {-rmRU5t@sK!sGqquRt IOEo@^JiYJG`Ԗ X~v-4%(Kkʼn/DmP%ʳ)Qjjqm- R&}EgXJ?iwH^v.z>j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݱVqoDt@^:%j[8\ݰ򌤕j BRVcgTrqNUS3ʪqq9UN8'*U88gTrqNUS3ʪqq9UN8'*U88gTrqNUS3ʪqq9UN8'*U88gTrqNUS3ʪqq9UN8'*U88gTrqNUS3ʪqq9UN8'*U88gTrqNUS3ʪqq9UN8'*U88gTr)kqg*{ffa,CG"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OS,T>"OSb4BHyXIk2X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|Ec'X2|CHoɒ)؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#ܞH>QJ$8%G^4 lϪCbRg4%R8D"q1D;$HYUm)g7Rb~<7 _"fWCV!$hA]!MUt=(<Y-Lm&9!/u 5RaPt(QYNDNU\DBQ~O>٪K'E~#:sw/8SDʕHARl+r$ ubS/bQ׻|$>5rQREtwIV"لU]$tWWD%uz,+)h)ISKQJ  Tziv9MGٶ$YH}`VAƺe]G[ny-&GY"p:U |g[0T>^hջyT()Y*gUpUKjHG1dtseaQϋub^FY. TQpꮳpooqHIi>c)B(wˢ[LөZC#=RNC Y̤]Wg4%U #D5UpC>>5/AO4 b-F-u=kΆt:hjYSWcp!ou랊;HUZbmb/IMb*|#!u'P:ACB URhLj4ћdRޢu& v]qWVb`h귫-QmBpJCa]qn^k؈+8#7"v 4V"mZo|% °Tl*цKoij=U4=Ge=\; 搄{. FYGs,Z״DB*}E$DNUKG\YEwTI%") ݲ"a!-xMe- 7 ^Qj%G/XRRl+h.i:oX/ [U7D̞Bz%wO RjgTꨋ/̝7 _!MD-8&|#!ާ]D%O.I cRRlҡÑYQs潈"\3r6I9[Q9joZKǒGaϐD5T൝CcMLꨌ{ny-Cz[nqMU={GCW!NKn~:7]m!̦? 4uuuݘױVq FnFwLۅ!4,Q5d6Nۋ)+lقGRx^IsHB^>CQS z7QT')]kNm7 _!MD-8&|#!ާ]D%*Dy'~ VPC8vf潈"\3rECE muB+ie$S*h1IHMj>b+=N  ,f}f"S[-)R)uH3BY|&'o5Dc}JA㖥zg3u~H2[|*50!zxDƮCzu|~ki߯¦ :P2.~ ^k؈+8#7&q$1> iP,Č6rȤoh"㌫6^#iKgaz"pP~deQǮ7tK2J|%bZW^q {^[FUD>^hbS[km;N T'ǴiDC#5_9 "0!pHʅÜrQH)|IsHB^>CQSW/nGp5m⿊V:xo)[ny-Cz[nqMU={GCW!NKU'~dL,*iPf}gn8tNٙ:Xb|{Eg$f2\ U;Jo{D1JzՋ|; 搄|' Cյsd u+J;Wz!蒩q;{ny-Cz[nqMU={GCW!NKUyv[$aaS"SϬT$!ffTBOyb#ܑhEHԙRer qS0AB{V"^'OPM2r9{o/pzܖ; 搄|' (~G5G!!1h/-*礐@i2Ww\n۾b/J^q {^[FUD>^hbSU% XΣF"$YqbkXZ/ֹŋqbkXZ bRvu潈"\3rH3[!LD GJާ)4v! { >]DNUR)PHaP]Jd)oi5֮0R!ane Uj!oa5TC\.:!/RZI\N}ы{Eg$fxg4a9{H/x}sg4%0=u8MU~E|1b'Rz~J;EQR?ٞ\=7 _!MD-8&|#!ާ]D%]I;Ϻ1yb#ܒ!BQLhہ{f,Jm@2-)~e$bPP%8Ys[`IAHE\; 搄|I y_pwG y_:JZ%" >c9'WX덦LΘQ(Zj"2ؓ$=?42TBd3>  JH$d8'C8'ABifft\ W)*lWR>y:u?pOSu?pOSu?pOSu?pOSu?pOSu?pOSq+3#^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱyb#; 搄v7 ]4H|jl^k؈+8#59!/u/8l> "0!pHliKglp!ou8Dƫf潈"\3[83BY82[v#!ٱya:~!-7"PDE&{"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"adY?B&OЉ"ad.! ԣ0hw[EbIGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&ad} YBfGЙ&`Uf> aVXS0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3 #L0>,3DĪW:ՇrXpJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙa)pJf?ҙ\]9-,Eg yT:㧌t1:xOpmBӴduv+8b@MF+hLuM31_uܨk?ao+3F|iݢ0SFJtwW6I)NV-*g-3 0QԚy}]m$hfyq(h&H'hHڽꭜ~+sW;DU0ZJ[؈+8f9!7E+%Ns]Fj?('d["^jn m¥RNC.-'ዚt7~ hmACpval9F|iݢ0qH&6]r.w:϶y?̗sKusݘ|Gu6$D~2EgS~ŸyN 9؞z6\U!{Vpsn ].u^B BSRk\˜qp+nQ*A"Gpꛢ )|u+8ba;\1x$I(>ڨ\)$Ꞧ3NVpH-zNsoט?-9a\f߆Fo{ԗh*wտt1vU@_1UҮT³0Xdm6R%%S*B|[)Gʮ8LډE!{Vpsn 59L *Tb*oQ%^ ʿ IJk6r?X96|S8Q%?Cy}^σM;FY77RzV ˧Ϋa &OoטFVy]CHm^QNF|s 8(~PC 8(~Pr!{Tj9;wW=ه{D?+E]|L0p-M'/טM;0fv֯Yg\qI$|tU%:}vSjIǖTkQDa3xۢ#M1 )ReܞQQkmh?$4)Wv[6DD\\uM[Ҥ)uT8^^28Eg \׺5E/"JYT*"!dR0I$uҙ⨅k[,9ࡊF)?ÑOo[)j#> 4Eg Ǭd!4]e *ThMJ9v°ҕO몙%Q~U̘ST _$sݘ|G+'%%/^`HAR;DEXMk9[ffp2SImvm@_1U;F/2E, )t؈+8f9DЈz5pJ>/ޤʸ 4Eg ݉q.$$j9vf8"3@߯1U 4Eg 1u7ULPx~J*FuKlbU$8!JrJ[>CD/ /טhc37Q%)gD k΢y=+^ZK3DSCD/ /טh:3AlfU-5/6x5Cj"Jtnb#-_/=CͺE H!\F$JVp|+ BAQEg 1u7[D}eLFsf!xQ~R'YTPy,t4>Oj\FFY7Z^zoQuKh)T E+@H".k1X_ ޗ*+8f!Fs^bݠн;)xTDVh u{ Fs^bx_?P)W {[Gu,&:VK}8tnb#-_/=CSWSOLiVnYSGXjQH;h)bS[%m'ዚ VkyÑ 1fuS 4YT.iwU0K]LY)D*BEs,afuSnEg 1u7U0K:TPf_~]f4(RR^y4MWHH[D[&Nو8=va!uU$A?Dت4,J,+JOXCbQC|T=ͺ7{Vpsrf )'b_#כ[K Zuu|G0xzx*IRN IAHEUG"bpa~ڈ\ wh"nrg:*oKc0Pf\?ȭQ4~RѬyLb=Lb!D{[I؈+8f9 WP3Tj$!) dCk8Eg \bmD. ^FzσM;FY79 }3D M÷61tǰJꤹW=ه|^#9@_1U"!R8$˘dGQ=Zs.b}wEg '7!jyFjhT.}FI>dQ!(dG_i8Eg \bmD. ^FzσM;FY79 }3D L%)}3: KlbܕfӶc(6Usݜf!xQ~V8F]G |YWhzPU5m:2rs=ջ݈"o !T"lLu?p/Su?.6*JI/:vT(ТebnBR2F©:oy)Fk~Ye6ۋ%^bC2"K{'quSp[n-N.p1wSO -ȋttG%}wSO Gu??qY D6G̣ݢ0b\C'$^L]2Oup=~DQ3pmeJ3E^TQH'Z#G9<q[?QǷyS8ۢ0D:5*%+1 qvȂ~e3R}va!r5,JHֺd8?X"{cVuʔg=1RF^<NBT4%MkU.q/6U3>={*e@0J7gӮmvv"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanb#q8Eg \l0lf6v"0NkgVpv#ᛖvanacZM"JN~oxpm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm5c aA:pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g~3 ߌoq8pm86g yUfxYBdF33|g7o8'qOx>3|g7o8'qOx>3|g7o8'qOx>3|g7o8'qOx>3|g7o8'qOx>3|g7o8'qOx-"kka/+8%yJ8Oxp'< 8Oxp'< 8Oxp'< 8Oxp'< 8Oxp'< 8Oxp'< 8Ox#9.IFooooooooooooooooooooooooo“`-qiEgVka6FY.v-M;mVplݾ0flDa"[7o"ٮ3EgVka6FY.v-M;mVplݾ0flDa"[7o"ٮ3EgVka6FY.v-M;mVplݾ0flDa"[7o"ٮ3EgVka6FY.v-M;mVplݾ0flDa"[7o#׉5fe *aȒ+I?ΓN~Bfao^$՘J!sM( !pu!&mB_.D]jiDX86Լ͡/ʗ8K0 l#jN~GVp *e+h(!lbc&M3 f5[E#{I) KFt:_GUL8"CdQ0l&] DË(qt6E.ȢaL8"CdQ0l&%TM$v7Go#Qpe.A$M3 fie HI'V!n8JJS0:tαx(hԢTƭB%!#%$CKjA\keps(n$Ҥі컦QD(>zva!!z4f$(qCɩk$vS)[DE\bh㟂hv[n_B]7}"Jd Dœ* dߎcJJo\Npsݑ Ҟyͤ)K}ohǽ/Jj/]7!=D0$ʡnUVQ%$[ I(zX%JE[&`ԨRy-ڠeyZr"\-0P Q"8|L/^7Rsn?uD;faF?](:uM@A#hmgY=xލK7ͺ0mf=ۣ%nQP]fcЗYys.}TtmћH=UoQ&iMpA&u,aӷ)4ڭXU049y7i("hsaU_1>I>=o5HvVJԣ"4I*R.Kn凁Iz݈ MY9>$s A5a A|%&ˑjQ1pҳfhU{-P(U헫0e/R<ͺ~oS9~}WC0f*J,ϩ=#C %%EPU&RB`\4$B1ˈO:_x6iJU livX۩Ý+gUL:9*6DI$GI6˩9S& +/ к:abC}G.$:ˆPa/+f":I&Z+Vj9 vSTAh/!.'V8XKIH-'YT7FOvw+8EDInWCȯT.&%dMQ"1eK]DI#ơwT:R},{~֏M|uWo#tjQr)˭]-4BRltNٙ KȜTٵQ*-9(3$'ܥ џtcԪú'tA^J˵&9B &YlJSZC*aS:UI*RǷQC0f*TR+'%L2_h& GAɼʩbTX-,{&b6)WA Q|\m-.m}hy}%j* 'آb(|Fq(Sj;H*4*NCݢ0pD"x9zmFǺM4~1[_jY/2joGukzUA^ouv7D$ٝ?B(}EM4J+h*PY:vgf1E֦uPqrfof*k41A"TiQv6[ʒs7 I!7dS)G.껦~5_|IW8%I푖œqD$3="P,ӏ5'F+QC0f*(:qcRT Iݥjf1?&i7C݉ƔhQV2:uMLTF~-'#ءpJF PtUR-'"zTT*R2 IH/R.Vp%ΕI9Hʹ1'$t9yZǔ:wռhʘGc[ٰ]wFYJ^{jr?蛺-J%z5_q.RE%YL~J2UbSjWI{~IJe̮N? D6}\>q(k&7=&4p#U+PG*ϭ3a;?TQ{U8㨋(>~0pP=ڹ#%QC0f*"ru'Pf}&[<1$U 4TPȯUN#DzC䄔bHZ*{WQ "/Mo.: _"F"5jpu mD _a{?ջDa"n@n8n٨Zq^7~=w{=GZ9Y*O{go#uDL2ͷZ:d8$""َ?D:H'Lg}NΓ5Һ+)H&+%%!B] ]?5x<k"ƅn #:J^QH ]]s1zX֙(s>Wu?榊6ڻsPU+n5j(Gץr>r?U8M# ?=oJs<9wUQe)r0$,E'\sA4^Etv] 4NQC0f*ΕTKIlCQ8}%I|:mԒuS/bis hXW:P zϙO7C(j)sKGA0~suw7QT/1B+.Ot*(YQA}1zi[FY.!b*ܡsI~ AÕ+ldA)5jݾ0CJWOW~uBAM2HBaȝ3ҟ8}%`GRKQ"ʑpn:92-I2Wty o9P#m\'\v h9Hʮhk2O=EtTPb'T~R- T67_ty}$So;Σ/\ChjtMҺL􏷨T5g)홙Q4uĪb>I(l!z6S%?~ʝuD 3=" ze/)홏/C^|B(u~EP| Ci/12W *) E0CDu3b(Ԝ\1K{ =Zm5ԣ?.y~o}c }FKyj=$g.:GcZC PѺ!g>Hx3?'ht#+*)f뮝23:OKMEՈ4sTgT4jYTFY.!b*Z*gQ%%b3a2]>sɩ[DB&>_FgJkO0CJLMYKFMӐ$D3Ju%ThZRQm6Y \ʞ$R7D|[﨏t] 4NQC0f-R2N;J\:})DK5: i/ʄ'1 z!AuGQLOVuB4ToSCڡ=yB"Մ#wOPAN%o],ݘ"n8)J33#9 qh9㩍{~8^Bm؄\U1Y.it] 4NQC0f-ոXdyG]Q%).s1Cs"PѼ"RCһrPFuҬa~lAgLms:# k;VؔhJU8ʩK'OT!e"#xa_LAI9RɥdD~2Eg\4oGp$ R=餥pum?D<|1 pq3ΘnJjK+ˠZQ3/Eړ=Qt] 4NQC0f-7]pJRRtJQyM P*!#^ϺFI NG/JڞP㾗zBz?gvD+ȹ|ߛ^O^:Of&_$gLꋢWBZlRf"Dppͩ\IJxquG)Eg\4oGpk?#)UlUħ]0CJLU Y|3,W6t hcd8ϜXYRsl֣IJa*}[!\"&D&\uN4f|wE0CDu3bn-(uQZ_4y.֜!:D d $]kZ YA*G% K)0䕝w9֑ۛ믛"UN5(Ϝu=Ѩ:T:z<^ޯʞ>2^) l%rvLg}&3œGbɌ1dwc;Y1#3JvZIKE," e#=#XD{ӚT:j[+s=&%mxq79d/r%? 總Vg1sCt@ƑrxEg\4oGpe G]W7 *e1gNG!Q! r:‰E73DT:U|w*}" WHH"Rp+2lR\ݻO!w:s1UB^{B9oQvŽoiT|3i{+eU7Q-*.c fBtב9]pa)Gm%^ki*?nVpXsJjK+ޕφ{΢"?aE3(֣>Dr?U8uhE xYi[QD6UW pyyu] 4NQC0f*Ktp6_"E#[d3i{*`״GYiGPiˤߠUku,J("C9K2+FY.!j Ey'g\ş'?H!eIA2]Utq erm$$Ys?N~yVԪwNI/8#v9 SV'-i?);GI8N {ˡTtNܿ1PNQYI9 tb1)(|Πĥ/MÄ}N$FUÔzW #!jTҖ5H1 *o% Ov] 1Qw^J >j,~;I8Nek5yLzUP1%K9AavĞ朣9Ķ~e ^l?)(2ůѧYe'gh꫉ODF)L RJڈ)1{3ߠq^g@?E8/~{3ߠq^F ?>F':RL%BsʱЖ?p{F%>Չr($0gD'7%+[`AX\s~>w)E9RvM{|# ٻ|awL&ٝ+8E¶nE] gm0pltmh"\+f[50fv# ٻ|awL&ٝ+8E¶nE] gm0pltmh"\+f[50fv# ٻ|awL&ٝ+8E¶nE] gm0pltmh"\+f[50fv# ٻ|awL&ٝ+8E¶nE] gm0pltmh"M!m ,G($ސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސސ5uLbV!XbV!XbV!XbV!XbV!XbV!XbV!XbV!XbV!XbV!XbV!XbV!XbSlC"+,)Q!, !1Q Aa0@Pqp`?!'!! ??j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j35YUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYUYGIڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬڬ ?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j?j0\8D $$7ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|π3 DL$46L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&LPG J*TRJ*TRJ*TRJ*TRJ*TRJ*TRJeHXvuydɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dhr&!6Vg uB>ZF0b"B)a>H38ѩwzKz*ҩ#+"smf~#H0"IM2\-;Y¦KcQ&e Ssmf~1 sOAp.JRg81kI7L#rHD^! K5> 8e=k1(aBn@{8X2\̗N&^#0Q<ʼnR  ` 6zq<#rhw~o|>D^9 \*hԻ@$t?.Ssmf~s̛IK88!!NpIDI`&v2$D,M ,%H@4Y1Kg,B{Ǖv(T{XxSF=FxhmtSsmf~{@0 A )1ɰcy= /%F5@o n&dn&wy;0Z.aLQZR`2})4j]X:Nň!aEx;0` NͶU_hS$ g|3)pSyԤ\uvْYXBA g/Y0o܇ 8Tѩw G 5;.b w X=Xpm1C͵)3h^Gа# l~F8dѩws=O@f$w|.G EVpm:1"M!t">d{8:ե0vI .cq i!Āb ؟\dnhԻcq@nL<ܜ0[)¹ʳ?_Rg^PE=#P!(;;q̖v/7dNT Ax<"hԻKɘ  iL h5 ļG`lgbha1m:)MaK#;hkcnM˄%AYm8y5.p*?IЕ&L%0a}O8^N:((ðsY1B-Y`i5.p*I$d\!nwvE^KY8,,,O2X: (Opz7Be.[ 1`W\ bH4j]ADAnbeq7 tbjca*Icctg-\mVW %D ,GSFv *򿣩I{̉1ssp1&4j]kpm+:缜,B`DjdAGk4*`)AMyFv *O@]#cf͇`s8I8*V8 &X擽` 0`i/_!&K,c 8']B-B,HjF=T@@b"6#+O)j#5.⭾4h;[lHfʳ?KMs>m;&yFϛl3Idѩw3*㿒g-4j]ʳ?KMs>m;&yFϛl3Idѩw3*㿒g-4j]ʳ?KMs>m;&yFϛl3Idѩw3*㿒g-4j]ʳ?KMs>m;&yFϛl3Idѩw3&& 0 s<2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&Lf4P6[l\ g2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2a;tJ`v@ @ @ @ @ @ @fl. gdp1g'j@p1pY {7ϛ1`о?1GzTD@FO; $p\Dt -EXS}ѻãGpY]X`= 4y7qH=wLG <2L pZ8dANkUP<1ղ? 3&= 0I)BstcAb_J4(G3l"\< 8;t}iML> WyǰQd^] s٨` ӆv 3[+3/77loF7\V *T0aP ؓqʻ0,HEah`i2B=.Pa<aí[l:u, HwXF;LO<Ġ!.ũ<FM7#`@G"blI<{3[+3.5 !s Ҏj6y;uyѣXq{qipb v27^K3[+3.:Ǭ0`;`͉/&sqE.ޡ` MȽ70l'dؖ<)p /~^>XA#iR6Hy=Ęzu Hf:Vg&b1x4zML 1dS% ($hr`ϝ:{ S"dϱ D6n&s5`DT3@@YE+Sy,1)M0;ZjGyX0&NFHNf1]|/GHbI;\/0BьI<𙎭Is?A4kGTE)] _GMZy&6b~"Ȼ2S޺C(;$4 >0]JD $` m Q#ۆpi ` 8/n| f:Vg&|lW)5 GA I&ˌ<3 LC^Ì5r:F1Ά؍p0ApgqߘC"n3pC`ȓO^1ղ? 1 ,N 69Y‚-@I5}ÙK:͂;0oW&c1A QHIᯒ!ō )"Xbpxxpqjw%`=zr#9MA٣Ļ.1ղ? 0fՎ7\Q#0OW mpb !u\+# Ŧ 6g28z v XDaLSTȍ .okRd9ԋM@8; $(e'xhu :{-208:XnTs+.#ulLi9.Sv>2|v`ؠTν ܾ5`P,`rzYtÌحw[G-N"?F.h)YD qrj)A"cÓh!uulL(OS6K;v0Gl]jImB '&6v7ם @pc 05 &K9:GB{ $h)7Q1ղ?0Kx0ؘp\ل7=@{9Mɀ=ݞ/ bPdu6dcpvi Z.؀jS>1ղ? 27W_f&%Q F 0zQa=&0RDy<04QـyAq(ah l'&y(c@qsHýkxx?E(#Υm_O#ph(m =(`C4cOtL!Ťd<=D~! :VgF"ci$s3w|!6 e9ԍ85z7,DÔ}BאbOu h\WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWSGABد/////////////////////////////////////////////////!71E1!0 _K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K_K@X^Z/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫzkQV(ʠzh׃ (L. %`_5 h3w%Fܢ5R$,+T +N̔ ^8 > /}Bc̄o faUXPx"گLԐ@J`;ټ1{N-IDx<n-b^LCet6&ɉ̋s?0`יLVYV%4unNP"1xZ42s攂ڜཛtf!p~Gd:ϵoIS=);4I Dx!2 a=/X$VSDzvjTq`X04atu ^$Vx0ћ%A0;QZSF}ާg͊!%Ջ!Ų:Kuڅ &4Ixie 4:v.Ll.t٥ N: !Jl/VgYFwQ0#Hi]fq5DbLxFΨn`V6yJ-1.G,A g`%^Cz1HC)`v5Ѡk$fN/9.l[ ċe)p|2̷ 06@Zdl0,1ǻ,jzVgYIhQ6(Hh" F{ѢyJ { Yb!-aj}Xu.;[+3ļl"π@Pp!IL6 \p`(,ˁt.,L/åfuji6(63{UX; x ! ؞&; ݁Ų:Kn."'_K8"#D)hL.c%d_nS bjfYgڸl͊$ ^$V¯!dIebW $` ظл/z2 űYnp,l\=ѳ!QYS㱒Auy+-傋?[>flQ$7ulg$ vvy 3N j`3&BlVYV%|"b:aF =& DOKfz2m;4iedlc݆ b[u}آHn05IU`8*@W伝X;.&yX{2Le)`“ 7}آHn05IU`8*(@~, %8 iCפx [+3ļ[|@=%ep5>;.&k`bK%aD)q` ,%4syYgڸl͊$ ^$V¯!ll.Dp_ y;@dAJ pUVgUx0P1XH"7b]#xZ42j|v2]6H@T31m= \Bb3[(`艵 +c4/&oV3:ϵp4ٛI fI*]^BHI&cv52$;8*[+3ļ i,TGeaohI?Հ<X!H`Kawiedm{U`C>d`@I%8a`wѽγ\ 6fCwYyJgaW+6 eBz^MD I$I,Y@ VYV%)ni$K{2̸M|xi`_ ap7}آHn05IU`8*pqlΫɭZg=J < t,ˁt)p/Q@ Q>flQ$7ulg$ vvy8BոVgUxFLI{$#+@jaGL)g&Q& `842fǜa-hÃ9oAI6ȣ?wj4`#"mh8f(>hlo3W )(lH7aJDT-{~2IU`8yXDcÇ$@szÇ8pÇ' 69o+qlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$η/3L.gVgYgJqlΫ:42ufujy$ηЉUpU«W \*UpU«W \*UpU«W \*UpU«W \*UpU«W \*UpU«W \*Up`HX:iaR¥K ,*XTaR¥K ,*XTaR¥K ,*XTaR¥K ,*XTaR¥K ,*XTaR¥K ,*XTaR¤G #KX`KK ,X$I`%K ,X$I`%K ,X$I`%K ,X$I`%K ,X$I`%K ,X$I`%K '   -GH+ L%0J`)S L%0J`)S L%0J`)S L%0J`)S L%0J`)S L%0J`)S G:|LCdUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUʣT*Q?GUo֋ D~UoʭU*Vߕ[~UoʭU*Vߕ[~UoʭU*Vߕ[~UoʭU*Vߕ[~UoʭU*Vߕ[~UoʭU*Vߕ[~Uoj GU U*W_«U U*W_«U U*W_«U U*W_«U U*W_«U U*W_«U pMyx~Y[~o­U V*߅[~o­U V*߅[~o­U V*߅[~o­U V*߅[~o­U V*߅[~o­U V*߅[~MefuVYgUfgU9F;+3Ο2us:0<1YUtkfYtgNgQ'3̳]\Ϋ25<+:s:vVgUi9>euYay]5Yәc:I,W3̳ O3ΜΣZNgOfVejyWMVtuΪs:|5,Sj3efuVYgUfgU9F;+3Ο2us:0<1YUtkfYtgNgQ'3̳]\Ϋ25<+:s:vVgUi9>euYay]5Yәc:I,W3̳ O3ΜΣZNgOfVejyWMVtuΪp1_n}j<weBJB T%* ^'(8k`ڲǁAwk,(J$0Aed*ҫ kh@ %Uޕ]Uޕ]Uޕ]Uޕ]Uޕ]HG{U8 R26pnM[ʍ ތ ! >FFN;MtF;+3i) s|{dˇ R#hAk. @,Xl ̳]\gs3^۠>׼ pпj0X_y^F^5L0ᆌ ]5YӀKv5 9vxr OS!r%waԁkl8!c:Io LDAN֬Dqpks /kP T9X7tG*X2uoϒN2#NVs{U0x1&_},S:bWcIt|0|gw@{U7 Vj&e0Mh<>&&ֳ{J01YVejwM !)ʝǶ4v85[&tgMsCc-JsuvR`b˨z:@ '$#bI{Y kC2oefuVx%G.ĐyNHhA` 8vP3K`1%e.?w0=ĤjC #rM'۽,V0Ht&;{O_},SoI<?w&dI3; ϩz@۷nXWMVt޶q Kֱ$I3;Ӆ@/#g C -nL؅4ߛ[Q:#LKefuVx/t2Lo&$waIuChdv2uo@}ܧ`kE f ˓X`}roW?ԸL^vX Ipj0 zE%@rHX$dO] Ua+:oÉytA| ) %I0dL@SŽˡKOQ&4{/ .Hv(( Li7^)unK c`əo2uo&FFD`o5yfe<}q4of']Xlj_},Sr@vrRGY}/O)w\w36@ PY7Ot"B5`:5GRmTƱkP;Q&ٮ`QH4bI,,So BM# 4?1=NyWù{Of{A .=i޴ 63vܰnAeɘ`K4?&_}̳ N@pB[ R>0p墐43 6?A?B+:o!v /;p tXS Q`Be3$C i2A c:IѧklB O+'&|5:,g sE3Z/Ya8mp 縏#*8{U8AK}3 c:IѧkmD b&pD[C1SY!c>j! qm`Py4@eګ25<^NՃv1C46 ˂c"BUv܍ j? 7]5YӊpF@p9L&IF /|=ZF6xcT̐XxAwp  ^7fZN>V#{G4E$@Hu SY},WJY!c>e阺1B`$б7^;pcn0lk_ zZ@7 lUfYdBB4!{M U8VCRsõrJa7Ϊp4ipO{6` 2up9 77Yay8CwOlbwWMVtj(/W6ȝCM"wջʌvVgUi84I /L6Ki,W豟k@}yUfG.pX`Y+:qA6C0k. /f|$=*]\f6(ټefuVO0Dbu-C=%St`Ol;&9̃yOfE]ńŀer3|}̳ O.My ѰGJ,SBmIx*/!aT1~w]5YӋpqk(v :瘼qB#GZ-)i'640z6N yQ'FM"ey;{OfE__},SdKvWnCլkDrj῏< ~n ]:ZN>Sj$Gt؀:de1M3SY!c>j0Y8y%&7,n"f쮚9w=1(G#@&چXKi$F;+3 ' , Fv_P2H:g%0ɤ1)4XXw@ٟB e01+}K;|5SӦT hx}@:tݾDYaZ LE"=Lëff!B_r!ptBӁ( %(a%c;U4;&@%gYL0!Bd k/B|qEV KYw%2P F;+3Ο2us:0<1YUtkfYtgNgQ'3̳]\Ϋ25<+:s:vVgUi9>euYay]5Yәc:I,W3̳ O3ΜΣZNgOfVejyWMVtuΪs:|5,Sj3efuVYgUfgU9F;+3Ο2us:0<1YUtkfYtgNgQ'3̳]\Ϋ25<+:s:vVgUi9>euYay]5Yәc:I,W3̳ O3ΜΣZNgOfVejyWMVtuΪs:|5,Sj3c O A!& M>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>B>BXAAWGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGC6D/Okxv Lrc&91ɎLrc&91ɎLrc&91ɎLrc&91ɎLrc&91ɎLrc&91ɎLr0r֍tFbxX c<,g3xX c<,g3xX c<,g3xX c<,g3xX c<,g3xX c<,g3xX z3xX c<,g3xX c<,g3xX c<,g3xX c<,g3xX c<,g3xX c<,g3xLڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRu=鏦"dcHkM C iY.< R0P ĒG!DAtp?TR46X>"aDFk ;J IdbpsDgTp@Fh34hgpu6z @ @,o+3YO| WhS m^s Zy-N5H]Vv+<8N!{2"3v .Ba(ꘃhoY.  ( $KvT K !D d [0FN!g``C>{F̂S&yA! | >Fzl{ ^Bv83B|; ' ag0{+ 0AJ  7mܚ0\MrufQcX `6 \( 6F63#zLp5*[{8YIf&&5f˄1 2 t疂V8peḑrf $cdNJ8MdT)NM|9ݴ+`&P՘p,xEe {{w|r/!Bc>0nO, H7@a Y e׎fuS0Aq6фԊgTo]A݁6 Ui,$%HSyY{5h .v]"n uܛYvlG$܉@X0&l|5txx#DOf 깺!n# -VÛ>Ƌf%ΚCP 25_`Y zp`ls M1`fuJ0Fkfui,q1iaՇVXuaՇVA8%,%(iphn{NUӻ5"%-cQDy)F3h;AH /g`J( ֮OfF;] :k%uM݁} 7aH$0 i \ &;nH›Yئ wQTh?DgaxhwOņ"mfH. I"Ãq3D,3|, "h6"Is&NiN =mzBq7.tXa"DY߫3T݈Ό/ u2E0JZM>Kh.+t"31k3YO{ spa@m I+XM3$O`Q&$$ǼvɏAY-aO&g15cmMr$0e}xuo@ f'0`Eˬ~:ah: *>#Wv<: WVA\ &@"1`a6 P9T47Y,IF_0A> XI;@Gu2rFf fuJ xpnA\A3#T &B5LV*oqVtL-wok3YO{{,҇,Bˡ[ѐ2>c<74{46J^`m Q;H d6ɉ.tKx,\ O AI dxdǟ徬ΩRiXIs\g9,Bs%fŞ[!o8cA݁8`=2mq +,s:v+W 8Y.(j,F`E7[v|Z `QPZ#*|7>Q1y ᰁD% 1.V[cI$ē`Bzt]E?fuJLZM{o8 6 v;1p&gG՝6$ 1q' C$ƴobE 1%6 \S[9Dt}eV #yNqQ h7iWHaQ]*CbN:ތxȂZ4bK6 d>1.LY7ˌ /.bK^M16luVeaX^Ht3Td*nqCi4u$&gFnwCz' 9J/ QItŌErѹyNqQ"`8LQі6䮵K_9ó'vـ!+@'P Mb1&$Hs<g&.FBp ^I1&[ ٚMC=3Td*n^ y  f`!Qxp5&g@2^؞ d9M2_Nr!$-íW>p _B{O\! p~I6 fϟK !bMYРC@G`h"o0lΙL^ΩRiXI;$f/ĸ`p&s fk)ɬYK1AbĔpu%} Yyw'Do4鬗!MhRgg`J t\'n{XL̀%<3#^nh: HIfNewX)b Guͳ>@A&hΰ"aəwՙ*\ 2ki7 v 'bP]PDDi/$5&gF .kalzs i9 <5ȁ! 0nGd T[waHq"tKy|]$"7nRB-E2o"0yAg; X ފ"RaŴMz<SUÂ/7md`Y-<0 8ٳf͛1!HkByvZb9@L `4q+81 k!1$,6"$b7.5)qvVxVfŞY0,`8( 9T!-uq:yt:k%f>/M if8 `9bɕR`ɮBw*\ 2ki-P Nͱ IuX^ VfŞZL g|& GA"|p.{Nr1\='_ S`H2yp9)t$rFm 5(YRxa,K_}l 2它e=,[fУbYeh R z،D fq a>H`GC4,KԺ%@3\`d$#IS\ u2_o2BA}pC '>) K2e UPY2LR|HH%O 0q!D4W!@6 5DnF>Q9U`2,\kq6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͫ3Tfk)Ӧ\O6ΩRugNs=>ڳ:Kf:k%sj.gY{t鬗3ͪ,@JU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)TRJU)D a'*PJ * * * * * * * * * * * * !w'f"""""""""""""""""""""""""1yZ@ɸi s<<<<<<<<<<<<<<<<<<<0 0 0 0 0 0 0<<<<@<Pp 0"<@  H(@0<P 0 0 <@@@P  1  0@<@0 0  <<<< 0 0 0 0 0 0 0 0 0 0 0 0 # 0 0 0 0 0 0((P<@< ((P<@< 0C  (0P@( @@PC 0P (<(@(<@  @ (@@(  FP4 (< @8<@ @L@@ (D2( 0@P <@< ((P<@< ((<<<<<< 0 0 0 0 0 0 <<<<<<<@<<P<@<<0 P0  < @@@< L  (B0P( 0 <@  R@ (@!0(@ @ P(8@(H L < P@ @< @ ( (P(@<( P @  F"( @P(P( 0< B@ @< PB @<P<@<<P<@<P 0 0 0 0 0 0<<<<<<߿~߿~߿~߿~߿~߿~ 4vIUn͋,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbŋMNyR@ybŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,XbHD*9]0gF4hѣF4hѣF4hѣF4hѣF4hѣF4hѣCj:ð`YҵR%yϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϐ>*% # Fݣ;43Gwigv0߁a>3H;|g~wh # Fݣ;43Gwigv0߁a>3H;V́ Og>nnj{/.NKKWJzD-]& E3Un|QT/n1ȱPՌ7?S$"EjKВ4={k-&=U *Ǧ0U]Uf͚фo|fB`ݗО%҅n<zK%xnr8C77&GS{!F#7qѾ LL.lh+"`HhO8`XM ĻRӘ>1e`PIG:CZZM@aWUp F#3w0!5ϿR >0jΡInיM1\,IXUCv{˰8b b+(1]eC 7v2L;e7la 0\gtL 9/pMykGwcTQApF²1ۄ_`X0~!(N,*SZOaX (o;Ze`X  d-e*;[@,.SffAbCva&B H3Q4"79dQ1b1bޝf( 品E9-N,3+ W -N@9.+h?&D0)%,V긽lJب/ RL)1 7L "P`p?1}HH phz;NJhO'y][2YF%̂b:S^V"BZ3eKxX #XR< R7~I ;;EwHVb7s?P)$EBjfw_{+d)[J1K`XfLKu]-Al&\S^XHtd/I2!- L"lK=כ)iV hnf_SVvOQb`> vCX- B"DJ*[ iFQ ܨޛXW^Ƭ`y31@?|ەXa + VŴLQUq{d.AopEQ'20IWWf? "U U?\H؅.quKK>02ח4O3@" YFP,JLkҴ|f$"p;W؎s< (q #~='X< 8ID@(<zFQe䘔^Fl${P%ǔܬ)mZCI֋Il(W[.FW!V_lAwLSwUlMKۚ Kp?jD<9n|>QAYP<}ޕ8P.QlMELO'3O-.(eopME@ǂ8M~\`eH[1Bŋp|SY-kWUIrTY>6Hm`Ї E]B۶f&W,͕,x1}{^&LD^i`kx.2{>3U'e זK7h/85fm+-Ux43pg\O9>'=4|f(0e ܛh$gc3O_5P8Xs]#qa ;'?ѹ>';4|f+@,]H2 ^ *./qe!`W_+EH$FI#UPݱQ XO;j<[$ X`Z=B~<[%ɌSkw 0hlc2Dq/A(P>3UlkjB6th^#卙*ν73iD؁>GBR k Ғ.!)؝M>boHfwE54|fgafؒ^m},Q**UfwE5|fYڃ:snV0=yhb REPC8bXK<7Q. k>3T҅q>|ۿ ![߀Sـ(~J*TRJLRj++۔i΅bRe;¬%fovjk{KSQQ>P 4m?xawK23 󾀀bpzđ8>tB߁a>3H;|g~wh # Fݣ;43Gwigv0߁a>3H;|g~wh # Fݣ;43GwigR†X8f|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|J+v[!PPJϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϗc)(VV37򠠕`1y*TRJ*TRJ*TRJ*TRJ*TRJ*TRJ!W3%iNv%c޽zׯ^zׯ^zׯ^zׯ^zׯ^zׯ^u FRV Oo-ZjիVZjիVZjիVZjիVZjիVZjիVZQ BI ׯ^zׯ^zׯ^zׯ^zׯ^zׯ^zb(/R/@03ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|f+tߣ@kK34hѣF4hѣF4hѣF4hѣF4hѣF4hѣF4i\Uy&`HU =ʪ? {KT4~:@*ht.UP\UCGirHU =ʪ? {KT4~:@*ht.UP\UCb$U.wYyyobH(1=X8`ZkP?y6Q iGʠOU#5CR{XJG(5Q2 }^zׯ^z:i&dUV2;4 |Q<eDg>+7s+%W.%Izr8.p hse0G:- jig7Y3UK * I}m !vh`&BW6%#[`JrB&H .,&p4p3)% Cr,?]K> ¡5D#ǐR?wO (/~B`d2{d.{V]Α#Hq\mI4=ɓXZ7R V|THc[MNQ'1.5r_C'݅,UT,bobԐpb,ba#`6vP&҄Yl4s Un=\)Cra, 3.?GuGiL%I+,MX؈IP=!LyEN003vR5x_u RQ+5"Y@18G| YyK(K2Jy$_ic9DP*{p 'rl` qJgF8c!;&$x֏* X VXu~{ Id;'(@`shGx'"  *BBꬫieL00H&,ZXt۝vi7 HnYU 6l_wC-UK5k<9č8*:A(tOΐ;Â5$ȼc鈾@%IZ,eǡsҮgM2x[Q."Hҝ B02PꦕY^Hr@4aHG 9Fv|t28@ԉMN\  U.Nm)#!<2<zb,hYOR%*,IU#&+% Un J. jՉ.#yF"?/vAHo%B!E1@a(b8j<=l-p CF09#$"jncy}N 8X;mIKgv D{vz!I唹]~b )%6+9Ť`/ `]tpwfDKjM=c(R"7ѽ3Cp/qR8t˲gdQ~h,mr8/z(Pt4v%r_b"sWt.;7zya ,cfr 8,PQkX9]T20X=>]@rK 4 ǺNŀ!`",$&P! ["Af%"T~:H}\.\TĻ=}P#Z798[|<,D3JJ\lb(' 1p! vb?yS&N+ Y; cBȉ4jX /NcG㦔.lCx.v·@  0t5hgMֆ+rS^.`5[yL!ϖUCA~$68p9;+o'@r?#R3֮\`L3Q irD 1zk%s98\BSV;2T3RTBoB %q{@EYlPf8*dH`0YfrYʅ:k"2BؖTB$*aȇv@Q4gEa8Y8 зc",wt`e>tm n样 2lN1 * XKܻLAi;_P ",&k=ưb;*0%lR6 ʔQ!SBIHDR´` pEAt`F+s~81thY)7Nڨl`--8 2(, %mǬ$>N E:ARȈ@6#- p=(BWbgA, hΏJ{]]VcQP-ʈ" fв):sz(^)1j(N.-"Xj\G0Vѩ&@A*AYaymT/m\DfͅIzs!wgpO]]VcPbIWUjXQ Ü `s<0` 0` 0` 0` 0` 0` T*UT V3J*TRJ*TRJ*TRJ*TRJ*TRJ*TRIVyB켟 J9zׯ^zׯ^zׯ^zׯ^zׯ^zׯ^zS5@[VgL,6,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,nBH2% V߉2!3` 0` 0` 0` 0` 0` 0`X V wFPL.fbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xbŋ,X`r,h eϟ>|ϟ>|ϟ>|ϟ>|ϟ>|ϟ>|Q%lIKtӛ|%ǏHWA$ $G̵t]QC$q|Տ$"(@FV4jf+R܇A\u' /(9!|p6&%RBtaC3<FӸB"`JǁBE1Z2(]U)+@?P]UMEvY6Q ϥ YYd^:YK@@JTtz !nD@ `& p Y`'H( [S_@ؙhY5 zXg?jXb]mli=u^mg h)1Mbv5H{|LdB1fJ&6naG$n6oD*T\ͰqYŘ=DwZ*̵3"\FR80}fCƿz8l ;L4%n+;I$8^"s h0\VC:FHKȚsb[@&L8g0< 0A0La(EI[#Ȧ?91%dY0T߾_bvFֲaiTQav @IHd#)m,iUw2RFN8q/c\.<5<4cbLUHӁ"`DCdA ot68#BM_I0jOIL .#q!l4dD&@BV@J|)jmW0 `4ll3&W99|fӁ6 w"46% x/BF-|[I"4lL]3[A0Fm@\V< 81~ .q`0w3;: .*|Yi.kl6EtF)c!8`҈>b zw'o ?*%e_51rm)v(, 1.Uoof!Nrr& J3a H ۀ]f~L~hpw0@98(eVhh^ y2-2nJmߴVL1AD۵T=h@$/L("8,v,VkY3ńwKy>(I XE7Z 51[40ed1Hq{əSSyAp(!hdt|*.FxY4LDKEA(^ }qzUYU^, 0G N80}Z? |οC>8?@|N3I!zpES ^g!9@^"b'eXųDT w OdAS˂.O.Ű #`偓/.{0=jI GsV8[uM[6a枻yDk@4eMdm)+0K* N/y/[^rMFHeJUj0͌)>?c) Pw'oCD?]+= fe Vu;p:oE"V E`IF0 f_S@;'?q96pexySϧ`J!22'a^v)g8" [i({ϓʼ!t#R Ddx A,bãaBV"FȘ ,8Ave?ùw' za]wۀ@2Dv/$"%pjT6 $bg*` qLGٝۃ!1tB~O3U"K^Ag7&ƘD]wRUlOVˉ%uUU^ 903ܰ'ǀoZ;5 qy -ՉabY Sf@fZC6ˊ'ᯙY- 82c3o+`x&{v߷ȇ3KOۖ_'Mw! l.ȡv[uUt`Jy5>p9qzb^8 ē4ӀaMi[Z)ۥnoہڛy03ܰwx1x?|9b/`I{/^b4u8Qt "d{x.Ɵl4x'_ЂnI Vk#[" .@Puq B}ߓ Y=@\M xz%'?}- 8:ocJt `< P*gId^'>O3M?4\rF;k4 5 cw/B]ra+>g`JgE. T~"d"=@mY_f|#N/͕b0jb(iu S@ؖ\U[bҷvSS|g 2@E8?H rhJϙX,׀+/g 2q_Jh#Q]VF_7%IW u}|cJjG,gP >VE.C$W&LƎN%g,F8H;]Bhu`á#;I eLeI0-y. 8.oc,Q<(ڛ *պ%" obb~tIS/ OS:#bZL6r,.e)LIP&efĬ+`JWq!ZIfi pH2=?˟f|#N/u;z01RP˜y NaRo8-Hm|gb*pK/+Ĭ73͆$rH4c9h=%i)x9ٯ_5=OGy~:).2 Hqj) Y=J DГq9 Y)l<z05Uys/`I{?|,%O0) zi3,Յ"4l%*)EBV/2 7$ !<fl!DI R F46 z-y*UѥURJ7P|HH,w77>B8htPZİv 6Tɐ% Cyx 8I*,l٦$ٙHpbf-޳f͛6lٳf͘R_-,֝V?'ĬN/33X<^g?'gy8~O?|%cqy~J9?8sq+瓋V?'ĬN/33X<^g?'gy8~O?|%cqy~J9?8s}` p;ޭi ZYs&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&E6OF*H߿~߿~߿~߿~߿~߿~8Id \)EDurdɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2dɓ&L2d0H@+xLYlv۷nݻv۷nݻv۷nݻv۷nݻv۷nݻv۷nݻvEw> AZk{ٮ]fw{5k{ٮ]fw{5k{ٮ]fw{5k{ٮ]fw{5k{ٮ]fw{5k{ٮ]fw{5k&ٕ͂yXEn{)SsئMb7=n{)SsئMb7=n{)SsئMb7=n{)SsئMb7=n{)SsئMb7=n{)SsئMb7=n{)3ȉs`Fҷo4i٦Mf7o4i٦Mf7o4i٦Mf7o4i٦Mf7o4i٦Mf7o4i٦Mf7o4rDfZkۦMn7otۦMn7otۦMn7otۦMn7otۦMn7otۦMn7otۦMs"?+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7+V\~s7' \'Ъ{XP4ßףG8F}z7JYt]e)K#P>."(uw]]QISPz1'uw]]TKF൧h 1͛6lٳf͏1koVYk?N1{Ƒ1I=FHHYk<| ϥk\M"LeQ<_VDlpǮ q\P ŒcHKcT(|O 99,ZzBXcjlBзT¦`4|}j g2`*LSk ߏKZYA`]1Qq04P6Q,rru$2O?U*+Snba,-C4@@w/bh ҠAl4rfă$7PH , ְbzBr 5n os~@12oVXu8 `2@85ߘN7(@pD_idWc|Pp_ٓ!y|ylǻ kc zr.` @!gh[ 5(-qߊ 0*{Bψ6 ڔpdRuYbً?UG~V/l\ rb˾i_@8VGv-1Yp [f`,H)#j$/%%IQV(ìs`˓ʎ:.[/0<#R*~m9 YB'Ļh~J@|& \~w@7"1xfˊ74Uꕖ5|T(\UeUW,u$QTJм RwԾG@U(d "Àr%SaPjwDYtUz 3~yQ.*QBfʘZ2q^g|7"U m+lVYe%@HtQ44b85_ ;Xb[PW8['āf *a,P B*۪ѠG @ Bb{?~dRlDxFΜ.%պ`- |9'dlFg;X6gqa:1F%D*~zl^G[ GeL\q7 <LF̮XE\J(h*! cǹ!҅.2DOrrKm> q'%ئevQ@Ӊ i JfOsH&qfݡl7h I[?+Z{Y8sc #̌ߗg).G{."\)hg@K̒H:@(!"71w|̀R7ŝ-lѥ%p(.)% o|LF-Q"3b =cq-[;--sK ׂ|[%(,[g#z;nslX={bel$ xW.^0. g35m,&.qE% )$JDAYA6LWn!S^x-p11.%|Y1,ZHݴV#KJbZd8i f4>hwoϥ&u0%|3zA8R>jG KKZ8 iCPX2/@})"To4;}P u Հ">j(nS¹Mm= "BU[ۿGpdR1c pl sHP%g &;^l˧u1[;{d1Z ĩ #lXбnشDŽs Hfŝ i)^Ln/ &ЈO.izb4 4ڲ7q^ٿ;;;"u:sǘ.c6;1` `N?UJ6{diZ*F_E_#5 T saYD觢 Fȕ8F8h6q~G>V)wj[di LD{$@e-r #@%V+@UEqm`0b"AY˺b4吏VO1H ? $!+l71 *|)&D>` f"A@n1X5V19G:^, C*#7PM% [-fH.CVD|ؘ8Gv Vtq͌X,vtm#@N<` V0,XDDځd^ƀ76ebf!|)?N Y ۅʑKx5~4\qB7ɦk)\||SLu&٨Ń k%"6D52P{A (dHfRh0!Ë*Un(@  L) Y9LFV{kXǚ,Eײ)PtI. <FM2ş ׽koI '3dձ`ؽYYk.8`D\ tApXsM~>~#bGxJP#Е$ j$<)FV < #yҦU)X 7K먆"1|b b X[]WHcFjL,چ@8zIMqi_pHDƌLJ6T̎CXt^d;ϑt=m11(5Y@\&3\zyjG0h U%}JW ?USm+5WvRSφʯ~jC~#bGzDj!p &MD}9jG0h @J6'z)q%Ίxs%ˀK3+ރ||S*nKd*trnSLHž`H&53+'VD}P,+"D$H1IDKL$XNO"Dy:h - 6m5pK CC Y>IiBk kyG@%5cqODZ[6`+n$Rc˴ dF`] vج \A.yo>G>V)pڂaFO:{Sn}=w! Nə|7(v3ɬ 1gy9^8ҮC }jGm#@N vBfi fm,ybj7$Ty} dJzW$A0ẹW$ @p^iupL?U[m(WVo$K`f ĥ(`IchC ]4h܅PY< Vd.dB }G:wdbXV[қ.Bth $2Iq~.ՀQ ޵귋m(jykLX({r.]F d6"~#bG`׌%/&J0ݽ1BwZ 3ȖW/Bh & ,uX $m} mAy"%1f[koIy-ny"29rt: @]Zci/i|T!2 Te[{? @hHo0`ğ$Hi-n1%P#P\0@bwh"ɥ(eHB4 £ n^H ~5C ?+ֹsd連2%Jo!@9H1SL>¹h]r(C ϟu4`Ba hX<D/f=xٷsba:kQ)mm F\iO_(DuY`+(T鄯֢}%`*wl(*?UK[C D/6lۼ!K*f={L"\G5ԖAvmGcdzRP|g7Ѵs>C9΍ungյW}Ϧtmϥks>k}6oh}+]|ۙmU_o3sG3Z>ϫjyM9J_!}[U|mFV3ګgl:6gҵ}V_5>g7Ѵs>C9΍ungյW}Ϧtmϥks>k}6oh}+]|ۙmU_o3sG3Z>ϫjyM9J_!Y"'z5MNy|V_5GBS tEUGLD|MҌP, /(K/`'N oDM{3 uB2L_QOНA,L寄ѴxӝāU` eXdjdň,ZCm# HU[׽ǏuStUJxd (BbbXկUʿW*5jY̕w#u;E@{U6>.}WRP+N}K&{G1gL`( ϴI4/%koVNJv3 a0Jv_50@Um6\_-%,ӇP"#%1Ҏd/1 * a>8LV!3{ޛg{+s`N #I ^9xBʺB p yI&ʃD "6Dq[X˿iyx8JA`Z."6d;]sU&lDdR(HD@DEV!`.9!>tm#b]Nd2uc_`l^0@Mό0l> +턗4+]|ۼ8h/!V-Ávh~Pl<C[=bzHATn^|*B|I+j{Hg8!5ηStTUU^.,d`e13u>ARvJ rJK&R!%jgwq`Y.g[cK)[B62$"B DdJh?(a1I$ ZBViWKfXVʕ8&O]ۛHxFؽC7"Q@p[t'z!;˜\VQ~NpJI+-%,J4U%?Ǚ=2lR[#)Ű2zVySj2 -iШ9 R2fZ{"OIEfsMǴρ #glmGBh"Y!N֞DWhVȒ@Py z6@v@.JD<e8J_0*/W 1ezY>x n4}ITb*4'_^2F,>?N7T!P%hp(Rry@ ٕ[!2a*n{ ϜKtm3@.5&N(lp3K79Q[+UFMcIvda9Y+]|۽Pqƭ;M,%$N P"AtL$(09Iu^0% sR \2XbBb - mݞ3V_5d9s)9WH˴>VEx:]>KYw!pG| Yǟyl xav8սU"T]O Ft/ 1}w΍Z "! N5dv/aDlMVHSN}ҵ}ײI6O' ʫ_t"i)U-!̉< HL 5OqD= #wr= >^j{@"\G-R BLX0tw>f]O'hfk<$(Ēr"C0a"eyOZY'IkEkqj$)Gh=d  `@&b 9SN\tuo3"hR*!a,BJ_44/ i A@Y,HYġBTU{kN]ςDd@P`Pd2(bU,P`k4LMA>xCfx5Ta%ԋP~[ 5%$ Ihy3p Y'gB;:;΍x0#]|¬tu3.kx)x.ܒR+a;@l+QdK#A$R@y[D@d}յW})6O/$4K#`e/Jc1jc̴TYUeERr.*{*Ib6orYR `(4 ;έknĬd3CbaECHDFGdv:v$wMyRS͸x,0@;]|nWUmSQe8-5FǼ@f  G@[cМ|J_!ZSsd1 ֎RGYSY 2(fРeU2TXPVFP\ȉC8YF8V_5@I?,BRW#23QaX@he-R&ôqlHxY}8w6i`-5 ZPmYe `6j$3BӇPh> 4|"|y=΍xMl%z#<=J` Za"tuo4sȼDT=ǵDh x d w[U|] \D͉ +J`t=%|r,0D,1,߅t-l"6(i6rAnk26kP5lX˽w bJEU`P-Xȅ%ETXra4XFB *!Ck5oo.%mÐ$@#/ L-};A!P?1 X'|Eč1jD,OA *umU_oæ} c{ d2VhŸ3eH.-a6tZԇnh|3LG#s+3JtOJ7CFBu2 HgJ J\Wt;ɒ,((( ~C͏.n IXiEeM-Y+bT}DHDw1LA !*ힳz:F[.Fa2DŖ_:6gҵ}%V_5\Y6Du:6gҵ}V_5>g7Ѵs>C9΍ungյW}Ϧtmϥks>k}6oh}+]|ۙmU_o3sG3Z>ϫjyM9J_!}[U|mFV3ګgl:6gҵ}V_5>g7Ѵs>C9΍ungյW}Ϧtmϥks>k}6oh}+]|ۙmU_o3sG3Z>ϫjyM VH#Z꿧꿧꿧꿧꿧꿧꿧꿧꿧꿧꿧꿧꿧 ( 2rkW_]uUW_]uUW_]uUW_]uUW_]uUW_]uUW_,E M xf~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkh4AiAI 0FT*upappl-1.4.9/testsuite/portrait-gray.png000066400000000000000000001353161476704353100202270ustar00rootroot00000000000000PNG  IHDR+YgAMA a cHRMz&u0`:pQ<bKGD̿ pHYs.#.#x?vtIME /8vorNTϢwIDATxeUtwwH(-!"v>؁(X J(4( $Ι{|?ϋw=s䙀|gҺ,JݟS&:|rк7I`h$*pb EE(QD DՂ/tsaIM8%Q Kw~k@-,iˣ$jbIeQ +~7ZXR’#tD(EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD(E@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE!) ]05̲9z<=#3###[E( ()7mڴdΕRr)yl޲IW6/Tvq D/.8I.Xi>VBm׾}I*e| mZitOsN$D:u.F,hl(Zi5Y3Ζ:6ij@-ZrJUf QW*bޖ4hL_ܗw6̜Fu?j~{0fЪs{}~XwBLwЧqZe%_Q+Hnn/_t[@?O?6ܼwB*IaQt2pShʧԒ%#*ZŽqu_ѢF$l{g|{i[ʥz90;!6"Gny8]wf+(. oy߽{4 < jcwwg[;O!5kX_\A̶S} D6_4 &h˳7:d[ M*kӶE im>IGs[.Z1x;} {h>S胎z,VjסQPͬTwfQXӬ㸏(J!.2ہ#34\8zҡYdy{#"+rNm~Lz?(tϱoϤxg>h~|9MbZoݴjz>^5Eo_w/ɎxGN3~+Eb-3c9n}#k38s;^rɒ8IC<|'{^vv~OqǷvXg_ׯ﬷~f(l _L٥o'Scu_3Hw'ol/yUO|@jn]|Ky )Z_ ]?1%xnWlEg{?i"xݧMGOCyrts?[-[ZZ+]z/-^xWp̔^=.j~kgEmgVZGj`Y,PTf+Tw[:5[Cn֬A7mwځE.{㟖b(}4㲋=-kDqN޽l,x 79#%N\f&5Ãw9τ|YDQ|UMGٶeW\H{DѸr|D+ !rt/k)^"SLODàu"=ty-L'B߫W%V)LF韱& & nW^s&:.HtZXWULϡJ$LWvǴpӚ݇ڍ>7K";":Z`:_K}YM{sI啥B:Z -&EF'{8Wؔ(BD)?0OӞ<lr1+ u%DE, C&ja.lEU_~rSlI6s %2){X[R!9Ӕ{Ef0=WOE(uw"%=iJ"SÄw;%{ENg3S)?=4(O#>-oݷcx=D-Q\ jTH/sׂgHtD:Ӕ귝N,gt {EAGjd]܌(c랦~a%L7=F!"x+['F&y*Mt@{MCwY@o(x@S+% z1ڦ95ZŀTI'߭4ꈋdTV0"ۙ]Ҡ52C7mܤ˔I'4%Ћ;yN{/6q;"!iPwt钟eKuZ+FfztGtga<"q] qf.ݭaթNƬ4(lsC)R/y@vFFFFfFƩORA)UN|q;Pnx;,+K )Dt~ÿ\"A=&KGs^n `^&"i4"YQi$n>iJkG< U;gzY)9.%],U﷣iҐfEJeIvyR!(bfECTj=ܚ"h7'~E,hd-c]=1`nm|r"o7nLFA_oy|PaG!`e->a TAg'xU,qۨi&Os;e4ܙ.BYժ~Ji(a JSӚN|gƞxnD zygoPvkȥ 㤗c"@[778~8UWʧ aI/"m=:AަB&^N4MwtI "16P1~4'<&zgRFM܌NfB ?'"0 |0n=G-;+333#333x}Za 12FǂNA8t[x|'ʴiRs)QC|wȄLEB5wQJϪ"@KߩxWR(KjRu~JV:(6qu]ݴW≬!S( =}TgY#={U|NF%Oh&[=Nz&(44NiS(iV?mR>ZI{D6}<"&wPVɧAFoP(dnľREٌ DMkK,׋6'Q'㤧]v]"WA_'Qfʲn_7I$obŷ-{Ctn5k؟P( {c:Y?"*=u_fbpzskM,^H|j@ 'Qu).-kqhUvJ@fIT &R%E7gJԛ[BY^Yu D,$j13BY_("X_3m)BA YD,hM67NPD@A'KI1&BCIDgYTiGge 2S(h >$zad]ܓT D,ee6è} FIANpVYYoydȯJH `!kn8#uD"ɺdM4NrlQ6iY"?צN2O"<*-m!yQĠ `KoWC!&SdT D,bkwE甡Nv3S> QqY&3R'I}YަeQK혬IX?#6u4"XқONNSayTD,`Wò&7NFhp81"Gިw0% hbwC&w@LqzYӷKE kUcv<"hao&LMbpGFDf("rٮn[=(u/kTK))5*q+"@}&53+u\J ~yQGfsI?g2# %KץCu}_.Smo* &;}7Ek_Qnj!$>t=m@UA\G6f5֭ŵ yؾmm7=LEA\GvB+W(:+-5=5^m@dS[9y)mE \iKjFREL@sj=N @0Sς("& EQL G"f~?F[ ()"&#Ev8 k5fD qZTZT1EQ< J@PgyY9|D4UQ ;erz+<"Do4hԩ;Q7ezh|\5?4)+/[Ӊ:]:W Wۊ۷k-[ŋB6nҸ(ųc)|vJxf"{ݓ*i[rQ4kj"TB{MJKKKKKKOKK"4$,44pbb‰*S*EUpK33@0G`CE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((E"QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD(r&GDaaIsx#yO<P ȚNg~`Tj07SQL FQ 5Ee(S_GѺÒ>}b-jaEK’V_@ U%m?uy}XRc Šn:~?A-,is_AjaI,B0tD(EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD(E@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE!),!7Km夥gDFFE&N=vر̌!  /PXE"iCiiiXBIgڲQm9qE 7͛w={&_N /[3*8{׮]>|a+8!lEhabmټyYUM3mJUjʭ =!iua54 ! E{i{GkUp@Ͷ lfMT6"C5մ-FU,7כΛWmx(vS@e%Wf&"xpr/)TPiW|{atuy9|Amj9TP }q "\<|Cig)Vނmvz 2Oq|ΖҿK~>ؑ("🅟p/4%cۂ"}$-+)_htEglgP4;d(yMLհc8 xaMFQD6Q NԸc"f=|"^8I].OE6-n&v~("\췷)t4+(roSED֒W(tZi~ȴIlEilFDw6 mRDlDTGz&tD=d=3\):jv U)zp mME6jJb=ҫZE.G y՟DQ> ~J(vvALOJe*ڴR (]__.a"hhW7Wt>V%{=wpWN عYsSvV!"w}Iׯp;bE!Dn~X!mhDdoVC`k"-%)N VC]vTHMSsFI.F)٘ZA/u(y.[!{Elen:DR,cM?wT#Zdz=P>VWE EDZjY:TvVNk)?ADyzwO'BmPJY(ï6 #?''NG%,8#v(Q| -hɱ A!9!+oOid;(Fl.%NQqˎ4Tn%r=csmdEM4ke Il+Ht}0*tɕjQ"HZjH;"DQͦ$~]Ȧ,f_@~1A=ءv9@ǩ"I"ۚ< `|kJ(ũ*H(Tw>N7]CQ渶r[`Z89_qr]Q~$uHJkyX*QDA!~R|{(.ⶭLɝm Q#](-GA~2Qd(*N}'gt.Z[٠=EAm/}ʮ1{͖(yBb m \9V]sx4mC9-D2O0*Rߥ&YM/V3|~DE"AqЮ={)^h bMGN(=uǦ' T*{;F*'yϷ  '7bsEoT_.4jT8҉6kOަM^a+5gv Xt}EӎrH)HcIDʕ"ε=`CF'n-ZV}Oh6[U&)LKwynd:*Z;ԵK.ZӧwM !N~S|+x|;֪1oi\*O/v 5Z MwQMTyeEw Jk_%s" k]_ g)9_0I(߼v{R(Oi/ͮi8fOqGѰLN2Bq޵>{쾵uT,3",]mwo8IN3&/AQN_GM&Kr}OH.v;@'?ė^JW^׽" _Υƚ!Yl*t%Z9\|H!-}H Ʈmcmkmq]|HY>TG6L5*S#-^$Gb(mÃ-nGсeȵWvLcK|fvȶu=&_0)@HifHoK[Mv(D%}5/i+bT젾-栅lk;{<ɍ Aݩ^v|n7fCo%jn;fMߥțeskJn1Im+@ըsEG>Rܿjt_cCN"6k9_ݧnU26Vdvyoֻ-ψ"][$nQG][%Pj=1r'y #XFMmrQ|!A(꤮ ɍC䝢ĖH'?{nB+Tj &5p~}MN2E+쨚dz2׮% "JEB ~9J1E1"H=%SK]Ot::x{UŮB[ (*&cH(m;jc-1Ikd7E?{Jg0&(6EEvTYy:犋dzS}:J6+mPWDQ[H7oRJ4(CqFr.ӫ lF$|&)mLꞢ+2\5\ުE+JXRbNQ$dCyE>{f\l/ݐ"Dr| OJZ!AK)G=qNO OIHqH9fTGG%7-OQ$<%gNT$"Z'_vTMʓz,xI`ZED_A(FI ?#0Z}׳W8hkunWEIe=])HCt4U3t<j/C\ "l@6~Q;u GM%̲EE(N+Jm?ŕY}8Qd"ݢhR"Q̺vꎺh"EDHW3ˡ%UjP$RZ_}G7C!]wU${Eyj;ʋz![FG~:^t! $^5gs<]XaQJ3$ ZQ$(J:DF,*-z)i-"FjXon,Vg"VnzʓSٍl|H'JvH&E{Sh4QduEvF -:Y ;t."WUWD-L/ ʒ fFr SE:ɝ.kE EQW]hQ$ 8UWHrϼt5lۣ<òr,gix;vC5 "9B]Fը>"].WHRZ(2zٵOcO^@vl4(٘"E›G)#L{E~,1cy%΃XF.ǩU^{Ez/'4wE~"rB#ZzػB #E23!ub#}d/Itf?dٿ'[~J8k}H/oAt,TwVyh8H^ ^!yqI}Iy(?fт*]`/! jwr%{E8uJT':M5*-ɠ?"EL8$͸(ھPe?$E!_5SPqa>;E~k&2>K Yjr pjDv6|rSWnSU4#Idꗞnx_[Rc=̓Opk)*zI~M(Zfs/"ݼFMYK2CHy6ziNe&ߠN]vO~ÿ'kXիU-_t kJ w-k*|XzX|\ 5E]Iݯ< \>nIu,_[>$sJ!"V^|?sǶ Rv-+n#Uxnm/=8eׇUtƹ.ctn.՞*kg];ϛ ݜdUXikZpLB1bbCRSSSwnۛM7C 2h 86n"؊k-܃5B8b`1 XrKmOGL(Igg.hϪX9oH٧SݏSԖ4UhkEڵgCq(q,6nDm'Q#ʫe-8.jiu|+U,yBvVy pyiŚSpe THF(QsM;ёAimVEa"h%t|mcZ"ؤmNR3n*;0$fޤV67HƨW[cC\Eoc5НUu8 !et[=*dd"WGQ(YRs:mқaNA7\[={`]Eoe%T52UER% q6_ŽQ2iMzlAE_ɐ8G4uqX[jd-* ЫvykA zZvu %Ūjnw`CTQ4tY ?P$c mCwuM\E㻯4?gcv,KER5G򫃄x0nI⩒);|Mz*>>2$2@CXH?d-,QC^b$Ǡo-lWTjWm7D#M??k ѝsɘ)kQU2o+'jwfvMotZoaZ5q_6Mt@CN4[`M9[+}S&ηknnf|[+M;]֢5TTuZ蔏AVCC{^`w7l>v@Æ ۔N{nLgZtAEf+1Wdxvl;~m4IGw:\kwq5 Rwj@NqScD\GPUrx+Vr* NZe$ z&}3Q`Æ\X[&P-.k1*YBX˖Ws WxJǵaŸض۶,芕*U7XY[m߱K^zu#~5$D={|V@J* E"/䉓'NBÒNP%|b%%d~`Tj07SQL F'[&GQj07TWbXҺs_OlijaIrtIjaIR.JwQKz/wΜ7Q Kz/كZX/ۄ 0Q DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ D%E@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((.i(;/44'Nfeeef億-R  YYYiD>u3YYYYBGFDDDF*[2oqZHъYK/uժvGEZڳ{K~_Aʖ)[+=$8lV3IھmG~aUUK`Y(I:n]}g4GXR%{8~Ym۬\EWo<9w>!"61F"gݲ]&6R-qO;M> !w tl &*w]5^scI̪({B_.=Xaw|}÷qBP.i[{w{g-42v[<ǫgm೤o5Ï y?{7rlzup )zTќqE˾ڎcq)`<^e^@EhS.rF!Wq{""ӎ}'~v?-5hӪnjMq$$?4SעGFp~{Syǔn]@h6\>76֫Bh[_ }T6"os@^&>BKh?DioԴ;nx}gRzZ?:U;;פ7rUfk?+q!W$汚He~7ۀRffO]*T|-n(JGgps9=.;0fk?w8SQt }NVe>8jlk?- ʝE]4[`q:;C7ӎ(‰?7V_e1m:ݷ K.\{-y99ʭ-g9ųo3#]483[ YBMߦ0v{ /GFQ3y(k13:rĨ3OVu?8|O]oe(R  "/[U^YЙU`~4hNjUc9窹(&~tAa.2(fTD?u89#=+8"2A}J;jXlE)M~}  oyz5Uۆ1 mQ:Zח;[9{|C]'/vm4[ Θ N~{7<{G.X+BCh4("5bΝfϒKۛjosѷ_:ʇ$Q֧fk?u)d޸'Vh0HE K ^k t(Ċs#ߜ0n+m1 *{/O!E ת['.EŒ7lLGE/eQz-kEWZ;1˸3V#qgI=](+E<6+޹/*i-C(mQO;6s[vC e)0rve B)mH^!әg;rlm'KcgCBfWzY !V_ͬB !UݦXF{{ '-wUTl`'~J>j ?Qx=_&(:odz!ۻ%>Ru A۞BÃx5d=%٩vْߴEäO4oݖ SD'wU& jgcSrv+O Aު~]sͪ 5WKƦ !N~D:''+d<_@U]񹽒*J:(R7?4oݤO UfѭPǿ?Vʓ{4UAH QsOBhy|NvHzFxcј.B?&~Qs\l Ǚ_{"ٵ&f(ʓUMrvY&7Bӽ*eY~.?/Bnfk?G& 5/] Ȯ#9IDT=tjW$9=\~욥=Y@ILZ#3inPߞRkLsd"v!(8R%!T=$W-9|imzdIk~QX/d剢s$Uޒʷ,)aI;@'{$m:h MU4;1`gvWzױXPvgţHrN-AǬ<}7A$Tt惉^Q$:8I/gyuB1[IWta'-Y(Y6&ţHJʓ !Jxv@+*^Љ=m/$.2[9Bu5 %tވ(\uG"5!^(EQd>dquQ hs%Μ%W~%e"ɝ{' {#diWOP^b@cӋ$2:={EB,(^5'X+s>+ַ!V7"n{W8XFۧŪO(\:6G3!=CNOdr;($z7936ü7h( _aCv^z{E*!|KyOmEHQȗ(s[y/mܼ?nR+LjpHvG#i宕-2i\ K'kb]ũ^?UJLr5} {`wKh, gFѾ)[Uj^-ۢ Q_SGKMy$ k2k >(o"UCφkl-(0U\?+t4/ oFgr\Z ="uɚ;z]vP\8=F)3Y6(O!6;wlT=_|4+nf(rޝ蔏b(:Z`2J+urW0_dk(SYŸk,y;ŌpCm{w"tNKW[ :ߘaEw=Mt7DƉ"kuչ &,xkqA(*@Y--YVB _[4={WzV+*r Qd];-wzTz+^#2iS Wda%$,+hp6UF1ȺC ,,5JVJ F~j07(s 5EQ`sG7G$R +:t~S K:wb%ͼ<]KM,'V4=7{ƹE-,iq!LG"QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@"QD D((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ "ņԴԴL5;$";(2OR E]5!75-}pŊ/Z42,<4<,,D}6I%΋qҞw_rR%lL-E #4?R":f`܊w(vAI^[;ޏGY潴FJ52kGje!/yAxBer~b+rz1uL~خZ@4'O{vjvyQT|DqCcu遝8n(*p) ;J6)Q2Ѿ=zѴ̌̌ȨȨز9gZǎ߫0{Φ_BKW$m"5aHk pk6lE>hGwcRfؼ-m^۶o?uΜ("5S7nLG}X$O ͌_>Cn3vϪ޶?f#'--u QqG6zN+BLMRX@T٧J9;(;~D6\`Ս3pcgaef-'̝yd`CpK7v|4 m0|/5Q~E3>z5,k޼T5'h4yeM{da]Z[o4x1D7g-ϳaN~9e3<"p%}܃3*_ҊpHQճ;VKD?YE^3M&dXnFGQPϩz͔N_td/ͪSI>x^Vr/J <<"H༊Jc4>tT*&} TA2l;$ R~*B-S-:@j:í;+ݽN ("5:=jL\#)Z-gXQUY?@<=5;5QtkU~l\K7fƋ@$U{5+OOKtnl!tTrkHݠs6rzNãMr[˧ \=gjL4[X,k=5q? a=4%JkjИ:, >^+#ۤ~EoM/,EʓO8hM?ZF6tպÄ#@$B(ߐ/7h|j+i]gaHd^"E+a>'Je~Γ<2EuY+ReIUV>Qt#OF,;jUVqr򫫌]@0cuZ[yIj}lcR<>3>35#z- c)9dZQd"cHU3>P5QyҊ9F/-dEctak59pM*҅4|79{E^´(J"~.[>\- rEzY\q2C1)s*sv C΍ڽ.]R ;\Z>W]0+T!N3|\v3N蟯929Qi-\~vx (aMˣH{x輲˖Gc\>Vt) [QWϾ?U WԸ w+_G_asS\EbKKj@K/]8t_z@J(4dUYj-2adFto[$R_ǮJS_{G&|g:x|Bܞ žxqo꿀8W䥯4]7!5+RS; qR|r.ƦIJJJ:z;(kOc(?D.ʴ&1߄L9/7w)y_Ӿ Rw(dLxxXXxxxpYn]>/~?~ 읕W!f/?Q\!ĉ+V3N̤D"UyKW IS^!biuVDr^H}H!D8YKW{V-[tqWOJ޷avƐ̧B7x08غomW'v钻erSG23wwy{EWTnGJ?{8@w)ߙ=^$\W$ G_mx.JB n 2߰mqQ3;^~;"X\Zmm사mzK@;H8WU{o ŔTb ѹ7-, tի'2,hxVSNiux|h^wEezZL+*TZP);(Y@#<{ͼv3h񻇰zn1+M- X>e_j;l|&=Ԥ(_hҗ'pUhxC_5;`K.ݧ"a (FN8k-%i!WtqmP/VNgFCQvI񠐐АШ… RwWPTFOSF2yӎt4\>Quzs'xHԡ?W'Pܩvi[(˅v~C>KY:Q$?!VE(=_%6;fB"(rVZOe4t&i<2Ys2/bx}31Q.v80)NibE֐d)`<=1S>zp)qH"߸1"%!m[>pJm=NW$yӯzFj(2egvYF1tqTz]ƣxDj0wgNyrb1@^=7k(*lQU 9u99h1Ǒ;EBll57wXsJJJ+z$&),ȧj$ϙ.yz4L|(QQtjN_:\SA:}q(jTKFNm'/7u燢5m-lc͚ѕiⅡ=EU/S 44̗3)`4cS"#"""JzDk@mw<2^OYXG~CqmP8δ 9rʕ+W7)m"(+wD,YF㒈" ]G'Eo8i:vPgH!8~WKݴItt J+WӤgk%}}Dս}4E_H=-屔vb݆f^E*;m;whs=O~6Eְ4.=NfuMzOEG*YF""c>h0[৒7yl%屯) UӰ5O2xf{JbȹEц 1 &>>>>D)oFO~Myl;>b/.jd^'K5YrЪH:!gB+TT;VϝtY㤯u~TE5 |bLUuU| W Iچ|j&<6U-[Z qVϯՈ"d/{j~L{R+-qҷt! I(vTU?KO)O/dȧ!<4jVMKR)_U㫖Pg\XWP>Or)phQd_wQ߽(CEEhdz(l$y7Q*)Jn;+IZH:E 3k(R}&"_ <_BͲ\EEvCypЙ.gIMEKHր(Ǔ]'r(RE:}B 2%v~9@+ɏYCIFf|-maW$?^{J""-Q"%E:9<ًj)DIOP$3@''Dr!E~nE?kP&%Q~$&7SHB:]45<=(A((7+0#|&n!QuGQDIFdkEzEQ EEߦcP"B(+jt6 R)KvhEDE oE(v)?a2~B$ ED`oa{Q#S\Ge7$77E~nqPP7"ݬU|n*O', 8Qdz)jWժ*ʓOgY"._V>U|w;$T׍@!"')IiCT"?W~m wE %v*,k@Cr.NdEk(i(<֚(**;EGކ(<J[EعKyz}>ZJEuWMmp໛g;F1[2CSY!$ vEiC6YT ]K/Be9í% 588E_bHy>ўvQj׃}{iZ"?WeşU//dQ׎VgEP166⋟zy;?`cו}ADV-Ԑepf#Q-.\8qENPl#+/;[-{tJJԱ˽\dȓHEqlO!jtkz.E'RH[ժ سz!u!:VU VGfnٹsCCu?)[i=!zD88ZIDAT_^NhVA#M |{8sȺkzuVJXzBٹs6BU"Jm_ux亙 /;|#?y3.[l!*}pgS8Xx强WVPd͚BdKJINMNIII .[WϔJӓoSѪvDBmڲG"=|y!MMKKMK (uG[w"B+Q o(YxN"Y͖ .^A~09@ iS401ѫWkا`8T?J -hc^GG!"?tj(KjwuzDN MaLnͬKc D϶͠fAK_r`QΎɧo2 JӾӍDGٯrɏ~G3P wWSm͛q$l`4Ʒ1DOD࣯zj͜`'|uE|4GOjE+5Ez>E|w@OӪ"w?]NWeA,^0E:8co~>Jo3rR= _։"fE|sr qmΦ*^ה7Ny!yBv:!*n߈zI88Ve4a~79 4oPP#d>6ifmGQڵњtvтdp5kl?y즚FY>.g8N9]w847w]G©fs -1M|ώ?Wtr֬򍫔ck J4V%|}y?fPEeOyc/^2󧣦c7\gTj9N[_lZucK7mZ-Wl]W4Cwhn/j￙`(ځMDp*U*yݵsYF, metہbWX1V+v[+} Z>_&ZFvV:sxr@B"E)" ,#Gs&?"L+Q+~Dcw|ބ*V(&?Jݷw]ָEj Rj=s߲y/xܮ{E~m'd@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((E\.s ~R +8|Y>]@C%e !߹rөePk/Lj`e$(O FQ25E1`ns(LubhaII[ /KJ"k"{EQtEaIxIjaErh#y@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@"J DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ DD((EE@@""QQ0]0%MDDf&''gP k L21111111)))))GO0* GEGEG$$r (Xvؘ NNINN>qî|cUJ.UXdDDxK>{ٳߚCiZuj׮rOoݶmMzͶVUϩ[lkU(I .ܰzԍ?zV3]vbW%$Gڦ䑧oqCZmoРAKXem]a:H!Du .[ެze:^۱x5sZF&GE+-o8jzxao1z.6UI+-z8̢fԴK[Ӽl*mx~~Yi1Bvm!i4%fo)3 yCPU-YxWKV^Qv:pX}[y7= {id۶gfN[Ϧ 6u4nL_Qm\Ɍk9XQñotQT{ٛ+ y&]lӷWne紟d.,W껡0pH jÆr|+CW%[hN~e$,x](pyM_cٜk%޼ˋnr]#%_~%_V/E7Bonn peoHu1F}* ; BM4ұE[eK7Ǭx83a RT/x>֗UrM9bk.4~B+N#EQsOake> ?o?T^@aJ {e|%__[on9JWEͿmMh7.*G]X_ʊW+NogTr{~kZ m%_ {qWN:EB!ů5VWޯE/=lv}{;4A%jQ5ͽ~ͨOe9#"!Ā,o cY\FE7/8{~>QT|l7~䏽~vV-Ro⽻/꺦Ez7DOj[7f|jM=j㽢 ׎vEA)_ڪniMf9Y$}ǯ=qGl ۴ϝy$44|bq-kh5*s8SDOwG꺀*y=]uMw'꺀nxJ޺|,jnFOj 8g(Vzb?־gg7z_ng}~q}:nfc53 (*͵VnRggX`qkwP-=zmBJ6WFF(j]%|8=[σusY KշK|mÁjfÆ;a/=ccy@Tʆ?s6:PJTPR'C龀J4L{r>~?qv~ 5Qb;G| gq\ԛF=Uwp/ɘ*yU_gGQ\DNWesu]W4zY.owƷUؐ]Mzeعs\a*6dZ;8*}UYEӧ‹?T ,~KuV(lkOR2%o(jb3w9㛆,2[b=Uʕ]ĈֹIt݇Fz#?p"["%jj귮:gi$u_ *9s&%,>D3ՏnXs牪ζOzuC޹u梄ǿsA 3wט1_j=Z;6}؈ī9+{.;}nRvY ;.5}7U[ TyVϣnU3ϭoh֬/ɟRZ4GQ˭)߹wbngМ`)B:¡b?2.[T)ʟʉrxP~.Hr~^~ž䶯=i? ,u}_+'Q/~aI"S&lOd*TpnDUii]}):/Q){;ȥlzPLҳׯ/௣fEi׭ʓNȇQͬq_(?]^8O_g=aJQo-8Ŗ*\yv#aH:,SjU={yiQ;}+@uB_7rnʓSdqK6/j*b{t%8jѤƬvͫV)YO*Ž^y՞_V+V"wI#;]d[[=? 3r,oJUt]ubC'ߥuYO{M[qr0٦Zg=![8]UGA{u?%ō+QЫ6_rq5ZGa%QB*!-g?5rn8AtD T鲋s_jXN(x'H6pֿJgOS~q~ \Jq!2߫R׺j(~j}{JY*ˑ)I&fpNV u?/4kUkU1.U[:j-ʓ,QItMl1GnWmL/p]h&mI[w6;f}XfQ$9cWB`4;QtKǡQ$>+hP}CVݔuș 㞛鷀K.b*]+\P~٨ UbHEEA{T>}LyzgFQA.,򣠖8@O{;+DA.,@(ʝ<=UO[e܃<ɉ Kwۮ`-(k'Yj [IovUsV]gFHys,_=|6^DS_\yfɺ. H~o(b/ɉ W.vS$tI(!F@t=!5"Ό"N%S!^ sW#/[ iwxulp_/`i7I\@|N Hiӳ-YfV "ǥ.z+ Eyɹ^'~҅꾀ޗއ{b+DK^tS.ٗ^Ld(BD QS}(u{n"\vkY`FN^+>҅E}鿀voѪ]]]{0k^Owz]趀$|HFv|]J^ڪgwtnS5kEyֈ<g'[2۹ *(/EKJ ,i0ׇ ?j޲rnsf4R5$e9/{H9VӅUi<߭_5}&b}4EMa_F5M;Xe HEv${;B}NQ9wI]ћ<_n^@ .X7>\ sj;@]3^rz{< Șt&^;E HK^A )F"W%? ]r/m^̟O8EQ}TC)TE|H6[.fGQpރ]_u(2%OcdQ_YGQ_ףU%5L>W[yzn߆e>Dܙ҂'XGUKFKF_5+^Qo]|i[!{OVkFU2J(A"EQdQN (Mn?ٶqciw+Ÿ}Exڹv\*O_t$~qb4 =Q-yn.ra+ҞJv{E$>&N;*ʨղuQ{Nqn.d-9cc -*+OOr_|ٟkN=HENfY7$4dM^8)G$+3f`&rPg5nou.Ԕti:jf(*5]<sZ3Dej7V~z65_6j*iOċopY<)REQ.o#Ȗ*4`HWiT^cv}/N]0Ѧ*~9@HHܹhuTT;o;>S|UxgT$T{E(t'4"VTj&^?/Iy0?QW={m]WMW(P"+~fQ#t%Ug{sI}:E|yӝԍ0&H" 'iS&EMԵ˛5]ZQ֥<ݟW#[$w^3=Q$gIH7uSu~5VGv_ef#?$wNїmһPٛcȘDBɞ:8EKѪV{>S]#dLOm}h__}hDBMVv'0I:YS(B's%~j~Uq¨fF#(?Wu(8,C6H/U a=ۢkflr!վQ$/7]}(SُQd% xzn +o׻]5RUuB}d_۹Q>;w<REjP'9Ȱ# ^0yUfX %={7@+^3";W6+-dI'Zd=Le~ ow{/*E;8^DiOYDWd7P3~FzyZ<}'lXFfXKtzڶSZweE}~ћˣ/IE-6$ů4y"M#Y =!(_U:/ǏnsAz(OyjGb\?| 2@-AE r4dԟKuc$0-E8f=&Hۜ~w1I+kLxKle{IB{P+loʬ~nҡ7/Za*6%TkXEqjz)%"K%iܺA&I|%y^:멳r.}DZ w`{/pt|L'ѾNm$T5Qd !7R~y"9>7k#Otqꬋcz:lBid'?iQ?\ߗeRES'GE$ xPn(zVEGTZGy'4qi vvmKYURu!Dk[%ʯ^$WZmk% iEMQaZ:IW{G[TVKU ZJN52tROq~c91&tݒ8*K)d(+2@ SgEDe WxܹW-4+}XVέ9|IN86=Ȫ9 ,/5"M 1@I#AEhjkbi2N%h!ZQkZAĄ.hyYpewGLLsf={~gE q W(?DdUswioMyǣ]Z.uPcS}*܁odgƸ&kr})P"U3G?,ҩ۬v_WHm_OjdY}ԯQhA#\UC *jLtWW_~ymoFQсKL?/]l$tumĜRBEpaץgIW|3EC]7(w \\pEzн7f*xb}k\`֠Emv΄Й-0}+'R˂cx11·3E_:{b8><kn`ɗZ4u?De}dGBEv JN׳~L~cu䯥c'{s'P#%^1^>mB!c6[r^Q}A۶ƓgɌ ŷs\ݳq™(:3=k{-,`TnK5W)%q'm\'wۢ v3O)֣Ld X`8(XbؒN;mE*meh`WD)&:`Z{}aS$oco&gE8 Gv(8q̉2.Jk綟/`Gd?1hЕ;v6uҥKϊ~8_%vcuv,m`/wK1y==S[4B}$8M^u2T)fvqGxʴ\v(&d/ T]ovl,,fO]F/b_(4-Tb4kOtM> iZmm`EBA4H'wmPD3WEUI |( mY;.)BMwղeBF(ƫwFS <(Xp@CŮQn]aSe74Bq+j^ȼy,]ӌyX{cfMGxHnvTX{\֡h\1%猬9[tϖ7'(:*8 mzg?4n ({^~GB9nͺz̥;OAW.RmN+mzC˛߰aˉd_vV~Xy^`mk֦l\]0#|QݺUp*DQWQ-\WS[SS[S[SwSC _(o߾{٥KYY\.rh۷w^!xr\AS޽k[mݶ?UocҬygx\$u}LQ+u>CQęKvԤԾ>DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDQQQQQQQQQQQQQQQQQQQQQQQQQQQQtiiTjgV5鎤:m=Qm:Ddh6 Yok2O%[;eXIfMM*V^(if,,+BM%tEXtdate:create2020-12-03T15:47:23+00:00o%tEXtdate:modify2020-12-03T15:47:23+00:002putEXtexif:ColorSpace1ItEXtexif:ExifOffset102sB) tEXtexif:PhotometricInterpretation2+tEXtexif:PixelXDimension1674?tEXtexif:PixelYDimension2091]IENDB`pappl-1.4.9/testsuite/pwg-driver.c000066400000000000000000000671671476704353100171570ustar00rootroot00000000000000// // PWG test driver for the Printer Application Framework // // Copyright © 2020-2021 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #define PWG_DRIVER 1 #include "testpappl.h" #include // For papplCopyString #include #include "label-png.h" // // Driver types... // typedef struct pwg_s { cups_raster_t *ras; // PWG raster file size_t colorants[4]; // Color usage } pwg_job_data_t; // // Local globals... // static const char * const pwg_2inch_media[] = { // Supported media sizes for 2" label printer "oe_address-label_1.25x3.5in", "oe_lg-address-label_1.4x3.5in", "oe_multipurpose-label_2x2.3125in", "custom_max_2x3600in", "custom_min_0.25x0.25in" }; static const char * const pwg_4inch_media[] = { // Supported media sizes for 4" label printer "oe_address-label_1.25x3.5in", "oe_lg-address-label_1.4x3.5in", "oe_multipurpose-label_2x2.3125in", "na_index-3x5_3x5in", "na_index-4x6_4x6in", // "na_letter_8.5x11in", "custom_max_4x3600in", "custom_min_0.25x0.25in" }; static const char * const pwg_common_media[] = { // Supported media sizes for common printer "na_index-3x5_3x5in", "na_index-4x6_4x6in", "na_number-10_4.125x9.5in", "na_5x7_5x7in", "na_letter_8.5x11in", "na_legal_8.5x14in", "iso_a6_105x148mm", "iso_dl_110x220mm", "iso_a5_148x210mm", "iso_a4_210x297mm", "custom_max_8.5x14in", "custom_min_3x5in" }; // // Local functions... // static void pwg_identify(pappl_printer_t *printer, pappl_identify_actions_t actions, const char *message); static bool pwg_print(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); static bool pwg_rendjob(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); static bool pwg_rendpage(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); static bool pwg_rstartjob(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device); static bool pwg_rstartpage(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned page); static bool pwg_rwriteline(pappl_job_t *job, pappl_pr_options_t *options, pappl_device_t *device, unsigned y, const unsigned char *line); static bool pwg_status(pappl_printer_t *printer); static const char *pwg_testpage(pappl_printer_t *printer, char *buffer, size_t bufsize); // // 'pwg_autoadd()' - Auto-add callback. // const char * // O - Driver name or `NULL` for none pwg_autoadd(const char *device_info, // I - Device information string (not used) const char *device_uri, // I - Device URI (not used) const char *device_id, // I - IEEE-1284 device ID void *data) // I - Callback data (not used) { cups_len_t num_did; // Number of device ID pairs cups_option_t *did; // Device ID pairs const char *cmd, // Command set value *ret = NULL; // Return value (void)device_info; (void)device_uri; (void)data; num_did = (cups_len_t)papplDeviceParseID(device_id, &did); if ((cmd = cupsGetOption("COMMAND SET", num_did, did)) == NULL) cmd = cupsGetOption("CMD", num_did, did); if (cmd && strstr(cmd, "PWGRaster") != NULL) ret = "pwg_common-300dpi-srgb_8"; cupsFreeOptions(num_did, did); return (ret); } // // 'pwg_callback()' - Driver callback. // bool // O - `true` on success, `false` on failure pwg_callback( pappl_system_t *system, // I - System const char *driver_name,// I - Driver name const char *device_uri, // I - Device URI const char *device_id, // I - IEEE-1284 device ID string (not used) pappl_pr_driver_data_t *driver_data,// O - Driver data ipp_t **driver_attrs, // O - Driver attributes void *data) // I - Callback data { int i; // Looping var (void)device_id; if (!driver_name || !device_uri || !driver_data || !driver_attrs) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Driver callback called without required information."); return (false); } if (!data || (strcmp((const char *)data, "testpappl") && strcmp((const char *)data, "testmainloop"))) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Driver callback called with bad data pointer."); return (false); } if (!strncmp(driver_name, "pwg_fail", 8)) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Always-fails driver specified."); return (false); } if (strstr(driver_name, "-black_1")) { driver_data->raster_types = PAPPL_PWG_RASTER_TYPE_BLACK_1 | PAPPL_PWG_RASTER_TYPE_BLACK_8 | PAPPL_PWG_RASTER_TYPE_SGRAY_8; driver_data->force_raster_type = PAPPL_PWG_RASTER_TYPE_BLACK_1; } else if (strstr(driver_name, "-sgray_8")) { driver_data->raster_types = PAPPL_PWG_RASTER_TYPE_BLACK_1 | PAPPL_PWG_RASTER_TYPE_BLACK_8 | PAPPL_PWG_RASTER_TYPE_SGRAY_8; } else if (strstr(driver_name, "-srgb_8")) { driver_data->raster_types = PAPPL_PWG_RASTER_TYPE_BLACK_1 | PAPPL_PWG_RASTER_TYPE_BLACK_8 | PAPPL_PWG_RASTER_TYPE_SGRAY_8 | PAPPL_PWG_RASTER_TYPE_SRGB_8; } else { papplLog(system, PAPPL_LOGLEVEL_ERROR, "Unsupported driver name '%s'.", driver_name); return (false); } driver_data->identify_cb = pwg_identify; driver_data->identify_default = PAPPL_IDENTIFY_ACTIONS_SOUND; driver_data->identify_supported = PAPPL_IDENTIFY_ACTIONS_DISPLAY | PAPPL_IDENTIFY_ACTIONS_SOUND; driver_data->printfile_cb = pwg_print; driver_data->rendjob_cb = pwg_rendjob; driver_data->rendpage_cb = pwg_rendpage; driver_data->rstartjob_cb = pwg_rstartjob; driver_data->rstartpage_cb = pwg_rstartpage; driver_data->rwriteline_cb = pwg_rwriteline; driver_data->status_cb = pwg_status; driver_data->testpage_cb = pwg_testpage; driver_data->format = "image/pwg-raster"; driver_data->orient_default = IPP_ORIENT_NONE; driver_data->quality_default = IPP_QUALITY_NORMAL; driver_data->num_resolution = 0; if (strstr(driver_name, "-203dpi")) { driver_data->x_resolution[driver_data->num_resolution ] = 203; driver_data->y_resolution[driver_data->num_resolution ++] = 203; driver_data->x_default = driver_data->y_default = 203; } if (strstr(driver_name, "-300dpi")) { driver_data->x_resolution[driver_data->num_resolution ] = 300; driver_data->y_resolution[driver_data->num_resolution ++] = 300; driver_data->x_default = driver_data->y_default = 300; } if (strstr(driver_name, "-600dpi")) { driver_data->x_resolution[driver_data->num_resolution ] = 600; driver_data->y_resolution[driver_data->num_resolution ++] = 600; driver_data->x_default = driver_data->y_default = 600; } if (driver_data->num_resolution == 0) { papplLog(system, PAPPL_LOGLEVEL_ERROR, "No resolution information in driver name '%s'.", driver_name); return (false); } if (strstr(driver_name, "-pdf")) driver_data->format = "application/pdf"; if (!strncmp(driver_name, "pwg_2inch-", 10)) { papplCopyString(driver_data->make_and_model, "PWG 2-inch Label Printer", sizeof(driver_data->make_and_model)); driver_data->kind = PAPPL_KIND_LABEL | PAPPL_KIND_ROLL; driver_data->ppm = 20; // 20 labels per minute driver_data->left_right = 312; // 1/16" left and right driver_data->bottom_top = 625; // 1/8" top and bottom driver_data->num_media = (int)(sizeof(pwg_2inch_media) / sizeof(pwg_2inch_media[0])); memcpy((void *)driver_data->media, pwg_2inch_media, sizeof(pwg_2inch_media)); driver_data->num_source = 1; driver_data->source[0] = "main-roll"; papplCopyString(driver_data->media_default.size_name, "oe_address-label_1.25x3.5in", sizeof(driver_data->media_default.size_name)); papplCopyString(driver_data->media_ready[0].size_name, "oe_address-label_1.25x3.5in", sizeof(driver_data->media_ready[0].size_name)); driver_data->darkness_configured = 53; driver_data->darkness_supported = 16; driver_data->speed_supported[1] = 8 * 2540; } else if (!strncmp(driver_name, "pwg_4inch-", 10)) { papplCopyString(driver_data->make_and_model, "PWG 4-inch Label Printer", sizeof(driver_data->make_and_model)); driver_data->kind = PAPPL_KIND_LABEL | PAPPL_KIND_ROLL; driver_data->ppm = 20; // 20 labels per minute driver_data->left_right = 1; // Not quite borderless left and right driver_data->bottom_top = 1; // Not quite borderless top and bottom driver_data->num_media = (int)(sizeof(pwg_4inch_media) / sizeof(pwg_4inch_media[0])); memcpy((void *)driver_data->media, pwg_4inch_media, sizeof(pwg_4inch_media)); driver_data->num_source = 1; driver_data->source[0] = "main-roll"; papplCopyString(driver_data->media_default.size_name, "na_index-4x6_4x6in", sizeof(driver_data->media_default.size_name)); papplCopyString(driver_data->media_ready[0].size_name, "na_index-4x6_4x6in", sizeof(driver_data->media_ready[0].size_name)); papplCopyString(driver_data->media_ready[1].size_name, "oe_address-label_1.25x3.5in", sizeof(driver_data->media_ready[1].size_name)); driver_data->darkness_configured = 53; driver_data->darkness_supported = 16; driver_data->speed_supported[1] = 8 * 2540; } else if (!strncmp(driver_name, "pwg_common-", 11)) { papplCopyString(driver_data->make_and_model, "PWG Office Printer", sizeof(driver_data->make_and_model)); driver_data->has_supplies = true; driver_data->kind = PAPPL_KIND_DOCUMENT | PAPPL_KIND_PHOTO | PAPPL_KIND_POSTCARD; driver_data->ppm = 5; // 5 mono pages per minute driver_data->ppm_color = 2; // 2 color pages per minute driver_data->left_right = 423; // 1/6" left and right driver_data->bottom_top = 423; // 1/6" top and bottom driver_data->borderless = true; // Also borderless sizes driver_data->finishings = PAPPL_FINISHINGS_PUNCH | PAPPL_FINISHINGS_STAPLE; driver_data->num_media = (int)(sizeof(pwg_common_media) / sizeof(pwg_common_media[0])); memcpy((void *)driver_data->media, pwg_common_media, sizeof(pwg_common_media)); driver_data->num_source = 4; driver_data->source[0] = "main"; driver_data->source[1] = "alternate"; driver_data->source[2] = "manual"; driver_data->source[3] = "by-pass-tray"; if (driver_data->raster_types & PAPPL_PWG_RASTER_TYPE_SRGB_8) { // Color office printer gets two output bins... driver_data->num_bin = 2; driver_data->bin[0] = "center"; driver_data->bin[1] = "rear"; } else { // B&W office printer gets one output bin... driver_data->num_bin = 1; driver_data->bin[0] = "center"; } papplCopyString(driver_data->media_default.size_name, "na_letter_8.5x11in", sizeof(driver_data->media_default.size_name)); papplCopyString(driver_data->media_ready[0].size_name, "na_letter_8.5x11in", sizeof(driver_data->media_ready[0].size_name)); papplCopyString(driver_data->media_ready[1].size_name, "iso_a4_210x297mm", sizeof(driver_data->media_ready[1].size_name)); driver_data->sides_supported = PAPPL_SIDES_ONE_SIDED | PAPPL_SIDES_TWO_SIDED_LONG_EDGE | PAPPL_SIDES_TWO_SIDED_SHORT_EDGE; driver_data->sides_default = PAPPL_SIDES_TWO_SIDED_LONG_EDGE; } else { papplLog(system, PAPPL_LOGLEVEL_ERROR, "No dimension information in driver name '%s'.", driver_name); return (false); } if (!strncmp(driver_name, "pwg_common-", 11)) { driver_data->color_supported = PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_AUTO_MONOCHROME | PAPPL_COLOR_MODE_COLOR | PAPPL_COLOR_MODE_MONOCHROME; driver_data->color_default = PAPPL_COLOR_MODE_AUTO; driver_data->num_type = 8; driver_data->type[0] = "stationery"; driver_data->type[1] = "stationery-letterhead"; driver_data->type[2] = "labels"; driver_data->type[3] = "photographic"; driver_data->type[4] = "photographic-glossy"; driver_data->type[5] = "photographic-matte"; driver_data->type[6] = "transparency"; driver_data->type[7] = "envelope"; papplCopyString(driver_data->media_default.size_name, papplLocGetDefaultMediaSizeName(), sizeof(driver_data->media_default.size_name)); } else { static const int integers[] = // List of integers { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 }; static const char * const keywords[] = { // List of keywords "one-fish", "two-fish", "red-fish", "blue-fish" }; driver_data->color_supported = PAPPL_COLOR_MODE_AUTO | PAPPL_COLOR_MODE_MONOCHROME; driver_data->color_default = PAPPL_COLOR_MODE_MONOCHROME; memset(driver_data->gdither, 127, sizeof(driver_data->gdither)); driver_data->icons[0].data = label_sm_png; driver_data->icons[0].datalen = sizeof(label_sm_png); driver_data->icons[1].data = label_md_png; driver_data->icons[1].datalen = sizeof(label_md_png); driver_data->icons[2].data = label_lg_png; driver_data->icons[2].datalen = sizeof(label_lg_png); driver_data->top_offset_supported[0] = -2000; driver_data->top_offset_supported[1] = 2000; driver_data->tracking_supported = PAPPL_MEDIA_TRACKING_MARK | PAPPL_MEDIA_TRACKING_CONTINUOUS; driver_data->num_type = 3; driver_data->type[0] = "labels"; driver_data->type[1] = "continuous"; driver_data->type[2] = "labels-continuous"; driver_data->sides_supported = PAPPL_SIDES_ONE_SIDED; driver_data->sides_default = PAPPL_SIDES_ONE_SIDED; driver_data->num_vendor = 5; driver_data->vendor[0] = "vendor-boolean"; driver_data->vendor[1] = "vendor-integer"; driver_data->vendor[2] = "vendor-keyword"; driver_data->vendor[3] = "vendor-range"; driver_data->vendor[4] = "vendor-text"; *driver_attrs = ippNew(); ippAddBoolean(*driver_attrs, IPP_TAG_PRINTER, "vendor-boolean-default", 1); ippAddBoolean(*driver_attrs, IPP_TAG_PRINTER, "vendor-boolean-supported", 1); ippAddInteger(*driver_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "vendor-integer-default", 7); ippAddIntegers(*driver_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "vendor-integer-supported", (int)(sizeof(integers) / sizeof(integers[0])), integers); ippAddString(*driver_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "vendor-keyword-default", NULL, "two-fish"); ippAddStrings(*driver_attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "vendor-keyword-supported", (int)(sizeof(keywords) / sizeof(keywords[0])), NULL, keywords); ippAddInteger(*driver_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "vendor-range-default", 42); ippAddRange(*driver_attrs, IPP_TAG_PRINTER, "vendor-range-supported", -100, 100); ippAddString(*driver_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "vendor-text-default", NULL, "Hello, World!"); } // Fill out ready and default media for (i = 0; i < driver_data->num_source; i ++) { pwg_media_t *pwg = pwgMediaForPWG(driver_data->media_ready[i].size_name); if (pwg) { driver_data->media_ready[i].bottom_margin = driver_data->bottom_top; driver_data->media_ready[i].left_margin = driver_data->left_right; driver_data->media_ready[i].right_margin = driver_data->left_right; driver_data->media_ready[i].size_width = pwg->width; driver_data->media_ready[i].size_length = pwg->length; driver_data->media_ready[i].top_margin = driver_data->bottom_top; driver_data->media_ready[i].tracking = PAPPL_MEDIA_TRACKING_MARK; papplCopyString(driver_data->media_ready[i].source, driver_data->source[i], sizeof(driver_data->media_ready[i].source)); papplCopyString(driver_data->media_ready[i].type, driver_data->type[0], sizeof(driver_data->media_ready[i].type)); } if (!strcmp(driver_data->media_default.size_name, driver_data->media_ready[i].size_name)) driver_data->media_default = driver_data->media_ready[i]; } return (true); } // // 'pwg_identify()' - Identify the printer. // static void pwg_identify( pappl_printer_t *printer, // I - Printer pappl_identify_actions_t actions, // I - Actions to take const char *message) // I - Message, if any { (void)printer; (void)actions; // TODO: Open console and send BEL character and message to it instead... putchar(7); if (message) puts(message); fflush(stdout); } // // 'pwg_print()' - Print a file. // static bool // O - `true` on success, `false` on failure pwg_print( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options (unused) pappl_device_t *device) // I - Print device (unused) { int fd; // Input file ssize_t bytes; // Bytes read/written char buffer[65536]; // Read/write buffer (void)options; papplJobSetImpressions(job, 1); if ((fd = open(papplJobGetFilename(job), O_RDONLY)) < 0) { papplLogJob(job, PAPPL_LOGLEVEL_ERROR, "Unable to open print file '%s': %s", papplJobGetFilename(job), strerror(errno)); return (false); } while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) papplDeviceWrite(device, buffer, (size_t)bytes); close(fd); papplJobSetImpressionsCompleted(job, 1); return (true); } // // 'pwg_rendjob()' - End a job. // static bool // O - `true` on success, `false` on failure pwg_rendjob( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options (unused) pappl_device_t *device) // I - Print device (unused) { pwg_job_data_t *pwg = (pwg_job_data_t *)papplJobGetData(job); // Job data (void)options; (void)device; cupsRasterClose(pwg->ras); free(pwg); papplJobSetData(job, NULL); return (true); } // // 'pwg_rendpage()' - End a page. // static bool // O - `true` on success, `false` on failure pwg_rendpage( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options pappl_device_t *device, // I - Print device (unused) unsigned page) // I - Page number { pwg_job_data_t *pwg = (pwg_job_data_t *)papplJobGetData(job); // PWG driver data pappl_printer_t *printer = papplJobGetPrinter(job); // Printer pappl_supply_t supplies[5]; // Supply-level data (void)device; (void)page; if (papplPrinterGetSupplies(printer, 5, supplies) == 5) { // Calculate ink usage from coverage - figure 100 pages at 10% for black, // 50 pages at 10% for CMY, and 200 pages at 10% for the waste tank... int i; // Looping var int c, m, y, k, w; // Ink usage pappl_preason_t reasons = PAPPL_PREASON_NONE; // "printer-state-reasons" values papplLogJob(job, PAPPL_LOGLEVEL_DEBUG, "Calculating ink usage (%u,%u,%u,%u)", (unsigned)pwg->colorants[0], (unsigned)pwg->colorants[1], (unsigned)pwg->colorants[2], (unsigned)pwg->colorants[3]); c = (int)(pwg->colorants[0] / options->header.cupsWidth / options->header.cupsHeight / 5); m = (int)(pwg->colorants[1] / options->header.cupsWidth / options->header.cupsHeight / 5); y = (int)(pwg->colorants[2] / options->header.cupsWidth / options->header.cupsHeight / 5); k = (int)(pwg->colorants[3] / options->header.cupsWidth / options->header.cupsHeight / 10); w = (int)((pwg->colorants[0] + pwg->colorants[1] + pwg->colorants[2] + pwg->colorants[3]) / options->header.cupsWidth / options->header.cupsHeight / 20); // Keep levels between 0 and 100... if ((supplies[0].level -= c) < 0) supplies[0].level = 100; // Auto-refill if ((supplies[1].level -= m) < 0) supplies[1].level = 100; // Auto-refill if ((supplies[2].level -= y) < 0) supplies[2].level = 100; // Auto-refill if ((supplies[3].level -= k) < 0) supplies[3].level = 100; // Auto-refill if ((supplies[4].level += w) > 100) supplies[4].level = 0; // Auto-replace // Update printer-state-reasons accordingly... for (i = 0; i < 4; i ++) { if (supplies[i].level == 0) reasons |= PAPPL_PREASON_MARKER_SUPPLY_EMPTY; else if (supplies[i].level < 10) reasons |= PAPPL_PREASON_MARKER_SUPPLY_LOW; } if (supplies[4].level == 100) reasons |= PAPPL_PREASON_MARKER_WASTE_FULL; else if (supplies[4].level >= 90) reasons |= PAPPL_PREASON_MARKER_WASTE_ALMOST_FULL; papplPrinterSetSupplies(printer, 5, supplies); papplPrinterSetReasons(printer, reasons, PAPPL_PREASON_DEVICE_STATUS); } return (true); } // // 'pwg_rstartjob()' - Start a job. // static bool // O - `true` on success, `false` on failure pwg_rstartjob( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options pappl_device_t *device) // I - Print device (unused) { pwg_job_data_t *pwg = (pwg_job_data_t *)calloc(1, sizeof(pwg_job_data_t)); // PWG driver data (void)options; papplJobSetData(job, pwg); pwg->ras = cupsRasterOpenIO((cups_raster_cb_t)papplDeviceWrite, device, CUPS_RASTER_WRITE_PWG); return (1); } // // 'pwg_rstartpage()' - Start a page. // static bool // O - `true` on success, `false` on failure pwg_rstartpage( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options pappl_device_t *device, // I - Print device (unused) unsigned page) // I - Page number { pwg_job_data_t *pwg = (pwg_job_data_t *)papplJobGetData(job); // PWG driver data (void)device; (void)page; memset(pwg->colorants, 0, sizeof(pwg->colorants)); return (cupsRasterWriteHeader(pwg->ras, &options->header) != 0); } // // 'pwg_rwriteline()' - Write a raster line. // static bool // O - `true` on success, `false` on failure pwg_rwriteline( pappl_job_t *job, // I - Job pappl_pr_options_t *options, // I - Job options pappl_device_t *device, // I - Print device (unused) unsigned y, // I - Line number const unsigned char *line) // I - Line { const unsigned char *lineptr, // Pointer into line *lineend; // End of line pwg_job_data_t *pwg = (pwg_job_data_t *)papplJobGetData(job); // PWG driver data (void)device; (void)y; // Add the colorant usage for this line (for simulation purposes - normally // this is tracked by the printer/ink cartridge...) lineend = line + options->header.cupsBytesPerLine; switch (options->header.cupsColorSpace) { case CUPS_CSPACE_K : if (options->header.cupsBitsPerPixel == 1) { // 1-bit K static unsigned short amounts[256] = { // Amount of "ink" used for 8 pixels 0, 255, 255, 510, 255, 510, 510, 765, 255, 510, 510, 765, 510, 765, 765, 1020, 255, 510, 510, 765, 510, 765, 765, 1020, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 255, 510, 510, 765, 510, 765, 765, 1020, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 255, 510, 510, 765, 510, 765, 765, 1020, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 1020, 1275, 1275, 1530, 1275, 1530, 1530, 1785, 255, 510, 510, 765, 510, 765, 765, 1020, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 1020, 1275, 1275, 1530, 1275, 1530, 1530, 1785, 510, 765, 765, 1020, 765, 1020, 1020, 1275, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 1020, 1275, 1275, 1530, 1275, 1530, 1530, 1785, 765, 1020, 1020, 1275, 1020, 1275, 1275, 1530, 1020, 1275, 1275, 1530, 1275, 1530, 1530, 1785, 1020, 1275, 1275, 1530, 1275, 1530, 1530, 1785, 1275, 1530, 1530, 1785, 1530, 1785, 1785, 2040 }; for (lineptr = line; lineptr < lineend; lineptr ++) pwg->colorants[3] += amounts[*lineptr]; } else { // 8-bit K for (lineptr = line; lineptr < lineend; lineptr ++) pwg->colorants[3] += *lineptr; } break; case CUPS_CSPACE_W : case CUPS_CSPACE_SW : // 8-bit W (luminance) for (lineptr = line; lineptr < lineend; lineptr ++) pwg->colorants[3] += 255 - *lineptr; break; case CUPS_CSPACE_RGB : case CUPS_CSPACE_SRGB : case CUPS_CSPACE_ADOBERGB : // 24-bit RGB for (lineptr = line; lineptr < lineend; lineptr += 3) { // Convert RGB to CMYK using simple transform... unsigned char cc = 255 - lineptr[0]; unsigned char cm = 255 - lineptr[1]; unsigned char cy = 255 - lineptr[2]; unsigned char ck = cc; if (ck > cm) ck = cm; if (ck > cy) ck = cy; cc -= ck; cm -= ck; cy -= ck; pwg->colorants[0] += cc; pwg->colorants[1] += cm; pwg->colorants[2] += cy; pwg->colorants[3] += ck; } break; case CUPS_CSPACE_CMYK : // 32-bit CMYK for (lineptr = line; lineptr < lineend; lineptr += 4) { pwg->colorants[0] += lineptr[0]; pwg->colorants[1] += lineptr[1]; pwg->colorants[2] += lineptr[2]; pwg->colorants[3] += lineptr[3]; } break; default : break; } return (cupsRasterWritePixels(pwg->ras, (unsigned char *)line, options->header.cupsBytesPerLine) != 0); } // // 'pwg_status()' - Get current printer status. // static bool // O - `true` on success, `false` on failure pwg_status( pappl_printer_t *printer) // I - Printer { if (!strncmp(papplPrinterGetDriverName(printer), "pwg_common-", 11)) { // Supply levels... static pappl_supply_t supply[5] = // Supply level data { { PAPPL_SUPPLY_COLOR_CYAN, "Cyan Ink", true, 100, PAPPL_SUPPLY_TYPE_INK }, { PAPPL_SUPPLY_COLOR_MAGENTA, "Magenta Ink", true, 100, PAPPL_SUPPLY_TYPE_INK }, { PAPPL_SUPPLY_COLOR_YELLOW, "Yellow Ink", true, 100, PAPPL_SUPPLY_TYPE_INK }, { PAPPL_SUPPLY_COLOR_BLACK, "Black Ink", true, 100, PAPPL_SUPPLY_TYPE_INK }, { PAPPL_SUPPLY_COLOR_NO_COLOR, "Waste Ink Tank", true, 0, PAPPL_SUPPLY_TYPE_WASTE_INK } }; if (papplPrinterGetSupplies(printer, 0, NULL) == 0) papplPrinterSetSupplies(printer, (int)(sizeof(supply) / sizeof(supply[0])), supply); } // Every 10 seconds, set the "media-empty" reason for one second... if ((time(NULL) % 10) == 0) papplPrinterSetReasons(printer, PAPPL_PREASON_MEDIA_EMPTY, PAPPL_PREASON_NONE); else papplPrinterSetReasons(printer, PAPPL_PREASON_NONE, PAPPL_PREASON_MEDIA_EMPTY); return (true); } // // 'pwg_testpage()' - Return a test page file to print // static const char * // O - Filename or `NULL` pwg_testpage( pappl_printer_t *printer, // I - Printer char *buffer, // I - File Buffer size_t bufsize) // I - Buffer Size { const char *testfile; // Test File pappl_pr_driver_data_t data; // Driver data // Get the printer capabilities... papplPrinterGetDriverData(printer, &data); // Find the right test file... if (data.color_supported & PAPPL_COLOR_MODE_COLOR) testfile = "portrait-color.png"; else testfile = "portrait-gray.png"; papplCopyString(buffer, testfile, bufsize); if (access(buffer, R_OK)) snprintf(buffer, bufsize, "testsuite/%s", testfile); if (access(buffer, R_OK)) { *buffer = '\0'; return (NULL); } else { return (buffer); } } pappl-1.4.9/testsuite/set-wifi.test000066400000000000000000000007541476704353100173420ustar00rootroot00000000000000# Set Wi-Fi attributes # # Usage: # # ipptool -d ssid=SSID -d password=PASSWORD PRINTER-URI set-wifi.test # { NAME "Set Wi-Fi attributes" OPERATION Set-Printer-Attributes VERSION 2.0 GROUP operation-attributes-tag ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en ATTR uri printer-uri $uri GROUP printer-attributes-tag ATTR name printer-wifi-ssid $ssid ATTR octetString printer-wifi-password $password STATUS successful-ok } pappl-1.4.9/testsuite/template.c000066400000000000000000000004031476704353100166600ustar00rootroot00000000000000// // file for the Printer Application Framework // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include pappl-1.4.9/testsuite/test.h000066400000000000000000000142211476704353100160340ustar00rootroot00000000000000// // Unit test header for C/C++ programs. // // Copyright © 2021-2022 by Michael R Sweet. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // #ifndef TEST_H # define TEST_H # include # include # include # include # include # if _WIN32 # define isatty(f) _isatty(f) # else # include # endif // !_WIN32 # ifdef __cplusplus extern "C" { # endif // __cplusplus # if _WIN32 # define TEST_FORMAT(a,b) # elif defined(__has_extension) || defined(__GNUC__) # define TEST_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b))) # else # define TEST_FORMAT(a,b) # endif // _WIN32 // // This header implements a simple unit test framework for C/C++ programs. Inline // functions are provided to write a test summary to stdout and the details to stderr. // static int test_progress; // Current progress static inline void testBegin(const char *title, ...) TEST_FORMAT(1,2); static inline void testEnd(bool pass); static inline void testEndMessage(bool pass, const char *message, ...) TEST_FORMAT(2,3); static inline void testError(const char *error, ...) TEST_FORMAT(1,2); static inline void testHexDump(const unsigned char *buffer, size_t bytes); static inline void testMessage(const char *error, ...) TEST_FORMAT(1,2); static inline void testProgress(void); // Start a test static inline void testBegin(const char *title, ...) // I - printf-style title string { char buffer[1024]; // Formatted title string va_list ap; // Pointer to additional arguments // Format the title string va_start(ap, title); vsnprintf(buffer, sizeof(buffer), title, ap); va_end(ap); // Send the title to stdout and stderr... test_progress = 0; printf("%s: ", buffer); fflush(stdout); #ifndef DEBUG if (!isatty(2)) fprintf(stderr, "%s: ", buffer); #endif // !DEBUG } // End a test with no additional information static inline void testEnd(bool pass) // I - `true` if the test passed, `false` otherwise { // Send the test result to stdout and stderr if (test_progress) putchar('\b'); puts(pass ? "PASS" : "FAIL"); #ifndef DEBUG if (!isatty(2)) fputs(pass ? "PASS\n" : "FAIL\n", stderr); #endif // !DEBUG } // End a test with no additional information static inline void testEndMessage(bool pass, // I - `true` if the test passed, `false` otherwise const char *message, ...)// I - printf-style message { char buffer[1024]; // Formatted title string va_list ap; // Pointer to additional arguments // Format the title string va_start(ap, message); vsnprintf(buffer, sizeof(buffer), message, ap); va_end(ap); // Send the test result to stdout and stderr if (test_progress) putchar('\b'); printf(pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer); #ifndef DEBUG if (!isatty(2)) fprintf(stderr, pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer); #endif // !DEBUG } // Show/update a progress spinner static inline void testProgress(void) { if (test_progress) putchar('\b'); putchar("-\\|/"[test_progress & 3]); fflush(stdout); test_progress ++; } // Show an error to stderr... static inline void testError(const char *error, ...) // I - printf-style error string { char buffer[1024]; // Formatted title string va_list ap; // Pointer to additional arguments // Format the error string va_start(ap, error); vsnprintf(buffer, sizeof(buffer), error, ap); va_end(ap); // Send the error to stderr... fprintf(stderr, "%s\n", buffer); } // Show a message to stdout and stderr... static inline void testMessage(const char *error, ...) // I - printf-style error string { char buffer[1024]; // Formatted title string va_list ap; // Pointer to additional arguments // Format the error string va_start(ap, error); vsnprintf(buffer, sizeof(buffer), error, ap); va_end(ap); // Send the message to stdout and stderr too if needed... printf("%s\n", buffer); #ifndef DEBUG if (!isatty(2)) fprintf(stderr, "%s\n", buffer); #endif // !DEBUG } // Show a hex dump of a buffer to stderr... static inline void testHexDump(const unsigned char *buffer,// I - Buffer size_t bytes) // I - Number of bytes { size_t i, j; // Looping vars int ch; // Current ASCII char // Show lines of 16 bytes at a time... for (i = 0; i < bytes; i += 16) { // Show the offset... fprintf(stderr, "%04x ", (unsigned)i); // Then up to 16 bytes in hex... for (j = 0; j < 16; j ++) { if ((i + j) < bytes) fprintf(stderr, " %02x", buffer[i + j]); else fputs(" ", stderr); } // Then the ASCII representation of the bytes... fputs(" ", stderr); for (j = 0; j < 16 && (i + j) < bytes; j ++) { ch = buffer[i + j] & 127; if (ch < ' ' || ch == 127) fputc('.', stderr); else fputc(ch, stderr); } fputc('\n', stderr); } } # ifdef __cplusplus } # endif // __cplusplus #endif // !TEST_H pappl-1.4.9/testsuite/testhttpmon.c000066400000000000000000000162361476704353100174510ustar00rootroot00000000000000// // HTTP monitor unit tests for the Printer Application Framework // // Copyright © 2021-2022 by Michael R Sweet. // Copyright © 2012 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include #include "test.h" // // Local test data for the unit tests. // // Tests are a series of character strings; each string starts with a C if the // data comes from the client/USB host and S if it comes from the server/USB // device. The final element in the array must be NULL... // static const char * const good_basic_get[] = { "CGET / HTTP/1.1\r\n" "Host: localhost:1234\r\n" "\r\n", "SHTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 13\r\n" "\r\n", "SHello, World!", NULL }; static const char * const bad_basic_get[] = { "CGET /badresource HTTP/1.1\r\n" "Host: localhost:1234\r\n" "\r\n", "SHTTP/1.1 400 Bad Request\r\n" "Content-Type: text/plain\r\n" "Content-Length: 12\r\n" "\r\n", "SBad Request!", NULL }; static const char * const basic_head[] = { "CHEAD / HTTP/1.1\r\n" "Host: localhost:1234\r\n" "\r\n", "SHTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 13\r\n" "\r\n", NULL }; static const char * const basic_post[] = { "CPOST / HTTP/1.1\r\n" "Host: localhost:1234\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 13\r\n" "\r\n", "CHello, World!", // This doesn't need to be real IPP message data */ "SHTTP/1.1 200 OK\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 13\r\n" "\r\n", "SHello, World!", // This doesn't need to be real IPP message data */ NULL }; static const char * const post_continue[] = { "CPOST / HTTP/1.1\r\n" "Host: localhost:1234\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 26\r\n" "Expect: 100-continue\r\n" "\r\n", "CHello, World!", // This doesn't need to be real IPP message data */ "SHTTP/1.1 100 Continue\r\n" "\r\n", "CHello, World!", // This doesn't need to be real IPP message data */ "SHTTP/1.1 200 OK\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 13\r\n" "\r\n", "SHello, World!", // This doesn't need to be real IPP message data */ NULL }; static const char * const post_no_continue[] = { "CPOST / HTTP/1.1\r\n" "Host: localhost:1234\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 13\r\n" "Expect: 100-continue\r\n" "\r\n", "CHello, World!", // This doesn't need to be real IPP message data */ "SHTTP/1.1 200 OK\r\n" "Content-Type: application/ipp\r\n" "Content-Length: 13\r\n" "\r\n", "SHello, World!", // This doesn't need to be real IPP message data */ NULL }; static const char * const good_chunked_get[] = { "CGET / HTTP/1.1", "C\r\n", "CHost: localhost:1234", "C\r\n", "C\r\n", "SHTTP/1.1 200 OK", "S\r\n", "SContent-Type: text/plain", "S\r\n", "STransfer-Encoding: chunked", "S\r\n", "S\r\n", "SD\r\n", "SHello, World!", "S\r\n", "S0\r\n", "S\r\n", NULL }; static const char * const bad_chunked_get[] = { "CGET / HTTP/1.1", "C\r\n", "CHost: localhost:1234", "C\r\n", "C\r\n", "S200 OK", "S\r\n", "SContent-Type: text/plain", "S\r\n", "STransfer-Encoding: chunked", "S\r\n", "S\r\n", "SD\r\n", "SHello, World!", "S\r\n", // Missing trailing 0 chunk... NULL }; static const char * const chunked_post[] = { "CPOST / HTTP/1.1\r\n", "CHost: localhost:1234\r\n", "CContent-Type: application/ipp\r\n", "CTransfer-Encoding: chunked\r\n", "C\r\n", "CD\r\n", "CHello, World!", // This doesn't need to be real IPP message data */ "C\r\n", "C0\r\n", "C\r\n", "SHTTP/1.1 200 OK\r\n", "SContent-Type: application/ipp\r\n", "STransfer-Encoding: chunked\r\n", "S\r\n", "SD\r\n", "SHello, World!", "S\r\n", "SD\r\nHello, World!\r\n" "D\r\nHello, World!\r\n", // 2 chunks in one buffer "S0\r\n", "S\r\n", NULL }; static const char * const no_content_length_response[] = { "CPOST /eSCL/ScanJobs HTTP/1.1\r\n" "Host: localhost:1234\r\n" "Content-Type:text/xml\r\n" "Content-Length: 13\r\n", "C\r\n", "CHello, World!", // This doesn't need to be real XML eSCL job settings */ "SHTTP/1.1 201 Created\r\n" "Accept-Encoding: identity\r\n" "Date: Mon, 01 Jun 2015 22:01:12GMT\r\n" "Server: KM-MFP-http/V0.0.1\r\n" "Location: http://localhost:1234/eSCL/ScanJobs/1001\r\n", "S\r\n", NULL }; // // Local functions... // static bool run_tests(const char *name, _pappl_http_monitor_t *hm, const char * const *strings, http_status_t expected); // // 'main()' - Test the HTTP monitor code. // int // O - Exit status main(void) { bool pass = true; // Pass or fail _pappl_http_monitor_t hm; // HTTP monitor _papplHTTPMonitorInit(&hm); pass &= run_tests("Good Basic GET", &hm, good_basic_get, HTTP_STATUS_OK); hm.data_remaining = 1; pass &= run_tests("No Content Length Response", &hm, no_content_length_response, HTTP_STATUS_CREATED); pass &= run_tests("Bad Basic GET", &hm, bad_basic_get, HTTP_STATUS_BAD_REQUEST); pass &= run_tests("Basic HEAD", &hm, basic_head, HTTP_STATUS_OK); pass &= run_tests("Basic POST", &hm, basic_post, HTTP_STATUS_OK); pass &= run_tests("POST Expect w/Continue", &hm, post_continue, HTTP_STATUS_OK); pass &= run_tests("POST Expect w/o Continue", &hm, post_no_continue, HTTP_STATUS_OK); pass &= run_tests("Good Chunked GET", &hm, good_chunked_get, HTTP_STATUS_OK); pass &= run_tests("Chunked POST", &hm, chunked_post, HTTP_STATUS_OK); pass &= run_tests("Bad Chunked GET", &hm, bad_chunked_get, HTTP_STATUS_ERROR); return (pass ? 0 : 1); } // // 'run_tests()' - Run tests from an array of client/server data strings // static bool // O - `true` on success, `false` on failure run_tests( const char *name, // I - Test name _pappl_http_monitor_t *hm, // I - HTTP monitor const char * const *strings, // I - Array of test data http_status_t expected) // I - Expected HTTP status { http_status_t status = HTTP_STATUS_CONTINUE; // Current HTTP status const char *s; // Current string size_t len; // Length of string // Show the test name... testBegin("%s: ", name); // Loop until we get an error or run out of data... while (status != HTTP_STATUS_ERROR && *strings) { s = *strings++; len = strlen(s + 1); if (*s == 'C') { s ++; status = _papplHTTPMonitorProcessHostData(hm, &s, &len); } else { status = _papplHTTPMonitorProcessDeviceData(hm, s + 1, len); } } if (status != HTTP_STATUS_ERROR && _papplHTTPMonitorGetState(hm) != HTTP_STATE_WAITING) { hm->status = status = HTTP_STATUS_ERROR; hm->error = "Not in the HTTP_WAITING state."; } if (status == expected) testEnd(true); else if (status == HTTP_STATUS_ERROR) testEndMessage(false, "%s", _papplHTTPMonitorGetError(hm)); else if (status != expected) testEndMessage(false, "got status %d", status); return (status == expected); } pappl-1.4.9/testsuite/testmainloop.c000066400000000000000000000117271476704353100175760ustar00rootroot00000000000000// // papplMainloop unit test for the Printer Application Framework // // Copyright © 2020-2022 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include "testpappl.h" #include #include // // Local constants... // #define FOOTER_HTML "Copyright © 2020-2022 by Michael R Sweet. Provided under the terms of the Apache License 2.0." #define VERSION_STRING "1.2 build 42" // // Local functions... // static pappl_system_t *system_cb(int num_options, cups_option_t *options, void *data); // // 'main()' - Main entry for unit test. // int // O - Exit status main(int argc, // I - Number of command line arguments char *argv[]) // I - Command line arguments { if (getenv("PAPPL_USE_SYSTEM_CB")) return (papplMainloop(argc, argv, VERSION_STRING, FOOTER_HTML, (int)(sizeof(pwg_drivers) / sizeof(pwg_drivers[0])), pwg_drivers, /*autoadd_cb*/NULL, pwg_callback, /*subcmd_name*/NULL, /*subcmd_cb*/NULL, system_cb, /*usage_cb*/NULL, "testmainloop")); else return (papplMainloop(argc, argv, VERSION_STRING, FOOTER_HTML, (int)(sizeof(pwg_drivers) / sizeof(pwg_drivers[0])), pwg_drivers, /*autoadd_cb*/NULL, pwg_callback, /*subcmd_name*/NULL, /*subcmd_cb*/NULL, /*system_cb*/NULL, /*usage_cb*/NULL, "testmainloop")); } // // 'system_cb()' - System callback. // pappl_system_t * // O - New system object system_cb(int num_options, // I - Number of options cups_option_t *options, // I - Options void *data) // I - Callback data { pappl_system_t *system; // System object const char *val, // Current option value *hostname, // Hostname, if any *logfile, // Log file, if any *system_name; // System name, if any pappl_loglevel_t loglevel; // Log level int port = 0; // Port number, if any pappl_soptions_t soptions = PAPPL_SOPTIONS_MULTI_QUEUE | PAPPL_SOPTIONS_WEB_INTERFACE | PAPPL_SOPTIONS_WEB_LOG | PAPPL_SOPTIONS_WEB_NETWORK | PAPPL_SOPTIONS_WEB_SECURITY | PAPPL_SOPTIONS_WEB_TLS; // System options static pappl_contact_t contact = // Contact information { "John Q Admin", "jqadmin@example.org", "+1-705-555-1212" }; static pappl_version_t versions[1] = // Software versions { { "Test Application", "", VERSION_STRING, { PAPPL_VERSION_MAJOR, PAPPL_VERSION_MINOR, 0, 42 } } }; // Verify that the right callback data was sent to us... if (!data || strcmp((char *)data, "testmainloop")) { fprintf(stderr, "testmainloop: Bad callback data %p.\n", data); return (NULL); } // Parse options... if ((val = cupsGetOption("log-level", (cups_len_t)num_options, options)) != NULL) { if (!strcmp(val, "fatal")) loglevel = PAPPL_LOGLEVEL_FATAL; else if (!strcmp(val, "error")) loglevel = PAPPL_LOGLEVEL_ERROR; else if (!strcmp(val, "warn")) loglevel = PAPPL_LOGLEVEL_WARN; else if (!strcmp(val, "info")) loglevel = PAPPL_LOGLEVEL_INFO; else if (!strcmp(val, "debug")) loglevel = PAPPL_LOGLEVEL_DEBUG; else { fprintf(stderr, "testmainloop: Bad log-level value '%s'.\n", val); return (NULL); } } else loglevel = PAPPL_LOGLEVEL_UNSPEC; logfile = cupsGetOption("log-file", (cups_len_t)num_options, options); hostname = cupsGetOption("server-hostname", (cups_len_t)num_options, options); system_name = cupsGetOption("system-name", (cups_len_t)num_options, options); if ((val = cupsGetOption("server-port", (cups_len_t)num_options, options)) != NULL) { if (!isdigit(*val & 255)) { fprintf(stderr, "testmainloop: Bad server-port value '%s'.\n", val); return (NULL); } else port = atoi(val); } // Create the system object... if ((system = papplSystemCreate(soptions, system_name ? system_name : "testmainloop", port, "_print,_universal", cupsGetOption("spool-directory", (cups_len_t)num_options, options), logfile ? logfile : "-", loglevel, cupsGetOption("auth-service", (cups_len_t)num_options, options), /* tls_only */false)) == NULL) return (NULL); papplSystemAddListeners(system, NULL); papplSystemSetHostName(system, hostname); papplSystemSetPrinterDrivers(system, (int)(sizeof(pwg_drivers) / sizeof(pwg_drivers[0])), pwg_drivers, pwg_autoadd, /*create_cb*/NULL, pwg_callback, "testmainloop"); papplSystemSetFooterHTML(system, FOOTER_HTML); papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, (void *)"/tmp/testmainloop.state"); papplSystemSetVersions(system, (int)(sizeof(versions) / sizeof(versions[0])), versions); if (!papplSystemLoadState(system, "/tmp/testmainloop.state")) { papplSystemSetContact(system, &contact); papplSystemSetDNSSDName(system, system_name ? system_name : "Test Mainloop"); papplSystemSetGeoLocation(system, "geo:46.4707,-80.9961"); papplSystemSetLocation(system, "Test Lab 42"); papplSystemSetOrganization(system, "Example Company"); } return (system); } pappl-1.4.9/testsuite/testpappl.c000066400000000000000000004237721476704353100171030ustar00rootroot00000000000000// // Main test suite file for the Printer Application Framework // // Copyright © 2020-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Usage: // // testpappl [OPTIONS] ["SERVER NAME"] // // Options: // // --get-id DEVICE-URI Show IEEE-1284 device ID for URI // --get-status DEVICE-URI Show printer status bits for URI // --get-supplies DEVICE-URI Show supplies for URI // --help Show help // --list[-TYPE] List devices (dns-sd, local, network, usb) // --no-tls Don't support TLS // --ps-query DEVICE-URI Do a PostScript query to get the product string // --version Show version // -1 Single queue // -A PAM-SERVICE Enable authentication using PAM service // -c Do a clean run (no loading of state) // -d SPOOL-DIRECTORY Set the spool directory // -l LOG-FILE Set the log file // -L LOG-LEVEL Set the log level (fatal, error, warn, info, debug) // -m DRIVER-NAME Add a printer with the named driver // -p PORT Set the listen port (default auto) // -t TEST-NAME Run the named test (see below) // -T Enable TLS-only mode // -U Enable USB printer gadget // // Tests: // // all All of the following tests // api API tests // client Simulated client tests // client-CLxRQ Simulated CL clients and RQ requests tests // client-max Simulated max clients and requests tests // jpeg JPEG image tests // png PNG image tests // pwg-raster PWG Raster tests // // // Include necessary headers... // #include #include #include "testpappl.h" #include "test.h" #include #include #if _WIN32 # define PATH_MAX MAX_PATH # define realpath(rel,abs) win32_realpath((rel), (abs)) static inline char *win32_realpath(const char *relpath, char *abspath) { // Win32 version of POSIX realpath that returns proper forward slash directory delimiters and handles // DOS drive letters... char temp[MAX_PATH], // Temporary path buffer *tempptr = temp, // Pointer into temp buffer *absptr = abspath, // Pointer into abspath buffer *absend = abspath + MAX_PATH - 1; // End of abspath buffer // Get the full path with drive letter... if (!_fullpath(temp, relpath, sizeof(temp))) return (NULL); if (isalpha(*tempptr & 255) && tempptr[1] == ':') { if (*tempptr == (_getdrive() + '@')) { // Same drive so just skip the drive letter... tempptr += 2; } else { // Otherwise encode as "/L:" *absptr++ = '/'; *absptr++ = *tempptr++; *absptr++ = *tempptr++; } } // Re-encode path using conventional forward slashes... while (*tempptr && absptr < absend) { if (*tempptr == '\\') *absptr++ = '/'; else *absptr++ = *tempptr; tempptr ++; } *absptr = '\0'; return (abspath); } #endif // _WIN32 // // Constants... // #define _PAPPL_DEFAULT_CLIENTS 100 #define _PAPPL_DEFAULT_REQUESTS 1000 #define _PAPPL_MAX_CLIENTS 1000 #define _PAPPL_MAX_REQUESTS 100000 #define _PAPPL_MAX_TIMER_COUNT 32 #define _PAPPL_TIMER_INTERVAL 5 // // Local globals... // static bool all_tests_done = false; // All tests are done? static char current_ssid[32] = ""; // Current wireless network static size_t event_count = 0;// Number of events that have been delivered static pappl_event_t event_mask = PAPPL_EVENT_NONE; // Events that have been delivered static int output_count = 0; // Number of expected output files static char output_directory[1024] = ""; // Output directory // // Local types... // typedef struct _pappl_testclient_s // Client test data { pappl_system_t *system; // System size_t num_children, // Number of child threads num_requests; // Requests per child pthread_mutex_t mutex; // Access mutex size_t completed_count,// Number of completed children request_count; // Number of requests cups_array_t *errors; // Errors, if any struct timeval start, end; // Start/end times } _pappl_testclient_t; typedef struct _pappl_testdata_s // Test data { cups_array_t *names; // Tests to run pappl_system_t *system; // System const char *outdirname; // Output directory bool waitsystem; // Wait for system to start? time_t timer_start; // Start time int timer_count; // Number of times the timer callback has been called time_t timer_times[1000]; // Timestamps for each timer callback } _pappl_testdata_t; typedef struct _pappl_testprinter_s // Printer test data { bool pass; // Pass/fail int count; // Number of printers } _pappl_testprinter_t; // // Local functions... // static http_t *connect_to_printer(pappl_system_t *system, bool remote, char *uri, size_t urisize); static void device_error_cb(const char *message, void *err_data); static bool device_list_cb(const char *device_info, const char *device_uri, const char *device_id, void *data); static int do_ps_query(const char *device_uri); static void event_cb(pappl_system_t *system, pappl_printer_t *printer, pappl_job_t *job, pappl_event_t event, void *data); static const char *make_raster_file(ipp_t *response, bool grayscale, char *tempname, size_t tempsize); static void *run_tests(_pappl_testdata_t *testdata); static char *strcopy_cb(const char *s, void *data); static void strfree_cb(char *s, void *data); static bool test_api(pappl_system_t *system); static bool test_api_printer(pappl_printer_t *printer); static bool test_api_printer_cb(pappl_printer_t *printer, _pappl_testprinter_t *tp); static bool test_client(pappl_system_t *system); static void *test_client_child(_pappl_testclient_t *data); static bool test_client_max(pappl_system_t *system, const char *name); #if defined(HAVE_LIBJPEG) || defined(HAVE_LIBPNG) static bool test_image_files(pappl_system_t *system, const char *prompt, const char *format, int num_files, const char * const *files); #endif // HAVE_LIBJPEG || HAVE_LIBPNG static size_t test_network_get_cb(pappl_system_t *system, void *data, size_t max_networks, pappl_network_t *networks); static bool test_network_set_cb(pappl_system_t *system, void *data, size_t num_networks, pappl_network_t *networks); static bool test_pwg_raster(pappl_system_t *system); static bool test_wifi_join_cb(pappl_system_t *system, void *data, const char *ssid, const char *psk); static int test_wifi_list_cb(pappl_system_t *system, void *data, cups_dest_t **ssids); static pappl_wifi_t *test_wifi_status_cb(pappl_system_t *system, void *data, pappl_wifi_t *wifi_data); static bool timer_cb(pappl_system_t *system, _pappl_testdata_t *data); static int usage(int status); // // 'main()' - Main entry for test suite. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { int i; // Looping var const char *opt, // Current option *name = NULL, // System name, if any *spool = NULL, // Spool directory, if any *outdir = "testpappl.output", // Output directory *log = NULL, // Log file, if any *auth = NULL, // Auth service, if any *model; // Current printer model cups_array_t *models; // Printer models, if any int port = 0; // Port number, if any pappl_loglevel_t level = PAPPL_LOGLEVEL_DEBUG; // Log level bool clean = false, // Clean run? tls_only = false; // Restrict to TLS only? char outdirname[PATH_MAX], // Output directory name device_uri[1024]; // Device URI for printers pappl_soptions_t soptions = PAPPL_SOPTIONS_MULTI_QUEUE | PAPPL_SOPTIONS_WEB_INTERFACE | PAPPL_SOPTIONS_WEB_LOG | PAPPL_SOPTIONS_WEB_NETWORK | PAPPL_SOPTIONS_WEB_SECURITY | PAPPL_SOPTIONS_WEB_TLS | PAPPL_SOPTIONS_RAW_SOCKET; // System options pappl_system_t *system; // System #ifdef __APPLE__ pthread_t sysid; // System thread ID #endif // __APPLE__ pappl_printer_t *printer; // Printer _pappl_testdata_t testdata; // Test data pthread_t testid = 0; // Test thread ID void *ret; // Return value from thread int status = 0; // Exit status static pappl_contact_t contact = // Contact information { "Michael R Sweet", "msweet@example.org", "+1-705-555-1212" }; static pappl_version_t versions[1] = // Software versions { { "Test System", "", "1.4 build 42", { 1, 4, 0, 42 } } }; // Don't buffer stdout/stderr... setbuf(stdout, NULL); setbuf(stderr, NULL); #if _WIN32 // Windows builds put the executables under the "vcnet/Platform/Configuration" directory... if (!access("../../../testsuite", 0)) _chdir("../../../testsuite"); freopen("testpappl-stderr.log", "w", stderr); #endif // _WIN32 // Parse command-line options... models = cupsArrayNew(/*cb*/NULL, /*cbdata*/NULL, /*hashcb*/NULL, /*hashsize*/0, /*copy_cb*/NULL, /*free_cb*/NULL); testdata.names = cupsArrayNew(/*cb*/NULL, /*cbdata*/NULL, /*hashcb*/NULL, /*hashsize*/0, (cups_acopy_cb_t)strcopy_cb, (cups_afree_cb_t)strfree_cb); testdata.timer_count = 0; testdata.timer_start = time(NULL); for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--get-id")) { pappl_device_t *device; // Device char device_id[1024]; // Device ID string i ++; if (i >= argc) { fputs("testpappl: Missing device URI after '--get-id'.\n", stderr); return (1); } if ((device = papplDeviceOpen(argv[i], "get-id", NULL, NULL)) == NULL) return (1); if (papplDeviceGetID(device, device_id, sizeof(device_id))) puts(device_id); else fprintf(stderr, "testpappl: No device ID for '%s'.\n", argv[i]); papplDeviceClose(device); goto done; } else if (!strcmp(argv[i], "--get-status")) { pappl_device_t *device; // Device pappl_preason_t reasons; // State reason bits i ++; if (i >= argc) { fputs("testpappl: Missing device URI after '--get-status'.\n", stderr); return (1); } if ((device = papplDeviceOpen(argv[i], "get-status", NULL, NULL)) == NULL) { status = 1; goto done; } reasons = papplDeviceGetStatus(device); papplDeviceClose(device); if (!reasons) puts("none"); if (reasons & PAPPL_PREASON_OTHER) puts("other"); if (reasons & PAPPL_PREASON_COVER_OPEN) puts("cover-open"); if (reasons & PAPPL_PREASON_INPUT_TRAY_MISSING) puts("input-tray-missing"); if (reasons & PAPPL_PREASON_MARKER_SUPPLY_EMPTY) puts("marker-supply-empty"); if (reasons & PAPPL_PREASON_MARKER_SUPPLY_LOW) puts("marker-supply-low"); if (reasons & PAPPL_PREASON_MARKER_WASTE_ALMOST_FULL) puts("marker-waste-almost-full"); if (reasons & PAPPL_PREASON_MARKER_WASTE_FULL) puts("marker-waste-full"); if (reasons & PAPPL_PREASON_MEDIA_EMPTY) puts("media-empty"); if (reasons & PAPPL_PREASON_MEDIA_JAM) puts("media-jam"); if (reasons & PAPPL_PREASON_MEDIA_LOW) puts("media-low"); if (reasons & PAPPL_PREASON_MEDIA_NEEDED) puts("media-needed"); if (reasons & PAPPL_PREASON_OFFLINE) puts("offline"); if (reasons & PAPPL_PREASON_SPOOL_AREA_FULL) puts("spool-area-full"); if (reasons & PAPPL_PREASON_TONER_EMPTY) puts("toner-empty"); if (reasons & PAPPL_PREASON_TONER_LOW) puts("toner-low"); if (reasons & PAPPL_PREASON_DOOR_OPEN) puts("door-open"); if (reasons & PAPPL_PREASON_IDENTIFY_PRINTER_REQUESTED) puts("identify-printer-requested"); goto done; } else if (!strcmp(argv[i], "--get-supplies")) { pappl_device_t *device; // Device int j, // Looping var num_supplies; // Number of supplies pappl_supply_t supplies[32]; // Supplies static const char * const supply_colors[] = { // Supply colors "no-color", "black", "cyan", "gray", "green", "light-cyan", "light-gray", "light-magenta", "magenta", "orange", "violet", "yellow", "multi-color" }; static const char * const supply_types[] = { // Supply types "bandingSupply", "bindingSupply", "cleanerUnit", "coronaWire", "covers", "developer", "fuserCleaningPad", "fuserOilWick", "fuserOil", "fuserOiler", "fuser", "inkCartridge", "inkRibbon", "ink", "inserts", "opc", "paperWrap", "ribbonWax", "solidWax", "staples", "stitchingWire", "tonerCartridge", "toner", "transferUnit", "wasteInk", "wasteToner", "wasteWater", "wasteWax", "water", "glueWaterAdditive", "wastePaper", "shrinkWrap", "other", "unknown" }; i ++; if (i >= argc) { fputs("testpappl: Missing device URI after '--get-supplies'.\n", stderr); status = 1; goto done; } if ((device = papplDeviceOpen(argv[i], "get-supplies", NULL, NULL)) == NULL) { status = 1; goto done; } if ((num_supplies = papplDeviceGetSupplies(device, (int)(sizeof(supplies) / sizeof(supplies[0])), supplies)) > 0) { for (j = 0; j < num_supplies; j ++) { if (supplies[j].color != PAPPL_SUPPLY_COLOR_NO_COLOR) printf("%40s: %d%% (%s, %s)\n", supplies[j].description, supplies[j].level, supply_types[supplies[j].type], supply_colors[supplies[j].color]); else printf("%40s: %d%% (%s)\n", supplies[j].description, supplies[j].level, supply_types[supplies[j].type]); } } else { fprintf(stderr, "testpappl: No supplies for '%s'.\n", argv[i]); } papplDeviceClose(device); goto done; } else if (!strcmp(argv[i], "--help")) { status = usage(0); goto done; } else if (!strcmp(argv[i], "--list")) { papplDeviceList(PAPPL_DEVTYPE_ALL, device_list_cb, NULL, device_error_cb, NULL); goto done; } else if (!strcmp(argv[i], "--list-dns-sd")) { papplDeviceList(PAPPL_DEVTYPE_DNS_SD, device_list_cb, NULL, device_error_cb, NULL); goto done; } else if (!strcmp(argv[i], "--list-local")) { papplDeviceList(PAPPL_DEVTYPE_LOCAL, device_list_cb, NULL, device_error_cb, NULL); goto done; } else if (!strcmp(argv[i], "--list-network")) { papplDeviceList(PAPPL_DEVTYPE_NETWORK, device_list_cb, NULL, device_error_cb, NULL); goto done; } else if (!strcmp(argv[i], "--list-usb")) { papplDeviceList(PAPPL_DEVTYPE_USB, device_list_cb, NULL, device_error_cb, NULL); goto done; } else if (!strcmp(argv[i], "--no-tls")) { soptions |= PAPPL_SOPTIONS_NO_TLS; } else if (!strcmp(argv[i], "--ps-query")) { i ++; if (i < argc) { return (do_ps_query(argv[i])); } else { puts("testpappl: Missing device URI after '--ps-query'."); status = usage(1); goto done; } } else if (!strcmp(argv[i], "--version")) { puts(PAPPL_VERSION); goto done; } else if (!strncmp(argv[i], "--", 2)) { printf("testpappl: Unknown option '%s'.\n", argv[i]); status = usage(1); goto done; } else if (argv[i][0] == '-') { for (opt = argv[i] + 1; *opt; opt ++) { switch (*opt) { case '1' : // -1 (single queue) soptions &= (pappl_soptions_t)~PAPPL_SOPTIONS_MULTI_QUEUE; break; case 'A' : // -A PAM-SERVICE i ++; if (i >= argc) { puts("testpappl: Expected PAM service name after '-A'."); return (usage(1)); } auth = argv[i]; break; case 'c' : // -c (clean run) clean = true; break; case 'd' : // -d SPOOL-DIRECTORY i ++; if (i >= argc) { puts("testpappl: Expected spool directory after '-d'."); return (usage(1)); } spool = argv[i]; break; case 'l' : // -l LOG-FILE i ++; if (i >= argc) { puts("testpappl: Expected log file after '-l'."); return (usage(1)); } log = argv[i]; break; case 'L' : // -L LOG-LEVEL i ++; if (i >= argc) { puts("testpappl: Expected log level after '-L'."); return (usage(1)); } if (!strcmp(argv[i], "fatal")) { level = PAPPL_LOGLEVEL_FATAL; } else if (!strcmp(argv[i], "error")) { level = PAPPL_LOGLEVEL_ERROR; } else if (!strcmp(argv[i], "warn")) { level = PAPPL_LOGLEVEL_WARN; } else if (!strcmp(argv[i], "info")) { level = PAPPL_LOGLEVEL_INFO; } else if (!strcmp(argv[i], "debug")) { level = PAPPL_LOGLEVEL_DEBUG; } else { printf("testpappl: Unknown log level '%s'.\n", argv[i]); status = usage(1); goto done; } break; case 'm' : // -m DRIVER-NAME i ++; if (i >= argc) { puts("testpappl: Expected driver name after '-m'."); status = usage(1); goto done; } cupsArrayAdd(models, argv[i]); break; case 'o' : // -o OUTPUT-DIRECTORY i ++; if (i >= argc) { puts("testpappl: Expected output directory after '-o'."); status = usage(1); goto done; } outdir = argv[i]; break; case 'p' : // -p PORT-NUMBER i ++; if (i >= argc || atoi(argv[i]) <= 0 || atoi(argv[i]) > 32767) { puts("testpappl: Expected port number after '-p'."); status = usage(1); goto done; } port = atoi(argv[i]); break; case 't' : // -t TEST i ++; if (i >= argc) { puts("testpappl: Expected test name after '-t'."); status = usage(1); goto done; } if (!strcmp(argv[i], "all")) { // Add all tests cupsArrayAdd(testdata.names, "api"); cupsArrayAdd(testdata.names, "client"); cupsArrayAdd(testdata.names, "jpeg"); cupsArrayAdd(testdata.names, "png"); cupsArrayAdd(testdata.names, "pwg-raster"); cupsArrayAdd(testdata.names, "client-10x1000"); } else if (strchr(argv[i], ',')) { // Add comma-delimited tests char *start, // Start of current name *ptr; // Pointer into test names for (ptr = argv[i]; ptr;) { if (!*ptr) break; start = ptr; if ((ptr = strchr(ptr, ',')) != NULL) *ptr++ = '\0'; cupsArrayAdd(testdata.names, start); } } else { // Add a single test cupsArrayAdd(testdata.names, argv[i]); } break; case 'T' : // -T (TLS only) tls_only = true; break; case 'U' : // -U (USB printer gadget) soptions |= PAPPL_SOPTIONS_USB_PRINTER; break; default : printf("testpappl: Unknown option '-%c'.\n", *opt); status = usage(1); goto done; } } } else if (name) { printf("testpappl: Unexpected argument '%s'.\n", argv[i]); status = usage(1); goto done; } else { // "SERVER NAME" name = argv[i]; } } // Clean the log and output directory if necessary if (clean && log && strcmp(log, "-") && strcmp(log, "syslog")) unlink(log); if (clean && outdir && strcmp(outdir, ".")) { // Remove all PWG raster output files from output directory... cups_dir_t *dir; // Directory cups_dentry_t *dent; // Directory entry char *ext, // Extension on filename filename[1024]; // Filename if ((dir = cupsDirOpen(outdir)) != NULL) { while ((dent = cupsDirRead(dir)) != NULL) { // Only remove PWG raster files... if ((ext = strrchr(dent->filename, '.')) == NULL || strcmp(ext, ".pwg")) continue; // Remove this file... snprintf(filename, sizeof(filename), "%s/%s", outdir, dent->filename); unlink(filename); } cupsDirClose(dir); } } papplCopyString(output_directory, outdir, sizeof(output_directory)); // Initialize the system and any printers... system = papplSystemCreate(soptions, name ? name : "Test System", port, "_print,_universal", spool, log, level, auth, tls_only); papplSystemAddListeners(system, NULL); papplSystemAddTimerCallback(system, 0, _PAPPL_TIMER_INTERVAL, (pappl_timer_cb_t)timer_cb, &testdata); papplSystemSetEventCallback(system, event_cb, (void *)"testpappl"); papplSystemSetPrinterDrivers(system, (int)(sizeof(pwg_drivers) / sizeof(pwg_drivers[0])), pwg_drivers, pwg_autoadd, /* create_cb */NULL, pwg_callback, "testpappl"); papplSystemSetWiFiCallbacks(system, test_wifi_join_cb, test_wifi_list_cb, test_wifi_status_cb, (void *)"testpappl"); papplSystemAddLink(system, "Configuration", "/config", true); papplSystemSetFooterHTML(system, "Copyright © 2020-2025 by Michael R Sweet. " "Provided under the terms of the Apache License 2.0."); papplSystemSetNetworkCallbacks(system, test_network_get_cb, test_network_set_cb, (void *)"testnetwork"); papplSystemSetSaveCallback(system, (pappl_save_cb_t)papplSystemSaveState, (void *)"testpappl.state"); papplSystemSetVersions(system, (int)(sizeof(versions) / sizeof(versions[0])), versions); papplSystemAddStringsData(system, "/en.strings", "en", "\"/\" = \"This is a localized header for the system home page.\";\n\"/network\" = \"This is a localized header for the network configuration page.\";\n\"/printing\" = \"This is a localized header for all printing defaults pages.\";\n\"/Label_Printer/printing\" = \"This is a localized header for the label printer defaults page.\";\n"); mkdir(outdir, 0777); httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "file", NULL, NULL, 0, "%s?ext=pwg", realpath(outdir, outdirname)); if (clean || !papplSystemLoadState(system, "testpappl.state")) { papplSystemSetContact(system, &contact); papplSystemSetDNSSDName(system, name ? name : "Test System"); papplSystemSetGeoLocation(system, "geo:46.4707,-80.9961"); papplSystemSetLocation(system, "Test Lab 42"); papplSystemSetOrganization(system, "Lakeside Robotics"); if (cupsArrayGetCount(models)) { for (model = (const char *)cupsArrayGetFirst(models), i = 1; model; model = (const char *)cupsArrayGetNext(models), i ++) { char pname[128]; // Printer name if (cupsArrayGetCount(models) == 1) snprintf(pname, sizeof(pname), "%s", name ? name : "Test Printer"); else snprintf(pname, sizeof(pname), "%s %d", name ? name : "Test Printer", i); printer = papplPrinterCreate(system, /* printer_id */0, pname, model, "MFG:PWG;MDL:Test Printer;", device_uri); papplPrinterSetContact(printer, &contact); papplPrinterSetDNSSDName(printer, pname); papplPrinterSetGeoLocation(printer, "geo:46.4707,-80.9961"); papplPrinterSetLocation(printer, "Test Lab 42"); papplPrinterSetOrganization(printer, "Lakeside Robotics"); } } else { printer = papplPrinterCreate(system, /* printer_id */0, "Office Printer", "pwg_common-300dpi-600dpi-srgb_8", "MFG:PWG;MDL:Office Printer;", device_uri); papplPrinterSetContact(printer, &contact); papplPrinterSetDNSSDName(printer, "Office Printer"); papplPrinterSetGeoLocation(printer, "geo:46.4707,-80.9961"); papplPrinterSetLocation(printer, "Test Lab 42"); papplPrinterSetOrganization(printer, "Lakeside Robotics"); papplPrinterSetMaxPreservedJobs(printer, 3); if (soptions & PAPPL_SOPTIONS_MULTI_QUEUE) { printer = papplPrinterCreate(system, /* printer_id */0, "Label Printer", "pwg_4inch-203dpi-black_1", "MFG:PWG;MDL:Label Printer;", device_uri); papplPrinterSetContact(printer, &contact); papplPrinterSetDNSSDName(printer, "Label Printer"); // Not setting geo-location for label printer to ensure that DNS-SD works without a LOC record... papplPrinterSetLocation(printer, "Test Lab 42"); papplPrinterSetOrganization(printer, "Lakeside Robotics"); } } } // Run any test(s)... if (cupsArrayGetCount(testdata.names)) { testdata.outdirname = outdirname; testdata.system = system; if (cupsArrayGetCount(testdata.names) == 1 && !strcmp((char *)cupsArrayGetFirst(testdata.names), "api")) { // Running API test alone does not start system... testdata.waitsystem = false; status = run_tests(&testdata) != NULL; goto done; } testdata.waitsystem = true; if (pthread_create(&testid, NULL, (void *(*)(void *))run_tests, &testdata)) { perror("Unable to start testing thread"); status = 1; goto done; } } // Run the system... #ifdef __APPLE__ // TODO: Implement private/public API for running with UI // macOS requires UI code to run on the main thread, so put the system in a // background thread... if (pthread_create(&sysid, NULL, (void *(*)(void *))papplSystemRun, system)) { perror("Unable to create system thread"); status = 1; goto done; } while (!papplSystemIsRunning(system)) sleep(1); _papplSystemStatusUI(system); while (!_papplSystemIsShutdownNoLock(system)) sleep(1); pthread_join(sysid, &ret); #else // All other platforms run the system on the main thread... papplSystemRun(system); #endif // __APPLE__ if (testid) { pthread_join(testid, &ret); status = ret != NULL; } done: // Free memory before exiting to make ASAN happy on Linux... cupsArrayDelete(testdata.names); cupsArrayDelete(models); return (status); } // // 'connect_to_printer()' - Connect to the system and return the printer URI. // static http_t * // O - HTTP connection connect_to_printer( pappl_system_t *system, // I - System bool remote, // I - Remote connection char *uri, // I - URI buffer size_t urisize) // I - Size of URI buffer { char host[1024]; // Hostname if (remote) papplSystemGetHostName(system, host, sizeof(host)); else papplCopyString(host, "localhost", sizeof(host)); httpAssembleURI(HTTP_URI_CODING_ALL, uri, (cups_len_t)urisize, "ipp", NULL, host, papplSystemGetHostPort(system), "/ipp/print"); return (httpConnect(host, papplSystemGetHostPort(system), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL)); } // // 'device_error_cb()' - Show a device error message. // static void device_error_cb(const char *message, // I - Error message void *err_data) // I - Callback data (unused) { (void)err_data; printf("testpappl: %s\n", message); } // // 'device_list_cb()' - List a device. // static bool // O - `true` to stop, `false` to continue device_list_cb(const char *device_info, // I - Device description const char *device_uri, // I - Device URI const char *device_id, // I - IEEE-1284 device ID void *data) // I - Callback data (unused) { (void)data; printf("%s\n %s\n %s\n", device_info, device_uri, device_id); return (false); } // // 'do_ps_query()' - Try doing a simple PostScript device query. // static int // O - Exit status do_ps_query(const char *device_uri) // I - Device URI { pappl_device_t *device; // Connection to device char buffer[8192]; // Read buffer ssize_t bytes; // Bytes read if ((device = papplDeviceOpen(device_uri, "ps-query", device_error_cb, NULL)) == NULL) return (1); papplDevicePuts(device, "\033%-12345X%!\nproduct print\n"); papplDeviceFlush(device); if ((bytes = papplDeviceRead(device, buffer, sizeof(buffer) - 1)) > 0) { buffer[bytes] = '\0'; puts(buffer); } else { puts("<>"); } papplDeviceClose(device); return (0); } // // 'event_cb()' - Accumulate events. // void event_cb(pappl_system_t *system, // I - System pappl_printer_t *printer, // I - Printer, if any pappl_job_t *job, // I - Job, if any pappl_event_t event, // I - Event void *data) // I - Callback data { // fprintf(stderr, "event_cb: system=%p, printer=%p, job=%p, event=%08x, data=%p\n", system, printer, job, event, data); if (!data || strcmp((char *)data, "testpappl")) { fputs("testpappl: Bad event callback data.\n", stderr); exit(1); } if (!system) { fputs("testpappl: Bad system for event callback.\n", stderr); exit(1); } if ((event & PAPPL_EVENT_JOB_ALL) && !job) { fputs("testpappl: Missing job for event callback.\n", stderr); exit(1); } if ((event & PAPPL_EVENT_PRINTER_ALL) && !printer) { fputs("testpappl: Missing printer for event callback.\n", stderr); exit(1); } event_count ++; event_mask |= event; } // // 'make_raster_file()' - Create a temporary PWG raster file. // // Note: Adapted from CUPS "testclient.c"... // static const char * // O - Print filename make_raster_file(ipp_t *response, // I - Printer attributes bool grayscale, // I - Force grayscale? char *tempname, // I - Temporary filename buffer size_t tempsize) // I - Size of temp file buffer { cups_len_t i, // Looping var count; // Number of values ipp_attribute_t *attr; // Printer attribute const char *type = NULL; // Raster type (colorspace + bits) pwg_media_t *media = NULL; // Media size int xdpi = 0, // Horizontal resolution ydpi = 0; // Vertical resolution int fd; // Temporary file cups_raster_t *ras; // Raster stream cups_page_header_t header; // Page header unsigned char *line, // Line of raster data *lineptr; // Pointer into line unsigned y, // Current position on page xcount, ycount, // Current count for X and Y xrep, yrep, // Repeat count for X and Y xoff, yoff, // Offsets for X and Y yend; // End Y value int temprow, // Row in template tempcolor; // Template color const char *template; // Pointer into template const unsigned char *color; // Current color static const unsigned char colors[][3] = { // Colors for test { 191, 191, 191 }, { 127, 127, 127 }, { 63, 63, 63 }, { 0, 0, 0 }, { 255, 0, 0 }, { 255, 127, 0 }, { 255, 255, 0 }, { 127, 255, 0 }, { 0, 255, 0 }, { 0, 255, 127 }, { 0, 255, 255 }, { 0, 127, 255 }, { 0, 0, 255 }, { 127, 0, 255 }, { 255, 0, 255 } }; static const char * const templates[] = { // Raster template "PPPP A PPPP PPPP L TTTTT EEEEE SSS TTTTT 000 1 222 333 4 55555 66 77777 888 999 ", "P P A A P P P P L T E S S T 0 0 11 2 2 3 3 4 4 5 6 7 8 8 9 9 ", "P P A A P P P P L T E S T 0 0 1 2 3 4 4 5 6 7 8 8 9 9 ", "PPPP AAAAA PPPP PPPP L T EEEE SSS T 0 0 0 1 22 333 44444 555 6666 7 888 9999 ", "P A A P P L T E S T 0 0 1 2 3 4 5 6 6 7 8 8 9 ", "P A A P P L T E S S T 0 0 1 2 3 3 4 5 5 6 6 7 8 8 9 ", "P A A P P LLLLL T EEEEE SSS T 000 111 22222 333 4 555 666 7 888 99 ", " " }; // Figure out the the media, resolution, and color mode... if ((attr = ippFindAttribute(response, "media-ready", IPP_TAG_KEYWORD)) != NULL) { // Use ready media... if (ippContainsString(attr, "na_letter_8.5x11in")) media = pwgMediaForPWG("na_letter_8.5x11in"); else if (ippContainsString(attr, "iso_a4_210x297mm")) media = pwgMediaForPWG("iso_a4_210x297mm"); else media = pwgMediaForPWG(ippGetString(attr, 0, NULL)); } else if ((attr = ippFindAttribute(response, "media-default", IPP_TAG_KEYWORD)) != NULL) { // Use default media... media = pwgMediaForPWG(ippGetString(attr, 0, NULL)); } else { testEndMessage(false, "no default or ready media reported by printer"); return (NULL); } if ((attr = ippFindAttribute(response, "pwg-raster-document-resolution-supported", IPP_TAG_RESOLUTION)) != NULL) { for (i = 0, count = ippGetCount(attr); i < count; i ++) { int tempxdpi, tempydpi; ipp_res_t tempunits; tempxdpi = ippGetResolution(attr, 0, &tempydpi, &tempunits); if (i == 0 || tempxdpi < xdpi || tempydpi < ydpi) { xdpi = tempxdpi; ydpi = tempydpi; } } if ((attr = ippFindAttribute(response, "pwg-raster-document-type-supported", IPP_TAG_KEYWORD)) != NULL) { if (!grayscale && ippContainsString(attr, "srgb_8")) type = "srgb_8"; else if (ippContainsString(attr, "sgray_8")) type = "sgray_8"; } } if (xdpi < 72 || ydpi < 72) { testEndMessage(false, "no supported raster resolutions"); return (NULL); } if (!type) { testEndMessage(false, "no supported color spaces or bit depths"); return (NULL); } // Make the raster context and details... #if CUPS_VERSION_MAJOR < 3 && CUPS_VERSION_MINOR < 5 if (!cupsRasterInitPWGHeader(&header, media, type, xdpi, ydpi, "one-sided", NULL)) { testEndMessage(false, "unable to initialize raster context: %s", cupsRasterGetErrorString()); return (NULL); } #else // CUPS 2.5/CUPS 3.0+ cups_media_t cups_media; // CUPS media information memset(&cups_media, 0, sizeof(cups_media)); papplCopyString(cups_media.media, media->pwg, sizeof(cups_media.media)); cups_media.width = media->width; cups_media.length = media->length; if (!cupsRasterInitHeader(&header, &cups_media, /*optimize*/NULL, IPP_QUALITY_NORMAL, /*intent*/NULL, IPP_ORIENT_PORTRAIT, "one-sided", type, xdpi, ydpi, /*sheet_back*/NULL)) { testEndMessage(false, "unable to initialize raster context: %s", cupsRasterGetErrorString()); return (NULL); } #endif // CUPS_VERSION_MAJOR < 3 header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount] = 1; if (header.cupsWidth > (2 * header.HWResolution[0])) { xoff = header.HWResolution[0] / 2; yoff = header.HWResolution[1] / 2; } else { xoff = header.HWResolution[0] / 4; yoff = header.HWResolution[1] / 4; } xrep = (header.cupsWidth - 2 * xoff) / 140; yrep = xrep * header.HWResolution[1] / header.HWResolution[0]; yend = header.cupsHeight - yoff; // Prepare the raster file... if ((line = malloc(header.cupsBytesPerLine)) == NULL) { testEndMessage(false, "unable to allocate %u bytes for raster output: %s", header.cupsBytesPerLine, strerror(errno)); return (NULL); } if ((fd = cupsCreateTempFd(NULL, NULL, tempname, (cups_len_t)tempsize)) < 0) { testEndMessage(false, "unable to create temporary print file: %s", strerror(errno)); free(line); return (NULL); } if ((ras = cupsRasterOpen(fd, CUPS_RASTER_WRITE_PWG)) == NULL) { testEndMessage(false, "unable to open raster stream: %s", cupsRasterGetErrorString()); close(fd); free(line); return (NULL); } // Write a single page consisting of the template dots repeated over the page. cupsRasterWriteHeader(ras, &header); memset(line, 0xff, header.cupsBytesPerLine); for (y = 0; y < yoff; y ++) cupsRasterWritePixels(ras, line, header.cupsBytesPerLine); for (temprow = 0, tempcolor = 0; y < yend;) { template = templates[temprow]; color = colors[tempcolor]; temprow ++; if (temprow >= (int)(sizeof(templates) / sizeof(templates[0]))) { temprow = 0; tempcolor ++; if (tempcolor >= (int)(sizeof(colors) / sizeof(colors[0]))) tempcolor = 0; else if (tempcolor > 3 && header.cupsColorSpace == CUPS_CSPACE_SW) tempcolor = 0; } memset(line, 0xff, header.cupsBytesPerLine); if (header.cupsColorSpace == CUPS_CSPACE_SW) { // Do grayscale output... for (lineptr = line + xoff; *template; template ++) { if (*template != ' ') { for (xcount = xrep; xcount > 0; xcount --) *lineptr++ = *color; } else { lineptr += xrep; } } } else { // Do color output... for (lineptr = line + 3 * xoff; *template; template ++) { if (*template != ' ') { for (xcount = xrep; xcount > 0; xcount --, lineptr += 3) memcpy(lineptr, color, 3); } else { lineptr += 3 * xrep; } } } for (ycount = yrep; ycount > 0 && y < yend; ycount --, y ++) cupsRasterWritePixels(ras, line, header.cupsBytesPerLine); } memset(line, 0xff, header.cupsBytesPerLine); for (y = 0; y < header.cupsHeight; y ++) cupsRasterWritePixels(ras, line, header.cupsBytesPerLine); free(line); cupsRasterClose(ras); return (tempname); } // // 'run_tests()' - Run named tests. // static void * // O - Thread status run_tests(_pappl_testdata_t *testdata) // I - Testing data { const char *name; // Test name void *ret = NULL; // Return thread status time_t curtime; // Current time int expected; // Expected timer count cups_dir_t *dir; // Output directory cups_dentry_t *dent; // Output file int files = 0; // Total file count off_t total = 0; // Total output size #ifdef HAVE_LIBJPEG static const char * const jpeg_files[] = { // List of JPEG files to print "portrait-gray.jpg", "portrait-color.jpg", "landscape-gray.jpg", "landscape-color.jpg" }; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG static const char * const png_files[] = { // List of PNG files to print "portrait-gray.png", "portrait-color.png", "landscape-gray.png", "landscape-color.png" }; #endif // HAVE_LIBPNG testMessage("Starting tests..."); if (testdata->waitsystem) { // Wait for the system to start... while (!papplSystemIsRunning(testdata->system)) sleep(1); } // Run each test... for (name = (const char *)cupsArrayGetFirst(testdata->names); name && !ret && (!papplSystemIsShutdown(testdata->system) || !testdata->waitsystem); name = (const char *)cupsArrayGetNext(testdata->names)) { if (!strcmp(name, "api")) { if (!test_api(testdata->system)) ret = (void *)1; } else if (!strcmp(name, "client")) { if (!test_client(testdata->system)) ret = (void *)1; } else if (!strncmp(name, "client-", 7)) { if (!test_client_max(testdata->system, name)) ret = (void *)1; } #ifdef HAVE_LIBJPEG else if (!strcmp(name, "jpeg")) { if (!test_image_files(testdata->system, "jpeg", "image/jpeg", (int)(sizeof(jpeg_files) / sizeof(jpeg_files[0])), jpeg_files)) ret = (void *)1; } #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG else if (!strcmp(name, "png")) { if (!test_image_files(testdata->system, "png", "image/png", (int)(sizeof(png_files) / sizeof(png_files[0])), png_files)) ret = (void *)1; } #endif // HAVE_LIBPNG else if (!strcmp(name, "pwg-raster")) { if (!test_pwg_raster(testdata->system)) ret = (void *)1; } else { testBegin("%s", name); testEndMessage(false, "unknown test"); ret = (void *)1; } } if (name) { do { printf("%s: SKIP\n", name); #ifndef DEBUG if (!isatty(2)) fprintf(stderr, "%s: SKIP\n", name); #endif // !DEBUG } while ((name = (const char *)cupsArrayGetNext(testdata->names)) != NULL); } if (!ret && cupsArrayFind(testdata->names, (void *)"api")) { // papplSystemSetEventCallback testBegin("api: papplSystemSetEventCallback"); if (event_count > 0 && event_mask == (PAPPL_EVENT_SYSTEM_CONFIG_CHANGED | PAPPL_EVENT_PRINTER_CREATED | PAPPL_EVENT_PRINTER_DELETED | PAPPL_EVENT_PRINTER_CONFIG_CHANGED | PAPPL_EVENT_PRINTER_STATE_CHANGED | PAPPL_EVENT_JOB_COMPLETED | PAPPL_EVENT_JOB_CREATED | PAPPL_EVENT_JOB_PROGRESS | PAPPL_EVENT_JOB_STATE_CHANGED)) { testEndMessage(true, "count=%lu", (unsigned long)event_count); } else { int i; // Looping var pappl_event_t event; // Current event static const char * const events[31] = { // IPP "notify-events" strings for bits "document-completed", "document-config-changed", "document-created", "document-fetchable", "document-state-changed", "document-stopped", "job-completed", "job-config-changed", "job-created", "job-fetchable", "job-progress", "job-state-changed", "job-stopped", "printer-config-changed", "printer-finishings-changed", "printer-media-changed", "printer-queue-order-changed", "printer-restarted", "printer-shutdown", "printer-state-changed", "printer-stopped", "resource-canceled", "resource-config-changed", "resource-created", "resource-installed", "resource-changed", "printer-created", "printer-deleted", "system-config-changed", "system-state-changed", "system-stopped" }; testEndMessage(false, "count=%lu", (unsigned long)event_count); ret = (void *)1; if (event_mask == PAPPL_EVENT_NONE) { testError("api: No events captured."); } else { for (i = 0, event = PAPPL_EVENT_DOCUMENT_COMPLETED; event <= PAPPL_EVENT_SYSTEM_STOPPED; i ++, event *= 2) { if (event_mask & event) testError("api: Got notify-event='%s'", events[i]); } } } // papplSystemAddTimerCallback testBegin("api: papplSystemAddTimerCallback"); curtime = time(NULL); expected = (int)((curtime - testdata->timer_start + _PAPPL_TIMER_INTERVAL - 1) / _PAPPL_TIMER_INTERVAL); if (expected > _PAPPL_MAX_TIMER_COUNT) expected = _PAPPL_MAX_TIMER_COUNT; if (testdata->timer_count == 0 || testdata->timer_count > _PAPPL_MAX_TIMER_COUNT || abs(expected - testdata->timer_count) > 1) { int i; // Looping var testEndMessage(false, "timer_count=%d, expected=%d", testdata->timer_count, expected); for (i = 1; i < testdata->timer_count; i ++) testMessage("timer@%ld (%ld seconds)", (long)testdata->timer_times[i], (long)(testdata->timer_times[i] - testdata->timer_times[i - 1])); ret = (void *)1; } else { testEndMessage(true, "timer_count=%d", testdata->timer_count); } } // Summarize results... if ((dir = cupsDirOpen(testdata->outdirname)) != NULL) { while ((dent = cupsDirRead(dir)) != NULL) { if (!S_ISDIR(dent->fileinfo.st_mode)) { files ++; total += dent->fileinfo.st_size; } } cupsDirClose(dir); } papplSystemShutdown(testdata->system); if (files != output_count) ret = (void *)1; if (ret) printf("\nFAILED: %d of %d output file(s), %.1fMB\n", files, output_count, total / 1048576.0); else printf("\nPASSED: %d of %d output file(s), %.1fMB\n", files, output_count, total / 1048576.0); all_tests_done = true; return (ret); } // // 'strcopy_cb()' - Copy a string for an array. // static char * // O - New string strcopy_cb(const char *s, // I - String void *data) // I - Callback data (unused) { (void)data; return (strdup(s)); } // // 'strfree_cb()' - Free a string from an array. // static void strfree_cb(char *s, // I - String void *data) // I - Callback data (unused) { (void)data; free(s); } // // 'test_api()' - Run API unit tests. // static bool // O - `true` on success, `false` on failure test_api(pappl_system_t *system) // I - System { bool pass = true; // Pass/fail state int i, j; // Looping vars pappl_contact_t get_contact, // Contact for "get" call set_contact; // Contact for ", set" call int get_int, // Integer for "get" call set_int; // Integer for ", set" call char get_str[1024], // Temporary string for "get" call set_str[1024]; // Temporary string for ", set" call int get_nvers; // Number of versions for "get" call pappl_version_t get_vers[10], // Versions for "get" call set_vers[10]; // Versions for ", set" call const char *get_value; // Value for "get" call pappl_loglevel_t get_loglevel, // Log level for "get" call set_loglevel; // Log level for ", set" call size_t get_size, // Size for "get" call set_size; // Size for ", set" call pappl_printer_t *printer; // Current printer pappl_loc_t *loc; // Current localization _pappl_testprinter_t pdata; // Printer test data const char *key = "A printer with that name already exists.", // Key string *text; // Localized text static const char * const languages[] = { "de", "en", "es", "fr", "it", "ja" }; static const char * const set_locations[10][2] = { // Some wonders of the ancient world (all north-eastern portion of globe...) { "Great Pyramid of Giza", "geo:29.979175,31.134358" }, { "Temple of Artemis at Ephesus", "geo:37.949722,27.363889" }, { "Statue of Zeus at Olympia", "geo:37.637861,21.63" }, { "Colossus of Rhodes", "geo:36.451111,28.227778" }, { "Lighthouse of Alexandria", "geo:31.213889,29.885556" }, // Other places { "Niagara Falls", "geo:43.0828201,-79.0763516" }, { "Grand Canyon", "geo:36.0545936,-112.2307085" }, { "Christ the Redeemer", "geo:-22.9691208,-43.2583044" }, { "Great Barrier Reef", "geo:-16.7546653,143.8322946" }, { "Science North", "geo:46.4707,-80.9961" } }; static const char * const set_loglevels[] = { // Log level constants "UNSPEC", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" }; for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++) { // papplSystemFindLoc testBegin("api: papplSystemFindLoc('%s')", languages[i]); if ((loc = papplSystemFindLoc(system, languages[i])) == NULL) { testEnd(false); pass = false; } else testEnd(true); // papplLocGetString testBegin("api: papplLocGetString('%s')", key); if ((text = papplLocGetString(loc, key)) == NULL || text == key) { testEndMessage(false, "got %p", text); pass = false; } else if (!strcmp(key, text) && strcmp(languages[i], "en")) { testEndMessage(false, "not localized"); pass = false; } else testEndMessage(true, "got '%s'", text); } // papplSystemFindLoc testBegin("api: papplSystemFindLoc('zz')"); if ((loc = papplSystemFindLoc(system, "zz")) != NULL) { testEndMessage(false, "got %p", loc); pass = false; } else testEndMessage(true, "got NULL"); // papplLocGetString testBegin("api: papplLocGetString('%s')", key); if ((text = papplLocGetString(loc, key)) != key) { testEndMessage(false, "got %p", text); pass = false; } else testEndMessage(true, "got key string"); // papplSystemGet/SetAdminGroup testBegin("api: papplSystemGetAdminGroup"); if (papplSystemGetAdminGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "admin-%d", i); testBegin("api: papplSystemGet/SetAdminGroup('%s')", set_str); papplSystemSetAdminGroup(system, set_str); if (!papplSystemGetAdminGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetAdminGroup(NULL)"); papplSystemSetAdminGroup(system, NULL); if (papplSystemGetAdminGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetContact testBegin("api: papplSystemGetContact"); if (!papplSystemGetContact(system, &get_contact)) { testEndMessage(false, "got NULL, expected 'Michael R Sweet'"); pass = false; } else if (strcmp(get_contact.name, "Michael R Sweet")) { testEndMessage(false, "got '%s', expected 'Michael R Sweet'", get_contact.name); pass = false; } else if (strcmp(get_contact.email, "msweet@example.org")) { testEndMessage(false, "got '%s', expected 'msweet@example.org'", get_contact.email); pass = false; } else if (strcmp(get_contact.telephone, "+1-705-555-1212")) { testEndMessage(false, "got '%s', expected '+1-705-555-1212'", get_contact.telephone); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_contact.name, sizeof(set_contact.name), "Admin %d", i); snprintf(set_contact.email, sizeof(set_contact.email), "admin-%d@example.org", i); snprintf(set_contact.telephone, sizeof(set_contact.telephone), "+1-705-555-%04d", i * 1111); testBegin("api: papplSystemGet/SetContact('%s')", set_contact.name); papplSystemSetContact(system, &set_contact); if (!papplSystemGetContact(system, &get_contact)) { testEndMessage(false, "got NULL, expected '%s'", set_contact.name); pass = false; } else if (strcmp(get_contact.name, set_contact.name)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.name, set_contact.name); pass = false; } else if (strcmp(get_contact.email, set_contact.email)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.email, set_contact.email); pass = false; } else if (strcmp(get_contact.telephone, set_contact.telephone)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.telephone, set_contact.telephone); pass = false; } else testEnd(true); } // papplSystemGet/SetDefaultPrinterID testBegin("api: papplSystemGetDefaultPrinterID"); if ((get_int = papplSystemGetDefaultPrinterID(system)) == 0) { testEndMessage(false, "got 0, expected > 0"); pass = false; } else testEndMessage(true, "%d", get_int); for (set_int = 2; set_int >= 1; set_int --) { testBegin("api: papplSystemSetDefaultPrinterID(%d)", set_int); papplSystemSetDefaultPrinterID(system, set_int); if ((get_int = papplSystemGetDefaultPrinterID(system)) != set_int) { testEndMessage(false, "got %d, expected %d", get_int, set_int); pass = false; } else testEnd(true); } // papplSystemGet/SetDefaultPrintGroup testBegin("api: papplSystemGetDefaultPrintGroup"); if (papplSystemGetDefaultPrintGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "users-%d", i); testBegin("api: papplSystemGet/SetDefaultPrintGroup('%s')", set_str); papplSystemSetDefaultPrintGroup(system, set_str); if (!papplSystemGetDefaultPrintGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetDefaultPrintGroup(NULL)"); papplSystemSetDefaultPrintGroup(system, NULL); if (papplSystemGetDefaultPrintGroup(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetDNSSDName testBegin("api: papplSystemGetDNSSDName"); if (!papplSystemGetDNSSDName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'Test System'"); pass = false; } else if (strcmp(get_str, "Test System")) { testEndMessage(false, "got '%s', expected 'Test System'", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "System Test %c", i + 'A'); testBegin("api: papplSystemGet/SetDNSSDName('%s')", set_str); papplSystemSetDNSSDName(system, set_str); if (!papplSystemGetDNSSDName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetDNSSDName(NULL)"); papplSystemSetDNSSDName(system, NULL); if (papplSystemGetDNSSDName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetFooterHTML testBegin("api: papplSystemGetFooterHTML"); if ((get_value = papplSystemGetFooterHTML(system)) == NULL) { testEndMessage(false, "got NULL, expected 'Copyright ...'"); pass = false; } else if (strncmp(get_value, "Copyright © 202", 20)) { testEndMessage(false, "got '%s', expected 'Copyright ...'", get_value); pass = false; } else testEnd(true); testBegin("api: papplSystemSetFooterHTML('Mike wuz here.')"); papplSystemSetFooterHTML(system, "Mike wuz here."); if ((get_value = papplSystemGetFooterHTML(system)) == NULL) { testEndMessage(false, "got NULL, expected 'Mike wuz here.'"); pass = false; } else if (papplSystemIsRunning(system)) { // System is running so we can't change the footer text anymore... if (strncmp(get_value, "Copyright © 202", 20)) { testEndMessage(false, "got '%s', expected 'Copyright ...'", get_value); pass = false; } else testEnd(true); } else { // System is not running so we can change the footer text... if (strcmp(get_value, "Mike wuz here.")) { testEndMessage(false, "got '%s', expected 'Mike wuz here.'", get_value); pass = false; } else testEnd(true); } // papplSystemGet/SetGeoLocation testBegin("api: papplSystemGetGeoLocation"); if (!papplSystemGetGeoLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'geo:46.4707,-80.9961'"); pass = false; } else if (strcmp(get_str, "geo:46.4707,-80.9961")) { testEndMessage(false, "got '%s', expected 'geo:46.4707,-80.9961'", get_str); pass = false; } else testEnd(true); testBegin("api: papplSystemGet/SetGeoLocation('bad-value')"); papplSystemSetGeoLocation(system, "bad-value"); if (!papplSystemGetGeoLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'geo:46.4707,-80.9961'"); pass = false; } else if (strcmp(get_str, "geo:46.4707,-80.9961")) { testEndMessage(false, "got '%s', expected 'geo:46.4707,-80.9961'", get_str); pass = false; } else testEnd(true); for (i = 0; i < (int)(sizeof(set_locations) / sizeof(set_locations[0])); i ++) { testBegin("api: papplSystemGet/SetGeoLocation('%s')", set_locations[i][1]); papplSystemSetGeoLocation(system, set_locations[i][1]); if (!papplSystemGetGeoLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_locations[i][1]); pass = false; } else if (strcmp(get_str, set_locations[i][1])) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_locations[i][1]); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetGeoLocation(NULL)"); papplSystemSetGeoLocation(system, NULL); if (papplSystemGetGeoLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetHostname testBegin("api: papplSystemGetHostname"); if (!papplSystemGetHostName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '*.domain'"); pass = false; } else if (!strchr(get_str, '.')) { testEndMessage(false, "got '%s', expected '*.domain'", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "example%d.org", i); testBegin("api: papplSystemGet/SetHostname('%s')", set_str); papplSystemSetHostName(system, set_str); if (!papplSystemGetHostName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetHostName(NULL)"); papplSystemSetHostName(system, NULL); if (!papplSystemGetHostName(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '*.domain'"); pass = false; } else if (!strchr(get_str, '.')) { testEndMessage(false, "got '%s', expected '*.domain'", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetLocation testBegin("api: papplSystemGetLocation"); if (!papplSystemGetLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'Test Lab 42'"); pass = false; } else if (strcmp(get_str, "Test Lab 42")) { testEndMessage(false, "got '%s', expected 'Test Lab 42'", get_str); pass = false; } else testEnd(true); for (i = 0; i < (int)(sizeof(set_locations) / sizeof(set_locations[0])); i ++) { testBegin("api: papplSystemGet/SetLocation('%s')", set_locations[i][0]); papplSystemSetLocation(system, set_locations[i][0]); if (!papplSystemGetLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_locations[i][0]); pass = false; } else if (strcmp(get_str, set_locations[i][0])) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_locations[i][0]); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetLocation(NULL)"); papplSystemSetLocation(system, NULL); if (papplSystemGetLocation(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetLogLevel testBegin("api: papplSystemGetLogLevel"); if (papplSystemGetLogLevel(system) == PAPPL_LOGLEVEL_UNSPEC) { testEndMessage(false, "got PAPPL_LOGLEVEL_UNSPEC, expected another PAPPL_LOGLEVEL_ value"); pass = false; } else testEnd(true); for (set_loglevel = PAPPL_LOGLEVEL_FATAL; set_loglevel >= PAPPL_LOGLEVEL_DEBUG; set_loglevel --) { testBegin("api: papplSystemSetLogLevel(PAPPL_LOGLEVEL_%s)", set_loglevels[set_loglevel + 1]); papplSystemSetLogLevel(system, set_loglevel); if ((get_loglevel = papplSystemGetLogLevel(system)) != set_loglevel) { testEndMessage(false, "got PAPPL_LOGLEVEL_%s, expected PAPPL_LOGLEVEL_%s", set_loglevels[get_loglevel + 1], set_loglevels[set_loglevel + 1]); pass = false; } else testEnd(true); } // papplSystemGet/SetMaxLogSize testBegin("api: papplSystemGetMaxLogSize"); if ((get_size = papplSystemGetMaxLogSize(system)) != (size_t)(1024 * 1024)) { testEndMessage(false, "got %ld, expected %ld", (long)get_size, (long)(1024 * 1024)); pass = false; } else testEnd(true); for (set_size = 0; set_size <= (16 * 1024 * 1024); set_size += 1024 * 1024) { testBegin("api: papplSystemSetMaxLogSize(%ld)", (long)set_size); papplSystemSetMaxLogSize(system, set_size); if ((get_size = papplSystemGetMaxLogSize(system)) != set_size) { testEndMessage(false, "got %ld, expected %ld", (long)get_size, (long)set_size); pass = false; } else testEnd(true); } testBegin("api: papplSystemSetMaxLogSize(0)"); papplSystemSetMaxLogSize(system, 0); if ((get_size = papplSystemGetMaxLogSize(system)) != 0) { testEndMessage(false, "got %ld, expected 0", (long)get_size); pass = false; } else testEnd(true); // papplSystemGet/SetNextPrinterID testBegin("api: papplSystemGetNextPrinterID"); if ((get_int = papplSystemGetNextPrinterID(system)) != 3) { testEndMessage(false, "got %d, expected 3", get_int); pass = false; } else testEnd(true); set_int = (papplGetRand() % 1000000) + 4; testBegin("api: papplSystemSetNextPrinterID(%d)", set_int); papplSystemSetNextPrinterID(system, set_int); if ((get_int = papplSystemGetNextPrinterID(system)) != set_int) { if (papplSystemIsRunning(system)) testEnd(true); else { testEndMessage(false, "got %d, expected %d", get_int, set_int); pass = false; } } else testEnd(true); // papplSystemGet/SetOrganization testBegin("api: papplSystemGetOrganization"); if (!papplSystemGetOrganization(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'Lakeside Robotics'"); pass = false; } else if (strcmp(get_str, "Lakeside Robotics")) { testEndMessage(false, "got '%s', expected 'Lakeside Robotics'", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "Organization %c", i + 'A'); testBegin("api: papplSystemGet/SetOrganization('%s')", set_str); papplSystemSetOrganization(system, set_str); if (!papplSystemGetOrganization(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetOrganization(NULL)"); papplSystemSetOrganization(system, NULL); if (papplSystemGetOrganization(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetOrganizationalUnit testBegin("api: papplSystemGetOrganizationalUnit"); if (papplSystemGetOrganizationalUnit(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "%c Team", i + 'A'); testBegin("api: papplSystemGet/SetOrganizationalUnit('%s')", set_str); papplSystemSetOrganizationalUnit(system, set_str); if (!papplSystemGetOrganizationalUnit(system, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetOrganizationalUnit(NULL)"); papplSystemSetOrganizationalUnit(system, NULL); if (papplSystemGetOrganizationalUnit(system, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplSystemGet/SetUUID testBegin("api: papplSystemGetUUID"); if ((get_value = papplSystemGetUUID(system)) == NULL) { testEndMessage(false, "got NULL, expected 'urn:uuid:...'"); pass = false; } else if (strncmp(get_value, "urn:uuid:", 9)) { testEndMessage(false, "got '%s', expected 'urn:uuid:...'", get_value); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "urn:uuid:%04x%04x-%04x-%04x-%04x-%04x%04x%04x", (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536), (unsigned)(papplGetRand() % 65536)); testBegin("api: papplSystemGet/SetUUID('%s')", set_str); papplSystemSetUUID(system, set_str); if ((get_value = papplSystemGetUUID(system)) == NULL) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (papplSystemIsRunning(system)) { if (!strcmp(get_value, set_str) || strncmp(get_value, "urn:uuid:", 9)) { testEndMessage(false, "got '%s', expected different 'urn:uuid:...'", get_value); pass = false; } else testEnd(true); } else if (strcmp(get_value, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_value, set_str); pass = false; } else testEnd(true); } testBegin("api: papplSystemGet/SetUUID(NULL)"); if ((get_value = papplSystemGetUUID(system)) == NULL) { testEndMessage(false, "unable to get current UUID"); pass = false; } else { papplCopyString(get_str, get_value, sizeof(get_str)); papplSystemSetUUID(system, NULL); if ((get_value = papplSystemGetUUID(system)) == NULL) { testEndMessage(false, "got NULL, expected 'urn:uuid:...'"); pass = false; } else if (papplSystemIsRunning(system)) { if (!strcmp(get_value, set_str) || strncmp(get_value, "urn:uuid:", 9)) { testEndMessage(false, "got '%s', expected different 'urn:uuid:...'", get_value); pass = false; } else testEnd(true); } else if (!strcmp(get_value, set_str)) { testEndMessage(false, "got '%s', expected different '%s'", get_value, set_str); pass = false; } else testEnd(true); } // papplSystemGet/SetVersions testBegin("api: papplSystemGetVersions"); if ((get_nvers = papplSystemGetVersions(system, (int)(sizeof(get_vers) / sizeof(get_vers[0])), get_vers)) != 1) { testEndMessage(false, "got %d versions, expected 1", get_nvers); pass = false; } else if (strcmp(get_vers[0].name, "Test System") || strcmp(get_vers[0].sversion, "1.4 build 42")) { testEndMessage(false, "got '%s v%s', expected 'Test System v1.4 build 42'", get_vers[0].name, get_vers[0].sversion); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { testBegin("api: papplSystemGet/SetVersions(%d)", i + 1); memset(set_vers + i, 0, sizeof(pappl_version_t)); snprintf(set_vers[i].name, sizeof(set_vers[i].name), "Component %c", 'A' + i); set_vers[i].version[0] = (unsigned short)(i + 1); set_vers[i].version[1] = (unsigned short)(papplGetRand() % 100); snprintf(set_vers[i].sversion, sizeof(set_vers[i].sversion), "%u.%02u", set_vers[i].version[0], set_vers[i].version[1]); papplSystemSetVersions(system, i + 1, set_vers); if ((get_nvers = papplSystemGetVersions(system, (int)(sizeof(get_vers) / sizeof(get_vers[0])), get_vers)) != (i + 1)) { testEndMessage(false, "got %d versions, expected %d", get_nvers, i + 1); pass = false; } else { for (j = 0; j < get_nvers; j ++) { if (strcmp(get_vers[j].name, set_vers[j].name) || strcmp(get_vers[j].sversion, set_vers[j].sversion)) { testEndMessage(false, "got '%s v%s', expected '%s v%s'", get_vers[j].name, get_vers[j].sversion, set_vers[j].name, set_vers[j].sversion); pass = false; break; } } if (j >= get_nvers) testEnd(true); } } // papplSystemFindPrinter testBegin("api: papplSystemFindPrinter(default)"); if ((printer = papplSystemFindPrinter(system, "/ipp/print", 0, NULL)) == NULL) { testEndMessage(false, "got NULL"); pass = false; } else if (papplPrinterGetID(printer) != papplSystemGetDefaultPrinterID(system)) { testEndMessage(false, "got printer #%d, expected #%d", papplPrinterGetID(printer), papplSystemGetDefaultPrinterID(system)); pass = false; } else testEnd(true); for (set_int = 1; set_int < 3; set_int ++) { testBegin("api: papplSystemFindPrinter(%d)", set_int); if ((printer = papplSystemFindPrinter(system, NULL, set_int, NULL)) == NULL) { testEndMessage(false, "got NULL"); pass = false; } else { testEnd(true); if (!test_api_printer(printer)) pass = false; } } // papplPrinterCreate/Delete for (i = 0; i < 10; i ++) { char name[128]; // Printer name snprintf(name, sizeof(name), "test%d", i); testBegin("api: papplPrinterCreate(%s)", name); if ((printer = papplPrinterCreate(system, 0, name, "pwg_common-300dpi-black_1-sgray_8", "MFG:PWG;MDL:Office Printer;CMD:PWGRaster;", "file:///dev/null")) == NULL) { testEndMessage(false, "got NULL"); pass = false; } else { testEnd(true); get_int = papplPrinterGetID(printer); testBegin("api: papplPrinterDelete(%s)", name); papplPrinterDelete(printer); if (papplSystemFindPrinter(system, NULL, get_int, NULL) != NULL) { testEndMessage(false, "printer not deleted"); pass = false; } else { testEnd(true); testBegin("api: papplPrinterCreate(%s again)", name); if ((printer = papplPrinterCreate(system, 0, name, "pwg_common-300dpi-black_1-sgray_8", "MFG:PWG;MDL:Office Printer;CMD:PWGRaster;", "file:///dev/null")) == NULL) { testEndMessage(false, "got NULL"); pass = false; } else if (papplPrinterGetID(printer) == get_int) { testEndMessage(false, "got the same printer ID"); pass = false; } else testEnd(true); } } } // papplSystemIteratePrinters testBegin("api: papplSystemIteratePrinters"); pdata.pass = true; pdata.count = 0; papplSystemIteratePrinters(system, (pappl_printer_cb_t)test_api_printer_cb, &pdata); if (pdata.count != 12) { testEndMessage(false, "got %d printers, expected 12", pdata.count); pass = false; } else if (!pdata.pass) { testEndMessage(false, "per-printer test failed"); pass = false; } else testEnd(true); return (pass); } // // 'test_api_printer()' - Test papplPrinter APIs. // static bool // O - `true` on success, `false` on failure test_api_printer( pappl_printer_t *printer) // I - Printer { bool pass = true; // Pass/fail for tests int i; // Looping vars pappl_contact_t get_contact, // Contact for "get" call set_contact; // Contact for ", set" call int get_int, // Integer for "get" call set_int; // Integer for ", set" call char get_str[1024], // Temporary string for "get" call set_str[1024]; // Temporary string for ", set" call const char *get_ptr; // Get string pointer bool expected_null; // Expected NULL string value? static const char * const set_locations[10][2] = { // Some wonders of the ancient world (all north-eastern portion of globe...) { "Great Pyramid of Giza", "geo:29.979175,31.134358" }, { "Temple of Artemis at Ephesus", "geo:37.949722,27.363889" }, { "Statue of Zeus at Olympia", "geo:37.637861,21.63" }, { "Colossus of Rhodes", "geo:36.451111,28.227778" }, { "Lighthouse of Alexandria", "geo:31.213889,29.885556" }, // Other places { "Niagara Falls", "geo:43.0828201,-79.0763516" }, { "Grand Canyon", "geo:36.0545936,-112.2307085" }, { "Christ the Redeemer", "geo:-22.9691208,-43.2583044" }, { "Great Barrier Reef", "geo:-16.7546653,143.8322946" }, { "Science North", "geo:46.4707,-80.9961" } }; // papplPrinterGet/SetContact testBegin("api: papplPrinterGetContact"); if (!papplPrinterGetContact(printer, &get_contact)) { testEndMessage(false, "got NULL, expected 'Michael R Sweet'"); pass = false; } else if (strcmp(get_contact.name, "Michael R Sweet")) { testEndMessage(false, "got '%s', expected 'Michael R Sweet'", get_contact.name); pass = false; } else if (strcmp(get_contact.email, "msweet@example.org")) { testEndMessage(false, "got '%s', expected 'msweet@example.org'", get_contact.email); pass = false; } else if (strcmp(get_contact.telephone, "+1-705-555-1212")) { testEndMessage(false, "got '%s', expected '+1-705-555-1212'", get_contact.telephone); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_contact.name, sizeof(set_contact.name), "Admin %d", i); snprintf(set_contact.email, sizeof(set_contact.email), "admin-%d@example.org", i); snprintf(set_contact.telephone, sizeof(set_contact.telephone), "+1-705-555-%04d", i * 1111); testBegin("api: papplPrinterGet/SetContact('%s')", set_contact.name); papplPrinterSetContact(printer, &set_contact); if (!papplPrinterGetContact(printer, &get_contact)) { testEndMessage(false, "got NULL, expected '%s'", set_contact.name); pass = false; } else if (strcmp(get_contact.name, set_contact.name)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.name, set_contact.name); pass = false; } else if (strcmp(get_contact.email, set_contact.email)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.email, set_contact.email); pass = false; } else if (strcmp(get_contact.telephone, set_contact.telephone)) { testEndMessage(false, "got '%s', expected '%s'", get_contact.telephone, set_contact.telephone); pass = false; } else testEnd(true); } // papplPrinterGet/SetPrintGroup testBegin("api: papplPrinterGetPrintGroup"); if (papplPrinterGetPrintGroup(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "users-%d", i); testBegin("api: papplPrinterGet/SetPrintGroup('%s')", set_str); papplPrinterSetPrintGroup(printer, set_str); if (!papplPrinterGetPrintGroup(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetPrintGroup(NULL)"); papplPrinterSetPrintGroup(printer, NULL); if (papplPrinterGetPrintGroup(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplPrinterGet/SetDNSSDName testBegin("api: papplPrinterGetDNSSDName"); if (!papplPrinterGetDNSSDName(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected string"); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "Printer Test %c", i + 'A'); testBegin("api: papplPrinterGet/SetDNSSDName('%s')", set_str); papplPrinterSetDNSSDName(printer, set_str); if (!papplPrinterGetDNSSDName(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetDNSSDName(NULL)"); papplPrinterSetDNSSDName(printer, NULL); if (papplPrinterGetDNSSDName(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplPrinterGet/SetGeoLocation expected_null = !strcmp(papplPrinterGetName(printer), "Label Printer"); testBegin("api: papplPrinterGetGeoLocation"); get_ptr = papplPrinterGetGeoLocation(printer, get_str, sizeof(get_str)); if (get_ptr && expected_null) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else if (!get_ptr && !expected_null) { testEndMessage(false, "got NULL, expected 'geo:46.4707,-80.9961'"); pass = false; } else if (get_ptr && strcmp(get_str, "geo:46.4707,-80.9961")) { testEndMessage(false, "got '%s', expected 'geo:46.4707,-80.9961'", get_str); pass = false; } else testEnd(true); testBegin("api: papplPrinterGet/SetGeoLocation('bad-value')"); papplPrinterSetGeoLocation(printer, "bad-value"); get_ptr = papplPrinterGetGeoLocation(printer, get_str, sizeof(get_str)); if (get_ptr && expected_null) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else if (!get_ptr && !expected_null) { testEndMessage(false, "got NULL, expected 'geo:46.4707,-80.9961'"); pass = false; } else if (get_ptr && strcmp(get_str, "geo:46.4707,-80.9961")) { testEndMessage(false, "got '%s', expected 'geo:46.4707,-80.9961'", get_str); pass = false; } else testEnd(true); for (i = 0; i < (int)(sizeof(set_locations) / sizeof(set_locations[0])); i ++) { testBegin("api: papplPrinterGet/SetGeoLocation('%s')", set_locations[i][1]); papplPrinterSetGeoLocation(printer, set_locations[i][1]); if (!papplPrinterGetGeoLocation(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_locations[i][1]); pass = false; } else if (strcmp(get_str, set_locations[i][1])) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_locations[i][1]); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetGeoLocation(NULL)"); papplPrinterSetGeoLocation(printer, NULL); if (papplPrinterGetGeoLocation(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplPrinterGet/SetLocation testBegin("api: papplPrinterGetLocation"); if (!papplPrinterGetLocation(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'Test Lab 42'"); pass = false; } else if (strcmp(get_str, "Test Lab 42")) { testEndMessage(false, "got '%s', expected 'Test Lab 42'", get_str); pass = false; } else testEnd(true); for (i = 0; i < (int)(sizeof(set_locations) / sizeof(set_locations[0])); i ++) { testBegin("api: papplPrinterGet/SetLocation('%s')", set_locations[i][0]); papplPrinterSetLocation(printer, set_locations[i][0]); if (!papplPrinterGetLocation(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_locations[i][0]); pass = false; } else if (strcmp(get_str, set_locations[i][0])) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_locations[i][0]); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetLocation(NULL)"); papplPrinterSetLocation(printer, NULL); if (papplPrinterGetLocation(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplPrinterGet/SetNextJobID testBegin("api: papplPrinterGetNextJobID"); if ((get_int = papplPrinterGetNextJobID(printer)) != 1) { testEndMessage(false, "got %d, expected 1", get_int); pass = false; } else testEnd(true); set_int = (papplGetRand() % 1000000) + 2; testBegin("api: papplPrinterSetNextJobID(%d)", set_int); papplPrinterSetNextJobID(printer, set_int); if ((get_int = papplPrinterGetNextJobID(printer)) != set_int) { testEndMessage(false, "got %d, expected %d", get_int, set_int); pass = false; } else testEnd(true); // papplPrinterGet/SetOrganization testBegin("api: papplPrinterGetOrganization"); if (!papplPrinterGetOrganization(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected 'Lakeside Robotics'"); pass = false; } else if (strcmp(get_str, "Lakeside Robotics")) { testEndMessage(false, "got '%s', expected 'Lakeside Robotics'", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "Organization %c", i + 'A'); testBegin("api: papplPrinterGet/SetOrganization('%s')", set_str); papplPrinterSetOrganization(printer, set_str); if (!papplPrinterGetOrganization(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetOrganization(NULL)"); papplPrinterSetOrganization(printer, NULL); if (papplPrinterGetOrganization(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); // papplPrinterGet/SetOrganizationalUnit testBegin("api: papplPrinterGetOrganizationalUnit"); if (papplPrinterGetOrganizationalUnit(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); for (i = 0; i < 10; i ++) { snprintf(set_str, sizeof(set_str), "%c Team", i + 'A'); testBegin("api: papplPrinterGet/SetOrganizationalUnit('%s')", set_str); papplPrinterSetOrganizationalUnit(printer, set_str); if (!papplPrinterGetOrganizationalUnit(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got NULL, expected '%s'", set_str); pass = false; } else if (strcmp(get_str, set_str)) { testEndMessage(false, "got '%s', expected '%s'", get_str, set_str); pass = false; } else testEnd(true); } testBegin("api: papplPrinterGet/SetOrganizationalUnit(NULL)"); papplPrinterSetOrganizationalUnit(printer, NULL); if (papplPrinterGetOrganizationalUnit(printer, get_str, sizeof(get_str))) { testEndMessage(false, "got '%s', expected NULL", get_str); pass = false; } else testEnd(true); return (pass); } // // 'test_api_printer_cb()' - Iterator callback for testing printers. // static bool // O - `true` to continue test_api_printer_cb( pappl_printer_t *printer, // I - Printer _pappl_testprinter_t *tp) // I - Printer test data { tp->count ++; if (!printer) tp->pass = false; else if (!papplPrinterGetName(printer)) tp->pass = false; else { char get_str[128]; // Location string papplPrinterSetLocation(printer, "Nowhere"); if (!papplPrinterGetLocation(printer, get_str, sizeof(get_str)) || strcmp(get_str, "Nowhere")) tp->pass = false; } return (true); } // // 'test_client()' - Run simulated client tests. // static bool // O - `true` on success, `false` on failure test_client(pappl_system_t *system) // I - System { bool ret = false; // Return value http_t *http; // HTTP connection char uri[1024], // "printer-uri" value filename[1024] = "", // Print file outfile[1024]; // Output file ipp_t *request, // Request *response, // Response *supported = NULL; // Supported values ipp_attribute_t *attr; // Attribute pappl_event_t recv_events = PAPPL_EVENT_NONE; // Accumulated events int i, // Looping var job_id, // "job-id" value subscription_id; // "notify-subscription-id" value ipp_jstate_t job_state; // "job-state" value time_t end; // End time static const char * const events[] = // "notify-events" attribute { "job-completed", "job-created", "job-progress", "job-state-changed", "printer-created", "printer-deleted", "printer-config-changed", "printer-state-changed" }; static const char * const pattrs[] = // Printer attributes { "printer-contact-col", "printer-current-time", "printer-geo-location", "printer-location", "printer-name", "printer-state", "printer-state-reasons", "printer-uuid", "printer-uri-supported" }; static const char * const sattrs[] = // System attributes { "system-contact-col", "system-current-time", "system-geo-location", "system-location", "system-name", "system-state", "system-state-reasons", "system-uuid", "system-xri-supported" }; // Connect to system... testBegin("client: Connect to server"); if ((http = connect_to_printer(system, false, uri, sizeof(uri))) == NULL) { testEndMessage(false, "%s", cupsGetErrorString()); return (false); } else { testEnd(true); } // Test Get-System-Attributes testBegin("client: Get-System-Attributes"); request = ippNewRequest(IPP_OP_GET_SYSTEM_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/system"); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); ippDelete(response); goto done; } else { for (i = 0; i < (int)(sizeof(sattrs) / sizeof(sattrs[0])); i ++) { if (!ippFindAttribute(response, sattrs[i], IPP_TAG_ZERO)) { testEndMessage(false, "Missing required '%s' attribute in response", sattrs[i]); ippDelete(response); goto done; } } testEnd(true); ippDelete(response); } // Test Get-Printers testBegin("client: Get-Printers"); request = ippNewRequest(IPP_OP_GET_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/system"); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); ippDelete(response); goto done; } else { for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (!ippFindAttribute(response, pattrs[i], IPP_TAG_ZERO)) { testEndMessage(false, "Missing required '%s' attribute in response", pattrs[i]); ippDelete(response); goto done; } } testEnd(true); ippDelete(response); } // Test Get-Printer-Attributes on / testBegin("client: Get-Printer-Attributes=/"); request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/"); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); ippDelete(response); goto done; } else { for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (!ippFindAttribute(response, pattrs[i], IPP_TAG_ZERO)) { testEndMessage(false, "Missing required '%s' attribute in response", pattrs[i]); ippDelete(response); goto done; } } testEnd(true); ippDelete(response); } // Test Get-Printer-Attributes on /ipp/print testBegin("client: Get-Printer-Attributes=/ipp/print"); request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); supported = cupsDoRequest(http, request, "/ipp/print"); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else { for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (!ippFindAttribute(supported, pattrs[i], IPP_TAG_ZERO)) { testEndMessage(false, "Missing required '%s' attribute in response", pattrs[i]); goto done; } } testEnd(true); } // Create a system subscription for a variety of events... testBegin("client: Create-System-Subscriptions"); request = ippNewRequest(IPP_OP_CREATE_SYSTEM_SUBSCRIPTIONS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddStrings(request, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events", sizeof(events) / sizeof(events[0]), NULL, events); ippAddInteger(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, "notify-lease-duration", 60); ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-pull-method", NULL, "ippget"); response = cupsDoRequest(http, request, "/ipp/system"); subscription_id = ippGetInteger(ippFindAttribute(response, "notify-subscription-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else if (subscription_id == 0) { testEndMessage(false, "missing required 'notify-subscription-id' attribute in response"); goto done; } else { testEndMessage(true, "notify-subscription-id=%d", subscription_id); } end = time(NULL) + 70; // Verify the subscription exists... testBegin("client: Get-Subscription-Attributes"); request = ippNewRequest(IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-id", subscription_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/system"); attr = ippFindAttribute(response, "notify-events", IPP_TAG_KEYWORD); ippDelete(response); if (cupsGetError() != IPP_STATUS_OK) { printf("FAIL(%s)\n", cupsGetErrorString()); goto done; } else if (!attr) { testEndMessage(false, "missing 'notify-events' attribute"); goto done; } else { testEnd(true); } // Send a print job to get some events... testBegin("client: Make raster print file"); if (!make_raster_file(supported, false, filename, sizeof(filename))) goto done; testEnd(true); testBegin("client: Print-Job (Raster)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/pwg-raster"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test Raster Job"); response = cupsDoFileRequest(http, request, "/ipp/print", filename); job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEndMessage(true, "job-id=%d", job_id); output_count ++; #ifdef HAVE_LIBJPEG testBegin("client: Print-Job (JPEG)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/jpeg"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test JPEG Job"); ippAddString(request, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-hold-until", NULL, "indefinite"); if (access("portrait-color.jpg", R_OK)) papplCopyString(filename, "testsuite/portrait-color.jpg", sizeof(filename)); else papplCopyString(filename, "portrait-color.jpg", sizeof(filename)); response = cupsDoFileRequest(http, request, "/ipp/print", filename); job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEndMessage(true, "job-id=%d", job_id); testBegin("client: Release-Job (JPEG)"); request = ippNewRequest(IPP_OP_RELEASE_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/print")); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEnd(true); testBegin("client: Get-Job-Attributes (JPEG)"); do { request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/print"); job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); ippDelete(response); if (cupsGetError() == IPP_STATUS_OK && job_state < IPP_JSTATE_CANCELED) sleep(1); } while (cupsGetError() == IPP_STATUS_OK && job_state < IPP_JSTATE_CANCELED); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEndMessage(job_state == IPP_JSTATE_COMPLETED, "job-state=%s", ippEnumString("job-state", (int)job_state)); output_count ++; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG testBegin("client: Print-Job (PNG)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/png"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test PNG Job"); ippAddString(request, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-hold-until", NULL, "indefinite"); if (access("portrait-color.png", R_OK)) papplCopyString(filename, "testsuite/portrait-color.png", sizeof(filename)); else papplCopyString(filename, "portrait-color.png", sizeof(filename)); response = cupsDoFileRequest(http, request, "/ipp/print", filename); job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEndMessage(true, "job-id=%d", job_id); testBegin("client: Release-Job (PNG)"); request = ippNewRequest(IPP_OP_RELEASE_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/print")); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEnd(true); testBegin("client: Get-Job-Attributes (PNG)"); do { request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/print"); job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); ippDelete(response); if (cupsGetError() == IPP_STATUS_OK && job_state < IPP_JSTATE_CANCELED) sleep(1); } while (cupsGetError() == IPP_STATUS_OK && job_state < IPP_JSTATE_CANCELED); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEndMessage(job_state == IPP_JSTATE_COMPLETED, "job-state=%s", ippEnumString("job-state", (int)job_state)); output_count ++; #endif // HAVE_LIBPNG // Hold-New-Jobs testBegin("client: Hold-New-Jobs"); request = ippNewRequest(IPP_OP_HOLD_NEW_JOBS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/print")); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEnd(true); testBegin("client: Print-Job (Raster 2)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/pwg-raster"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test Raster Job 2"); ippDelete(cupsDoFileRequest(http, request, "/ipp/print", filename)); if (cupsGetError() == IPP_STATUS_OK) { testEndMessage(false, "Job accepted but should have been rejected."); goto done; } sleep(1); snprintf(outfile, sizeof(outfile), "%s/Client Test Raster Job 2.pwg", output_directory); if (!access(outfile, 0)) { testEndMessage(false, "Unexpected job output file created."); goto done; } testEnd(true); #ifdef HAVE_LIBJPEG testBegin("client: Print-Job (JPEG 2)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/jpeg"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test JPEG Job 2"); if (access("portrait-color.jpg", R_OK)) papplCopyString(filename, "testsuite/portrait-color.jpg", sizeof(filename)); else papplCopyString(filename, "portrait-color.jpg", sizeof(filename)); response = cupsDoFileRequest(http, request, "/ipp/print", filename); job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); ippDelete(response); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else if (job_state != IPP_JSTATE_HELD) { testEndMessage(false, "job-state is %s, expected pending-held", ippEnumString("job-state", (int)job_state)); goto done; } sleep(1); snprintf(outfile, sizeof(outfile), "%s/Client Test JPEG Job 2.pwg", output_directory); if (!access(outfile, 0)) { testEndMessage(false, "Unexpected job output file created."); goto done; } testEndMessage(true, "job-id=%d", job_id); output_count ++; #endif // HAVE_LIBJPEG #ifdef HAVE_LIBPNG testBegin("client: Print-Job (PNG 2)"); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/png"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, "Client Test PNG Job 2"); if (access("portrait-color.png", R_OK)) papplCopyString(filename, "testsuite/portrait-color.png", sizeof(filename)); else papplCopyString(filename, "portrait-color.png", sizeof(filename)); response = cupsDoFileRequest(http, request, "/ipp/print", filename); job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); ippDelete(response); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else if (job_state != IPP_JSTATE_HELD) { testEndMessage(false, "job-state is %s, expected pending-held", ippEnumString("job-state", (int)job_state)); goto done; } sleep(1); snprintf(outfile, sizeof(outfile), "%s/Client Test PNG Job 2.pwg", output_directory); if (!access(outfile, 0)) { testEndMessage(false, "Unexpected job output file created."); goto done; } testEndMessage(true, "job-id=%d", job_id); output_count ++; #endif // HAVE_LIBPNG // Release-Held-New-Jobs testBegin("client: Release-Held-New-Jobs"); request = ippNewRequest(IPP_OP_RELEASE_HELD_NEW_JOBS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippDelete(cupsDoRequest(http, request, "/ipp/print")); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } testEnd(true); // Get event notifications... testBegin("client: Get-Notifications"); request = ippNewRequest(IPP_OP_GET_NOTIFICATIONS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-ids", subscription_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/system"); for (attr = ippFindAttribute(response, "notify-subscribed-event", IPP_TAG_KEYWORD); attr; attr = ippFindNextAttribute(response, "notify-subscribed-event", IPP_TAG_KEYWORD)) { const char *keyword = ippGetString(attr, 0, NULL); // "notify-subscribed-event" keyword value if (!strcmp(keyword, "job-created")) { recv_events |= PAPPL_EVENT_JOB_CREATED; } else if (!strcmp(keyword, "job-completed")) { recv_events |= PAPPL_EVENT_JOB_COMPLETED; } else if (!strcmp(keyword, "job-progress")) { recv_events |= PAPPL_EVENT_JOB_PROGRESS; } else if (!strcmp(keyword, "job-state-changed")) { recv_events |= PAPPL_EVENT_JOB_STATE_CHANGED; } else if (!strcmp(keyword, "printer-config-changed")) { recv_events |= PAPPL_EVENT_PRINTER_CONFIG_CHANGED; } else if (!strcmp(keyword, "printer-state-changed")) { recv_events |= PAPPL_EVENT_PRINTER_STATE_CHANGED; } else { testEndMessage(false, "Unexpected event '%s'", keyword); ippDelete(response); goto done; } } ippDelete(response); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else if (recv_events != (PAPPL_EVENT_JOB_COMPLETED | PAPPL_EVENT_JOB_CREATED | PAPPL_EVENT_JOB_PROGRESS | PAPPL_EVENT_JOB_STATE_CHANGED | PAPPL_EVENT_PRINTER_CONFIG_CHANGED | PAPPL_EVENT_PRINTER_STATE_CHANGED)) { testEndMessage(false, "wrong events seen"); goto done; } else { testEnd(true); } // PAPPL-Find-Devices testBegin("client: PAPPL-Find-Devices"); request = ippNewRequest(IPP_OP_PAPPL_FIND_DEVICES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); response = cupsDoRequest(http, request, "/ipp/system"); if ((attr = ippFindAttribute(response, "smi55357-device-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) testEndMessage(true, "%u devices found", (unsigned)ippGetCount(attr)); else if (cupsGetError() == IPP_STATUS_ERROR_NOT_FOUND) testEndMessage(true, "no devices found"); else testEndMessage(false, "failed: %s", cupsGetErrorString()); ippDelete(response); // PAPPL-Find-Drivers testBegin("client: PAPPL-Find-Drivers"); request = ippNewRequest(IPP_OP_PAPPL_FIND_DRIVERS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); response = cupsDoRequest(http, request, "/ipp/system"); if ((attr = ippFindAttribute(response, "smi55357-driver-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) testEndMessage(true, "%u drivers found", (unsigned)ippGetCount(attr)); else testEndMessage(false, "failed: %s", cupsGetErrorString()); ippDelete(response); // PAPPL-Find-Drivers (good device-id) testBegin("client: PAPPL-Find-Drivers (good device-id)"); request = ippNewRequest(IPP_OP_PAPPL_FIND_DRIVERS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_TEXT), "smi55357-device-id", NULL, "MFG:Example;MDL:Printer;CMD:PWGRaster;"); response = cupsDoRequest(http, request, "/ipp/system"); if ((attr = ippFindAttribute(response, "smi55357-driver-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) testEndMessage(true, "%u drivers found", (unsigned)ippGetCount(attr)); else testEndMessage(false, "failed: %s", cupsGetErrorString()); ippDelete(response); // PAPPL-Find-Drivers (bad device-id) testBegin("client: PAPPL-Find-Drivers (bad device-id)"); request = ippNewRequest(IPP_OP_PAPPL_FIND_DRIVERS); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_TEXT), "smi55357-device-id", NULL, "MFG:Example;MDL:Printer;CMD:PCL;"); response = cupsDoRequest(http, request, "/ipp/system"); if ((attr = ippFindAttribute(response, "smi55357-driver-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) testEndMessage(false, "%u drivers found", (unsigned)ippGetCount(attr)); else if (cupsGetError() == IPP_STATUS_ERROR_NOT_FOUND) testEndMessage(true, "no drivers found"); else testEndMessage(false, "failed: %s", cupsGetErrorString()); ippDelete(response); // Verify that the subscription expires... testBegin("client: Get-Subscription-Attributes(expiration)"); while (time(NULL) < end) { testProgress(); sleep(5); } request = ippNewRequest(IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_URI), "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-id", subscription_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); httpConnectAgain(http, 30000, NULL); response = cupsDoRequest(http, request, "/ipp/system"); attr = ippFindAttribute(response, "notify-events", IPP_TAG_KEYWORD); ippDelete(response); if (cupsGetError() != IPP_STATUS_ERROR_NOT_FOUND) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } else if (attr) { testEndMessage(false, "unexpected 'notify-events' attribute"); goto done; } else { testEnd(true); } ret = true; // Clean up and return... done: ippDelete(supported); httpClose(http); return (ret); } // // 'test_client_child()' - Test client child thread. // static void * // O - Thread exit status test_client_child( _pappl_testclient_t *data) // I - Client data { size_t i; // Looping var http_t *http; // HTTP connection char printer_uri[1024]; // "printer-uri" value ipp_t *request; // IPP request char error[1024]; // Error message // Connect to the server... if ((http = httpConnect("localhost", papplSystemGetHostPort(data->system), /*addrlist*/NULL, AF_UNSPEC, HTTP_ENCRYPTION_NEVER, /*blocking*/true, /*msec*/30000, /*cancel*/NULL)) == NULL) { snprintf(error, sizeof(error), "Unable to connect to 'localhost:%d': %s", papplSystemGetHostPort(data->system), cupsGetErrorString()); pthread_mutex_lock(&data->mutex); data->completed_count ++; cupsArrayAdd(data->errors, error); pthread_mutex_unlock(&data->mutex); return ((void *)1); } httpAssembleURI(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp", /*userpass*/NULL, "localhost", papplSystemGetHostPort(data->system), "/ipp/print"); // Do Get-Printer-Attributes requests for (i = 0; i < data->num_requests; i ++) { request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); ippDelete(cupsDoRequest(http, request, "/ipp/print")); pthread_mutex_lock(&data->mutex); data->request_count ++; if (cupsGetError() > IPP_STATUS_OK_EVENTS_COMPLETE) { snprintf(error, sizeof(error), "Get-Printer-Attributes: %s", cupsGetErrorString()); cupsArrayAdd(data->errors, error); } gettimeofday(&data->end, NULL); pthread_mutex_unlock(&data->mutex); } httpClose(http); pthread_mutex_lock(&data->mutex); data->completed_count ++; pthread_mutex_unlock(&data->mutex); return (NULL); } // // 'test_client_max()' - Test max clients throughput. // static bool // O - Results of test test_client_max(pappl_system_t *system, // I - System const char *name) // I - Test name { size_t i; // Looping var double secs; // Seconds pthread_t threads[_PAPPL_MAX_CLIENTS]; // Threads _pappl_testclient_t data; // Client data size_t total, // Total number of requests expected current, // Number of requests last = 0; // Last number of requests const char *ptr; // Pointer into name char progress[13]; // Progress bar int pcounter = 0; // Progress counter // Don't rotate the logs for this test... papplSystemSetMaxLogSize(system, 0); // Prepare client data... memset(&data, 0, sizeof(data)); data.system = system; data.errors = cupsArrayNew(/*cb*/NULL, /*cbdata*/NULL, /*hashcb*/NULL, /*hashsize*/0, (cups_acopy_cb_t)strcopy_cb, (cups_afree_cb_t)strfree_cb); pthread_mutex_init(&data.mutex, NULL); // Parse the name if (!strcmp(name, "client-max")) { // Test the maximum number of clients and requests data.num_children = _PAPPL_DEFAULT_CLIENTS; data.num_requests = _PAPPL_DEFAULT_REQUESTS; } else { // Parse "client-CLIENTSxREQUESTS" if ((data.num_children = (size_t)strtoul(name + 7, (char **)&ptr, 10)) > _PAPPL_MAX_CLIENTS) { fprintf(stderr, "testpappl: Reducing number of clients from %lu to %d.\n", (unsigned long)data.num_children, _PAPPL_MAX_CLIENTS); data.num_children = _PAPPL_MAX_CLIENTS; } else if (data.num_children == 0) { fprintf(stderr, "testpappl: Using %d clients.\n", _PAPPL_DEFAULT_CLIENTS); data.num_children = _PAPPL_DEFAULT_CLIENTS; } if (!ptr || *ptr != 'x') { // Use default number of requests data.num_requests = _PAPPL_DEFAULT_REQUESTS; } else if ((data.num_requests = (size_t)strtoul(ptr + 1, NULL, 10)) > _PAPPL_MAX_REQUESTS) { fprintf(stderr, "testpappl: Reducing number of requests from %lu to %d.\n", (unsigned long)data.num_requests, _PAPPL_MAX_REQUESTS); data.num_requests = _PAPPL_MAX_REQUESTS; } else if (data.num_requests == 0) { data.num_requests = _PAPPL_DEFAULT_REQUESTS; fprintf(stderr, "testpappl: Doing %d requests.\n", _PAPPL_DEFAULT_REQUESTS); } } papplSystemSetMaxClients(system, (int)data.num_children + 1); total = data.num_children * data.num_requests; // Start client threads testBegin("%s", name); gettimeofday(&data.start, NULL); gettimeofday(&data.end, NULL); for (i = 0; i < data.num_children; i ++) pthread_create(threads + i, NULL, (void *(*)(void *))test_client_child, &data); // Wait for threads to finish current = last; while (data.completed_count < data.num_children) { if (current > 0) fputs("\b\b\b\b\b\b\b\b\b\b\b\b", stdout); i = 10 * current / total; if (i == 10) { // Completed fputs("[==========]", stdout); } else { // Partial progress[0] = '['; if (i > 0) memset(progress + 1, '=', i); if (i < 9) memset(progress + i + 2, ' ', 10 - i); progress[i + 1] = "-\\|/"[pcounter & 3]; progress[11] = ']'; progress[12] = '\0'; fputs(progress, stdout); pcounter ++; } fflush(stdout); sleep(1); pthread_mutex_lock(&data.mutex); current = data.request_count; pthread_mutex_unlock(&data.mutex); } if (current > 0) fputs("\b\b\b\b\b\b\b\b\b\b\b\b", stdout); for (i = 0; i < data.num_children; i ++) pthread_join(threads[i], NULL); // Report on activity and return... secs = (double)(data.end.tv_sec - data.start.tv_sec) + 0.000001 * (data.end.tv_usec - data.start.tv_usec); i = (size_t)cupsArrayGetCount(data.errors); testEndMessage(i == 0, "%.3f seconds, %.0f requests/sec, %lu errors", secs, data.request_count / secs, (unsigned long)i); for (ptr = (const char *)cupsArrayGetFirst(data.errors); ptr; ptr = (const char *)cupsArrayGetNext(data.errors)) fprintf(stderr, "%s: %s\n", name, ptr); cupsArrayDelete(data.errors); return (i == 0); } #if defined(HAVE_LIBJPEG) || defined(HAVE_LIBPNG) // // 'test_image_files()' - Run image file tests. // static bool // O - `true` on success, `false` on failure test_image_files( pappl_system_t *system, // I - System const char *prompt, // I - Prompt for files const char *format, // I - MIME media type of files int num_files, // I - Number of files to print const char * const * files) // I - Files to print { int i, j, k, m; // Looping vars http_t *http; // HTTP connection char uri[1024], // "printer-uri" value filename[1024], // Print file job_name[1024]; // "job_name" value ipp_t *request, // Request *response; // Response int job_id; // "job-id" value ipp_jstate_t job_state; // "job-state" value static const int orients[] = // "orientation-requested" values { IPP_ORIENT_NONE, IPP_ORIENT_PORTRAIT, IPP_ORIENT_LANDSCAPE, IPP_ORIENT_REVERSE_PORTRAIT, IPP_ORIENT_REVERSE_LANDSCAPE }; static const char * const modes[] = // "print-color-mode" values { "auto", "color", "monochrome" }; static const char * const scalings[] =// "print-scaling" values { "auto", "auto-fit", "fill", "fit", "none" }; // Connect to system... testBegin("%s: Connect to server", prompt); if ((http = connect_to_printer(system, true, uri, sizeof(uri))) == NULL) { testEndMessage(false, "Unable to connect: %s", cupsGetErrorString()); return (false); } testEnd(true); // Print files... for (i = 0; i < num_files; i ++) { if (access(files[i], R_OK)) snprintf(filename, sizeof(filename), "testsuite/%s", files[i]); else papplCopyString(filename, files[i], sizeof(filename)); for (j = 0; j < (int)(sizeof(orients) / sizeof(orients[0])); j ++) { for (k = 0; k < (int)(sizeof(modes) / sizeof(modes[0])); k ++) { for (m = 0; m < (int)(sizeof(scalings) / sizeof(scalings[0])); m ++) { // Stop the test if the system is shutdown (e.g. CTRL+C) if (papplSystemIsShutdown(system)) return (false); // Print the job... snprintf(job_name, sizeof(job_name), "%s+%s+%s+%s", files[i], ippEnumString("orientation-requested", orients[j]), modes[k], scalings[m]); testBegin("%s: Print-Job(%s)", prompt, job_name); request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, job_name); ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "orientation-requested", orients[j]); ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "print-color-mode", NULL, modes[k]); ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "print-scaling", NULL, scalings[m]); response = cupsDoFileRequest(http, request, "/ipp/print", filename); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); ippDelete(response); httpClose(http); return (false); } job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); testEndMessage(true, "job-id=%d", job_id); ippDelete(response); output_count ++; // Poll job status until completed... do { sleep(1); testBegin("%s: Get-Job-Attributes(job-id=%d)", prompt, job_id); request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/print"); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "%s", cupsGetErrorString()); httpClose(http); ippDelete(response); return (false); } job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); testEndMessage(job_state != (ipp_jstate_t)0, "job-state=%d", job_state); ippDelete(response); } while (job_state < IPP_JSTATE_CANCELED); } } } } httpClose(http); return (true); } #endif // HAVE_LIBJPEG || HAVE_LIBPNG // // 'test_network_get_cb()' - Get test networks. // static pappl_network_t test_networks[2]; static size_t // O - Number of networks test_network_get_cb( pappl_system_t *system, // I - System void *data, // I - Callback data size_t max_networks, // I - Maximum number of networks pappl_network_t *networks) // I - Networks { (void)system; (void)data; if (!test_networks[0].name[0]) { // Initialize test networks: eth0 and wlan0 size_t i; // Looping var static const char * const names[] = // Network names { "Ethernet", "Wi-Fi" }; static const char * const idents[] =// Network identities { "eth0", "wlan0" }; for (i = 0; i < (sizeof(names) / sizeof(names[0])); i ++) { // Initialize a network interface papplCopyString(test_networks[i].name, names[i], sizeof(test_networks[i].name)); papplCopyString(test_networks[i].ident, idents[i], sizeof(test_networks[i].name)); test_networks[i].up = true; test_networks[i].config4 = PAPPL_NETCONF_DHCP; test_networks[i].config6 = PAPPL_NETCONF_DHCP; test_networks[i].dns[0].ipv4.sin_family = AF_INET; test_networks[i].dns[0].ipv4.sin_addr.s_addr = htonl(0x0a000101); test_networks[i].addr4.ipv4.sin_family = AF_INET; test_networks[i].addr4.ipv4.sin_addr.s_addr = htonl(0x0a000102 + i); test_networks[i].mask4.ipv4.sin_family = AF_INET; test_networks[i].mask4.ipv4.sin_addr.s_addr = htonl(0xffffff00); test_networks[i].gateway4.ipv4.sin_family = AF_INET; test_networks[i].gateway4.ipv4.sin_addr.s_addr = htonl(0x0a000101); test_networks[i].linkaddr6.ipv6.sin6_family = AF_INET6; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[0] = 0xfe; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[1] = 0x80; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[10] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[11] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[12] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[13] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[14] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_addr.s6_addr[15] = papplGetRand() & 255; test_networks[i].linkaddr6.ipv6.sin6_scope_id = (unsigned)i + 1; } } if (max_networks < 2) memcpy(networks, test_networks, max_networks * sizeof(pappl_network_t)); else memcpy(networks, test_networks, sizeof(test_networks)); return (2); } // // 'test_network_set_cb()' - Set test networks. // static bool // O - `true` to indicate success test_network_set_cb( pappl_system_t *system, // I - System void *data, // I - Callback data size_t num_networks, // I - Number of networks pappl_network_t *networks) // I - Networks { (void)system; (void)data; if (num_networks != 2) return (false); memcpy(test_networks, networks, sizeof(test_networks)); return (true); } // // 'test_pwg_raster()' - Run PWG Raster tests. // static bool // O - `true` on success, `false` on failure test_pwg_raster(pappl_system_t *system) // I - System { bool ret = false; // Return value http_t *http = NULL; // HTTP connection char uri[1024], // "printer-uri" value filename[1024] = "", // Print file job_name[1024]; // "job_name" value ipp_t *request, // IPP request *response, // IPP response *supported = NULL; // Supported attributes ipp_attribute_t *mode_supported; // "print-color-mode-supported" attribute int i; // Looping var int job_id; // "job-id" value ipp_jstate_t job_state; // "job-state" value static const char * const modes[] = // "print-color-mode" values { "auto", "auto-monochrome", "color", "monochrome" }; // Connect to system... testBegin("pwg-raster: Connect to server"); if ((http = connect_to_printer(system, false, uri, sizeof(uri))) == NULL) { testEndMessage(false, "Unable to connect: %s", cupsGetErrorString()); return (false); } testEnd(true); // Get printer capabilities testBegin("pwg-raster: Get-Printer-Attributes"); request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/ipp/print"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); supported = cupsDoRequest(http, request, "/ipp/print"); if (cupsGetError() != IPP_STATUS_OK) { testEndMessage(false, "%s", cupsGetErrorString()); goto done; } if ((mode_supported = ippFindAttribute(supported, "print-color-mode-supported", IPP_TAG_KEYWORD)) == NULL) { testEndMessage(false, "missing required 'print-color-mode-supported' attribute in response"); goto done; } testEnd(true); // Loop through the supported print-color-mode values... for (i = 0; i < (int)(sizeof(modes) / sizeof(modes[0])); i ++) { // Make raster data for this mode... testBegin("pwg-raster: Print-Job(%s)", modes[i]); if (!ippContainsString(mode_supported, modes[i])) continue; // Not supported, skip if (!make_raster_file(supported, strstr(modes[i], "monochrome") != NULL, filename, sizeof(filename))) break; // Error // Print the file... snprintf(job_name, sizeof(job_name), "pwg-raster-%s", modes[i]); do { request = ippNewRequest(IPP_OP_PRINT_JOB); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format", NULL, "image/pwg-raster"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, job_name); ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "print-color-mode", NULL, modes[i]); response = cupsDoFileRequest(http, request, "/ipp/print", filename); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { ippDelete(response); response = NULL; sleep(1); } } while (cupsGetError() == IPP_STATUS_ERROR_BUSY); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "Unable to print %s: %s", job_name, cupsGetErrorString()); goto done; } job_id = ippGetInteger(ippFindAttribute(response, "job-id", IPP_TAG_INTEGER), 0); ippDelete(response); testEndMessage(true, "job-id=%d", job_id); output_count ++; // Poll job status until completed... do { sleep(1); testBegin("pwg-raster: Get-Job-Attributes(job-id=%d)", job_id); request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsGetUser()); response = cupsDoRequest(http, request, "/ipp/print"); if (cupsGetError() >= IPP_STATUS_ERROR_BAD_REQUEST) { testEndMessage(false, "Unable to get job state for '%s': %s", job_name, cupsGetErrorString()); goto done; } job_state = (ipp_jstate_t)ippGetInteger(ippFindAttribute(response, "job-state", IPP_TAG_ENUM), 0); testEndMessage(true, "job-state=%d", job_state); ippDelete(response); } while (job_state < IPP_JSTATE_CANCELED); // Cleanup... unlink(filename); } // If we complete the loop without errors, it is a successful run... ret = true; done: if (filename[0]) unlink(filename); httpClose(http); ippDelete(supported); return (ret); } // // 'test_wifi_join_cb()' - Try joining a Wi-Fi network. // // Note: The code here is for a Raspberry Pi running the default Raspberry Pi // OS using wpa_supplicant for Wi-Fi support. Any existing wpa_supplicant.conf // file is backed up. And obviously this means that "testpappl" has to run as // root. // static bool // O - `true` on success, `false` otherwise test_wifi_join_cb( pappl_system_t *sys, // I - System void *data, // I - Callback data (should be "testpappl") const char *ssid, // I - Wi-Fi SSID name const char *psk) // I - Wi-Fi password { cups_file_t *infile, // Old wpa_supplicant.conf file *outfile; // New wpa_supplicant.conf file char line[1024]; // Line from file // Range check input... if (!sys) { fputs("test_wifi_join_cb: System pointer is NULL.\n", stderr); return (false); } if (!data || strcmp((char *)data, "testpappl")) { fprintf(stderr, "test_wifi_join_cb: Bad callback data pointer %p.\n", data); return (false); } if (!ssid || !*ssid || !psk) { fprintf(stderr, "test_wifi_join_cb: Bad SSID '%s' or PSK '%s'.\n", ssid ? ssid : "(null)", psk ? psk : "(null)"); return (false); } if (access("/etc/wpa_supplicant/wpa_supplicant.conf", W_OK)) { // No write access to the wpa_supplicant configuration file, so just assume // that SSID == PSK is OK... bool ok = !strcmp(ssid, psk); // Do SSID and PSK match? if (ok) papplCopyString(current_ssid, ssid, sizeof(current_ssid)); return (ok); } if (rename("/etc/wpa_supplicant/wpa_supplicant.conf", "/etc/wpa_supplicant/wpa_supplicant.conf.O") && errno != ENOENT) { perror("test_wifi_join_cb: Unable to backup '/etc/wpa_supplicant/wpa_supplicant.conf'"); return (false); } if ((outfile = cupsFileOpen("/etc/wpa_supplicant/wpa_supplicant.conf", "w")) == NULL) { perror("test_wifi_join_cb: Unable to create new '/etc/wpa_supplicant/wpa_supplicant.conf' file"); if (rename("/etc/wpa_supplicant/wpa_supplicant.conf.O", "/etc/wpa_supplicant/wpa_supplicant.conf") && errno != ENOENT) perror("test_wifi_join_cb: Unable to restore '/etc/wpa_supplicant/wpa_supplicant.conf'"); return (false); } if ((infile = cupsFileOpen("/etc/wpa_supplicant/wpa_supplicant.conf.O", "r")) == NULL) { // Write standard header for config file on Raspberry Pi OS... cupsFilePuts(outfile, "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n"); cupsFilePuts(outfile, "update_config=1\n"); // can't specify country for 5GHz... Locale is probably not set... } else { // Copy old config file up to the "network={"... Real code might want to // preserve the old network lines to allow for roaming... while (cupsFileGets(infile, line, sizeof(line))) { if (!strncmp(line, "network={", 9)) break; cupsFilePrintf(outfile, "%s\n", line); } cupsFileClose(infile); } // Write a network definition... Production code needs to deal with special // characters! cupsFilePuts(outfile, "network={\n"); cupsFilePrintf(outfile, "\tssid=\"%s\"\n", ssid); if (*psk) cupsFilePrintf(outfile, "\tpsk=\"%s\"\n", psk); else cupsFilePuts(outfile, "\tkey_mgmt=NONE\n"); cupsFilePuts(outfile, "}\n"); cupsFileClose(outfile); // Force re-association... if (system("wpa_cli -i wlan0 reconfigure")) return (false); return (!system("dhclient -v &")); } // // 'test_wifi_list_cb()' - List available Wi-Fi networks. // // Note: The code here is for a Raspberry Pi running the default Raspberry Pi // OS using wpa_supplicant for Wi-Fi support. The Wi-Fi interface name needs // to be "wlan0". // static int // O - Number of Wi-Fi networks test_wifi_list_cb( pappl_system_t *sys, // I - System void *data, // I - Callback data (should be "testpappl") cups_dest_t **ssids) // O - Wi-Fi network list { cups_len_t num_ssids = 0; // Number of Wi-Fi networks cups_dest_t *ssid; // Current Wi-Fi network #if !_WIN32 FILE *fp; // Pipe to "iwlist" command char line[1024], // Line from command *start, // Start of SSID *end; // End of SSID #endif // !_WIN32 if (ssids) *ssids = NULL; if (!sys) { fputs("test_wifi_status_cb: System pointer is NULL.\n", stderr); return (0); } if (!data || strcmp((char *)data, "testpappl")) { fprintf(stderr, "test_wifi_status_cb: Bad callback data pointer %p.\n", data); return (0); } if (!ssids) { fputs("test_wifi_status_cb: ssid pointer is NULL.\n", stderr); return (0); } #if _WIN32 // Just return a dummy list for testing... num_ssids = cupsAddDest("One Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Two Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Red Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Blue Fish", NULL, num_ssids, ssids); if ((ssid = cupsGetDest(current_ssid, NULL, num_ssids, *ssids)) != NULL) ssid->is_default = true; #else // See if we have the iw and iwlist commands... if (access("/sbin/iw", X_OK) || access("/sbin/iwlist", X_OK)) { // No, return a dummy list for testing... num_ssids = cupsAddDest("One Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Two Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Red Fish", NULL, num_ssids, ssids); num_ssids = cupsAddDest("Blue Fish", NULL, num_ssids, ssids); if ((ssid = cupsGetDest(current_ssid, NULL, num_ssids, *ssids)) != NULL) ssid->is_default = true; return ((int)num_ssids); } // Force a Wi-Fi scan... system("/sbin/iw dev wlan0 scan"); sleep(1); // Then read back the list of Wi-Fi networks... if ((fp = popen("/sbin/iwlist wlan0 scanning", "r")) == NULL) { // Can't run command, so no Wi-Fi support... return (0); } while (fgets(line, sizeof(line), fp)) { // Parse line of the form: // // ESSID:"ssid" if ((start = strstr(line, "ESSID:\"")) == NULL) continue; start += 7; if ((end = strchr(start, '\"')) != NULL) { *end = '\0'; if (*start) num_ssids = cupsAddDest(start, NULL, num_ssids, ssids); } } pclose(fp); #endif // _WIN32 return ((int)num_ssids); } // // 'test_wifi_status_cb()' - Check the status of the current Wi-Fi network connection, if any. // // Note: The code here is for a Raspberry Pi running the default Raspberry Pi // OS using wpa_supplicant for Wi-Fi support. The Wi-Fi interface name needs // to be "wlan0". // static pappl_wifi_t * // O - Wi-Fi status or `NULL` on error test_wifi_status_cb( pappl_system_t *system, // I - System void *data, // I - Callback data (should be "testpappl") pappl_wifi_t *wifi_data) // I - Wi-Fi status buffer { #if !_WIN32 FILE *fp; // Pipe to "iwgetid" command char line[1024], // Line from command *ptr; // Pointer into line #endif // !_WIN32 // Range check input... if (wifi_data) { memset(wifi_data, 0, sizeof(pappl_wifi_t)); wifi_data->state = PAPPL_WIFI_STATE_NOT_CONFIGURED; } if (!system) { fputs("test_wifi_status_cb: System pointer is NULL.\n", stderr); return (NULL); } if (!data || strcmp((char *)data, "testpappl")) { fprintf(stderr, "test_wifi_status_cb: Bad callback data pointer %p.\n", data); return (NULL); } if (!wifi_data) { fputs("test_wifi_status_cb: wifi_data pointer is NULL.\n", stderr); return (NULL); } if (current_ssid[0]) { papplCopyString(wifi_data->ssid, current_ssid, sizeof(wifi_data->ssid)); wifi_data->state = PAPPL_WIFI_STATE_ON; return (wifi_data); } #if !_WIN32 // Fill in the Wi-Fi status... This code only returns the 'not-configured' or // 'on' state values for simplicity, but production code should support all of // them. if (access("/sbin/iwgetid", X_OK)) return (wifi_data); // No iwgetid command... if ((fp = popen("/sbin/iwgetid", "r")) == NULL) { // Can't run command, so no Wi-Fi support... return (wifi_data); } if (fgets(line, sizeof(line), fp)) { // Parse line of the form: // // ifname ESSID:"ssid" if ((ptr = strrchr(line, '\"')) != NULL) *ptr = '\0'; // Strip trailing quote if ((ptr = strchr(line, '\"')) != NULL) { // Skip leading quote and copy SSID... ptr ++; papplCopyString(wifi_data->ssid, ptr, sizeof(wifi_data->ssid)); wifi_data->state = PAPPL_WIFI_STATE_ON; } } pclose(fp); if (wifi_data->state == PAPPL_WIFI_STATE_NOT_CONFIGURED) { // Try reading the wpa_supplicant.conf file... if ((fp = fopen("/etc/wpa_supplicant/wpa_supplicant.conf", "r")) != NULL) { while (fgets(line, sizeof(line), fp)) { if ((ptr = strstr(line, "ssid=\"")) != NULL) { papplCopyString(wifi_data->ssid, ptr + 6, sizeof(wifi_data->ssid)); if ((ptr = strchr(wifi_data->ssid, '\"')) != NULL) *ptr = '\0'; wifi_data->state = PAPPL_WIFI_STATE_JOINING; break; } } fclose(fp); } } #endif // !_WIN32 return (wifi_data); } // // 'timer_cb()' - Timer callback. // static bool // O - `true` to continue, `false` to stop timer_cb(pappl_system_t *system, // I - System _pappl_testdata_t *data) // I - Test data { (void)system; if (data->timer_count < (int)(sizeof(data->timer_times) / sizeof(data->timer_times[0]))) data->timer_times[data->timer_count] = time(NULL); data->timer_count ++; papplLog(system, PAPPL_LOGLEVEL_DEBUG, "timer_cb: count=%d", data->timer_count); return (data->timer_count < _PAPPL_MAX_TIMER_COUNT); } // // 'usage()' - Show usage. // static int // O - Exit status usage(int status) // I - Exit status { puts("Usage: testpappl [OPTIONS] [\"SERVER NAME\"]"); puts("Options:"); puts(" --get-id DEVICE-URI Show IEEE-1284 device ID for URI."); puts(" --get-status DEVICE-URI Show printer status for URI."); puts(" --get-supplies DEVICE-URI Show supplies for URI."); puts(" --help Show help"); puts(" --list List devices"); puts(" --list-TYPE Lists devices of TYPE (dns-sd, local, network, usb)"); puts(" --no-tls Do not support TLS"); puts(" --ps-query DEVICE-URI Do a PostScript query to get the product string."); puts(" --version Show version"); puts(" -1 Single queue"); puts(" -A PAM-SERVICE Enable authentication using PAM service"); puts(" -c Do a clean run (no loading of state)"); puts(" -d SPOOL-DIRECTORY Set the spool directory"); puts(" -l LOG-FILE Set the log file"); puts(" -L LOG-LEVEL Set the log level (fatal, error, warn, info, debug)"); puts(" -m DRIVER-NAME Add a printer with the named driver"); puts(" -o OUTPUT-DIRECTORY Set the output directory (default '.')"); puts(" -p PORT Set the listen port (default auto)"); puts(" -t TEST-NAME Run the named test (see below)"); puts(" -T Enable TLS-only mode"); puts(" -U Enable USB printer gadget"); puts(""); puts("Tests:"); puts(" all All of the following tests"); puts(" client Simulated client tests"); puts(" jpeg JPEG image tests"); puts(" png PNG image tests"); puts(" pwg-raster PWG Raster tests"); return (status); } pappl-1.4.9/testsuite/testpappl.h000066400000000000000000000033261476704353100170750ustar00rootroot00000000000000// // Test suite header file for the Printer Application Framework // // Copyright © 2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _TESTPAPPL_H_ # define _TESTPAPPL_H_ // // Include necessary headers... // #include // // Globals... // extern pappl_pr_driver_t pwg_drivers[11]; #ifdef PWG_DRIVER pappl_pr_driver_t pwg_drivers[11] = { // Drivers { "pwg_2inch-203dpi-black_1", "PWG 2inch Label 203DPI Black", NULL, NULL }, { "pwg_2inch-300dpi-black_1", "PWG 2inch Label 300DPI Black", NULL, NULL }, { "pwg_4inch-203dpi-black_1", "PWG 4inch Label 203DPI Black", NULL, NULL }, { "pwg_4inch-300dpi-black_1", "PWG 4inch Label 300DPI Black", NULL, NULL }, { "pwg_common-300dpi-black_1", "PWG Office 300DPI Black", NULL, NULL }, { "pwg_common-300dpi-sgray_8", "PWG Office 300DPI sGray 8-bit", NULL, NULL }, { "pwg_common-300dpi-srgb_8", "PWG Office 300DPI sRGB 8-bit", NULL, NULL }, { "pwg_common-300dpi-600dpi-black_1", "PWG Office 300DPI 600DPI Black", NULL, NULL }, { "pwg_common-300dpi-600dpi-sgray_8", "PWG Office 300DPI 600DPI sGray 8-bit", NULL, NULL }, { "pwg_common-300dpi-600dpi-srgb_8", "PWG Office 300DPI 600DPI sRGB 8-bit", NULL, NULL }, { "pwg_fail-300dpi-black_1", "PWG Always Fails 300DPI Black", NULL, NULL } }; #endif // PWG_DRIVER // // Functions.. // extern const char *pwg_autoadd(const char *device_info, const char *device_uri, const char *device_id, void *data); extern bool pwg_callback(pappl_system_t *system, const char *driver_name, const char *device_uri, const char *device_id, pappl_pr_driver_data_t *driver_data, ipp_t **driver_attrs, void *data); #endif // !_TESTPAPPL_H_ pappl-1.4.9/vcnet/000077500000000000000000000000001476704353100137725ustar00rootroot00000000000000pappl-1.4.9/vcnet/config.h000066400000000000000000000063161476704353100154160ustar00rootroot00000000000000// // Visual Studio configuration header file for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Define MS runtime stuff in the standard headers... // #define _CRT_RAND_S // // Include necessary headers... // #include #include #include #include #include #include #include // // Microsoft renames the POSIX functions to _name, and introduces // a broken compatibility layer using the original names. As a result, // random crashes can occur when, for example, strdup() allocates memory // from a different heap than used by malloc() and free(). // // To avoid moronic problems like this, we #define the POSIX function // names to the corresponding non-standard Microsoft names. // #define access _access #define close _close #define fileno _fileno #define lseek _lseek #define mkdir(d,p) _mkdir(d) #define open _open #define read _read #define rmdir _rmdir #define snprintf _snprintf #define strdup _strdup #define unlink _unlink #define vsnprintf _vsnprintf #define write(f,b,l) _write((f), (b), (unsigned)(l)) // // Microsoft "safe" functions use a different argument order than POSIX... // #define gmtime_r(t,tm) gmtime_s(tm,t) #define localtime_r(t,tm) localtime_s(tm,t) // // Map the POSIX strcasecmp() and strncasecmp() functions to the Win32 // _stricmp() and _strnicmp() functions... // #define strcasecmp _stricmp #define strncasecmp _strnicmp // // Map the POSIX sleep() and usleep() functions to the Win32 Sleep() function... // typedef unsigned long useconds_t; #define sleep(X) Sleep(1000 * (X)) #define usleep(X) Sleep((X)/1000) // // POSIX getpid() is Windows GetCurrentProcessId() // #define getpid GetCurrentProcessId // // Map various parameters to Posix style system calls // # define F_OK 00 # define X_OK 0 # define W_OK 02 # define R_OK 04 # define O_CLOEXEC 0 # define O_CREAT _O_CREAT # define O_EXCL _O_EXCL # define O_NOFOLLOW 0 # define O_RDONLY _O_RDONLY # define O_TRUNC _O_TRUNC # define O_WRONLY _O_WRONLY # define S_ISCHR(m) ((m) & S_IFCHR) # define S_ISDIR(m) ((m) & S_IFDIR) # define S_ISREG(m) ((m) & S_IFREG) // Version numbers #define PAPPL_VERSION "1.4.9" #define PAPPL_VERSION_MAJOR 1 #define PAPPL_VERSION_MINOR 4 // Location of PAPPL state and spool data (when run as root) #define PAPPL_STATEDIR "C:/CUPS/var" // Location of PAPPL domain socket (when run as root) /* #undef PAPPL_SOCKDIR */ // Location of CUPS config files #define CUPS_SERVERROOT "C:/CUPS/etc" // DNS-SD (mDNSResponder or Avahi) #define HAVE_DNSSD 1 #define HAVE_MDNSRESPONDER 1 /* #undef HAVE_AVAHI */ // GNU TLS, LibreSSL/OpenSSL /* #undef HAVE_GNUTLS */ #define HAVE_OPENSSL 1 // libjpeg #define HAVE_LIBJPEG 1 // libpng #define HAVE_LIBPNG 1 // libusb /* #undef HAVE_LIBUSB */ // libpam /* #undef HAVE_LIBPAM */ /* #undef HAVE_SECURITY_PAM_APPL_H */ /* #undef HAVE_PAM_PAM_APPL_H */ // String functions /* #undef HAVE_STRLCPY */ // Random number support /* #undef HAVE_SYS_RANDOM_H */ /* #undef HAVE_ARC4RANDOM */ /* #undef HAVE_GETRANDOM */ /* #undef HAVE_GNUTLS_RND */ pappl-1.4.9/vcnet/copy-dlls.bat000066400000000000000000000011501476704353100163650ustar00rootroot00000000000000:: Script to copy dependent DLLs to the named build directory copy packages\libcups2_native.redist.2.4.11.1\build\native\bin\x64\Debug\*.dll %1 copy packages\libjpeg-turbo-v142.2.0.4.3\build\native\bin\x64\v142\Debug\*.dll %1 copy packages\libressl_native.redist.3.7.3\build\native\bin\x64\Debug\*.dll %1 copy packages\libpng_native.redist.1.6.30\build\native\bin\x64\Debug\*.dll %1 copy packages\libpng_native.redist.1.6.30\build\native\bin\x64\Release\*.dll %1 copy packages\zlib_native.redist.1.2.11\build\native\bin\x64\Debug\*.dll %1 copy packages\zlib_native.redist.1.2.11\build\native\bin\x64\Release\*.dll %1pappl-1.4.9/vcnet/dns_sd.c000066400000000000000000000365611476704353100154230ustar00rootroot00000000000000// // Dynamic wrapper for Bonjour SDK for Windows. // // Copyright 2021 by Michael R Sweet // Copyright 2018 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #include #include // // Pointers for functions... // static int dnssd_initialized = 0; static pthread_mutex_t dnssd_mutex = PTHREAD_MUTEX_INITIALIZER; static DNSServiceErrorType (*dnssd_add_record)(DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint16_t rrtype, uint16_t rdlen, const void *rdata, uint32_t ttl); static DNSServiceErrorType (*dnssd_browse)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, DNSServiceBrowseReply callBack, void *context); static DNSServiceErrorType (*dnssd_construct_full_name)(char * const fullName, const char * const service, const char * const regtype, const char * const domain); static DNSServiceErrorType (*dnssd_create_connection)(DNSServiceRef *sdRef); static DNSServiceErrorType (*dnssd_process_result)(DNSServiceRef sdRef); static DNSServiceErrorType (*dnssd_query_record)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callBack, void *context); static void (*dnssd_deallocate)(DNSServiceRef sdRef); static int (*dnssd_sock_fd)(DNSServiceRef sdRef); static DNSServiceErrorType (*dnssd_register)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, const char *host, uint16_t port, uint16_t txtLen, const void *txtRecord, DNSServiceRegisterReply callBack, void *context); static DNSServiceErrorType (*dnssd_remove_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags); static DNSServiceErrorType (*dnssd_resolve)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, DNSServiceResolveReply callBack, void *context); static DNSServiceErrorType (*dnssd_update_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, uint16_t rdlen, const void *rdata, uint32_t ttl); static void (*dnssd_txt_create)(TXTRecordRef *txtRecord, uint16_t bufferLen, void *buffer); static void (*dnssd_txt_deallocate)(TXTRecordRef *txtRecord); static const void *(*dnssd_txt_get_bytes_ptr)(const TXTRecordRef *txtRecord); static uint16_t (*dnssd_txt_get_count)(uint16_t txtLen, const void *txtRecord); static uint16_t (*dnssd_txt_get_length)(const TXTRecordRef *txtRecord); static DNSServiceErrorType (*dnssd_txt_get_item_at_index)(uint16_t txtLen, const void *txtRecord, uint16_t itemIndex, uint16_t keyBufLen, char *key, uint8_t *valueLen, const void **value); static const void *(*dnssd_txt_get_value_ptr)(uint16_t txtLen, const void *txtRecord, const char *key, uint8_t *valueLen); static DNSServiceErrorType (*dnssd_txt_set_value)(TXTRecordRef *txtRecord, const char *key, uint8_t valueSize, const void *value); // // 'dnssd_init()' - Initialize function pointers... // static void dnssd_init(void) { pthread_mutex_lock(&dnssd_mutex); if (!dnssd_initialized) { HINSTANCE dll_handle = LoadLibraryA("dnssd.dll"); if (dll_handle) { dnssd_add_record = (DNSServiceErrorType (*)(DNSServiceRef, DNSRecordRef *, DNSServiceFlags, uint16_t, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceAddRecord"); dnssd_browse = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, DNSServiceBrowseReply, void *))GetProcAddress(dll_handle, "DNSServiceBrowse"); dnssd_construct_full_name = (DNSServiceErrorType(*)(char * const, const char * const, const char * const, const char * const))GetProcAddress(dll_handle, "DNSServiceConstructFullName"); dnssd_create_connection = (DNSServiceErrorType(*)(DNSServiceRef *))GetProcAddress(dll_handle, "DNSServiceCreateConnection"); dnssd_deallocate = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefDeallocate"); dnssd_process_result = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceProcessResult"); dnssd_query_record = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, uint16_t, uint16_t, DNSServiceQueryRecordReply, void *))GetProcAddress(dll_handle, "DNSServiceQueryRecord"); dnssd_register = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, const char *, uint16_t, uint16_t, const void *, DNSServiceRegisterReply, void *))GetProcAddress(dll_handle, "DNSServiceRegister"); dnssd_remove_record = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags))GetProcAddress(dll_handle, "DNSServiceRemoveRecord"); dnssd_resolve = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, DNSServiceResolveReply, void *))GetProcAddress(dll_handle, "DNSServiceResolve"); dnssd_sock_fd = (int(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefSockFD"); dnssd_update_record = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceUpdateRecord"); dnssd_txt_create = (void (*)(TXTRecordRef *, uint16_t, void *))GetProcAddress(dll_handle, "TXTRecordCreate"); dnssd_txt_deallocate = (void (*)(TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordDeallocate"); dnssd_txt_get_bytes_ptr = (const void *(*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetBytesPtr"); dnssd_txt_get_count = (uint16_t (*)(uint16_t, const void *))GetProcAddress(dll_handle, "TXTRecordGetCount"); dnssd_txt_get_item_at_index = (DNSServiceErrorType (*)(uint16_t, const void *, uint16_t, uint16_t, char *, uint8_t *, const void **))GetProcAddress(dll_handle, "TXTRecordGetItemAtIndex"); dnssd_txt_get_length = (uint16_t (*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetLength"); dnssd_txt_get_value_ptr = (const void *(*)(uint16_t, const void *, const char *, uint8_t *))GetProcAddress(dll_handle, "TXTRecordGetValuePtr"); dnssd_txt_set_value = (DNSServiceErrorType (*)(TXTRecordRef *, const char *, uint8_t, const void *))GetProcAddress(dll_handle, "TXTRecordSetValue"); } dnssd_initialized = 1; } pthread_mutex_unlock(&dnssd_mutex); } // DNSServiceAddRecord DNSServiceErrorType DNSSD_API DNSServiceAddRecord ( DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint16_t rrtype, uint16_t rdlen, const void *rdata, uint32_t ttl ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_add_record) return (*dnssd_add_record)(sdRef, RecordRef, flags, rrtype, rdlen, rdata, ttl); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceBrowse DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, /* may be NULL */ DNSServiceBrowseReply callBack, void *context /* may be NULL */ ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_browse) return (*dnssd_browse)(sdRef, flags, interfaceIndex, regtype, domain, callBack, context); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceConstructFullName DNSServiceErrorType DNSSD_API DNSServiceConstructFullName ( char * const fullName, const char * const service, /* may be NULL */ const char * const regtype, const char * const domain ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_construct_full_name) return (*dnssd_construct_full_name)(fullName, service, regtype, domain); else return (-1); } // DNSServiceCreateConnection DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) { if (!dnssd_initialized) dnssd_init(); if (dnssd_create_connection) return (*dnssd_create_connection)(sdRef); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceProcessResult DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef) { if (!dnssd_initialized) dnssd_init(); if (dnssd_process_result) return (*dnssd_process_result)(sdRef); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceQueryRecord DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callBack, void *context /* may be NULL */ ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_query_record) return (*dnssd_query_record)(sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceRefDeallocate void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) { if (!dnssd_initialized) dnssd_init(); if (dnssd_deallocate) (*dnssd_deallocate)(sdRef); } // DNSServiceRefSockFD int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) { if (!dnssd_initialized) dnssd_init(); if (dnssd_sock_fd) return (*dnssd_sock_fd)(sdRef); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceRegister DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, /* may be NULL */ const char *regtype, const char *domain, /* may be NULL */ const char *host, /* may be NULL */ uint16_t port, /* In network byte order */ uint16_t txtLen, const void *txtRecord, /* may be NULL */ DNSServiceRegisterReply callBack, /* may be NULL */ void *context /* may be NULL */ ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_register) return (*dnssd_register)(sdRef, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceRemoveRecord DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_remove_record) return (*dnssd_remove_record)(sdRef, RecordRef, flags); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceResolve DNSServiceErrorType DNSSD_API DNSServiceResolve ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, DNSServiceResolveReply callBack, void *context /* may be NULL */ ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_resolve) return (*dnssd_resolve)(sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context); else return (kDNSServiceErr_ServiceNotRunning); } // DNSServiceUpdateRecord DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, /* may be NULL */ DNSServiceFlags flags, uint16_t rdlen, const void *rdata, uint32_t ttl ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_update_record) return (*dnssd_update_record)(sdRef, RecordRef, flags, rdlen, rdata, ttl); else return (kDNSServiceErr_ServiceNotRunning); } // TXTRecordCreate void DNSSD_API TXTRecordCreate( TXTRecordRef *txtRecord, uint16_t bufferLen, void *buffer) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_create) (*dnssd_txt_create)(txtRecord, bufferLen, buffer); } // TXTRecordDeallocate void DNSSD_API TXTRecordDeallocate ( TXTRecordRef *txtRecord ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_deallocate) (*dnssd_txt_deallocate)(txtRecord); } // TXTRecordGetBytesPtr const void * DNSSD_API TXTRecordGetBytesPtr ( const TXTRecordRef *txtRecord ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_get_bytes_ptr) return (*dnssd_txt_get_bytes_ptr)(txtRecord); else return (NULL); } // TXTRecordGetLength uint16_t DNSSD_API TXTRecordGetLength ( const TXTRecordRef *txtRecord ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_get_length) return (*dnssd_txt_get_length)(txtRecord); else return (0); } // TXTRecordSetValue DNSServiceErrorType DNSSD_API TXTRecordSetValue ( TXTRecordRef *txtRecord, const char *key, uint8_t valueSize, /* may be zero */ const void *value /* may be NULL */ ) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_set_value) return (*dnssd_txt_set_value)(txtRecord, key, valueSize, value); else return (-1); } // TXTRecordGetCount uint16_t DNSSD_API TXTRecordGetCount( uint16_t txtLen, const void *txtRecord) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_get_count) return (*dnssd_txt_get_count)(txtLen, txtRecord); else return (0); } // TXTRecordGetItemAtIndex DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex( uint16_t txtLen, const void *txtRecord, uint16_t itemIndex, uint16_t keyBufLen, char *key, uint8_t *valueLen, const void **value) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_get_item_at_index) return (*dnssd_txt_get_item_at_index)(txtLen, txtRecord, itemIndex, keyBufLen, key, valueLen, value); else return (-1); } // TXTRecordGetValuePtr const void * DNSSD_API TXTRecordGetValuePtr( uint16_t txtLen, const void *txtRecord, const char *key, uint8_t *valueLen) { if (!dnssd_initialized) dnssd_init(); if (dnssd_txt_get_value_ptr) return (*dnssd_txt_get_value_ptr)(txtLen, txtRecord, key, valueLen); else return (NULL); } pappl-1.4.9/vcnet/libpappl1.vcxproj000066400000000000000000000367211476704353100173040ustar00rootroot00000000000000 Debug-Messages x64 Debug x64 Release x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1} libpappl1 Win32Proj 10.0 DynamicLibrary v142 Unicode DynamicLibrary v142 Unicode DynamicLibrary v142 Unicode <_ProjectFileVersion>12.0.30501.0 $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ false $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ false $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ false X64 Disabled packages\libpng_native.1.6.30\build\native\include;packages\libjpeg-turbo-v142.2.0.4.3\build\native\include;packages\libressl_native.3.7.3\build\native\include;..\vcnet;..;%(AdditionalIncludeDirectories) _DEBUG;_WINDOWS;_USRDLL;LIBPAPPL1_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true Level3 ProgramDatabase packages\libcups2_native.2.4.11.1\build\native\lib\x64\Debug\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libpng_native.1.6.30\build\native\lib\x64\Debug\libpng16d.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Debug\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) $(OutDir)libpappl1.dll ..\pappl\libpappl1.def true $(Platform)\$(Configuration)\libpappl1.pdb Windows $(OutDir)libpappl1.lib MachineX64 X64 Disabled packages\libpng_native.1.6.30\build\native\include;packages\libjpeg-turbo-v142.2.0.4.3\build\native\include;packages\libressl_native.3.7.3\build\native\include;..\vcnet;..;%(AdditionalIncludeDirectories) DEBUG;_DEBUG;_WINDOWS;_USRDLL;LIBPAPPL1_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true Level3 ProgramDatabase packages\libcups2_native.2.4.11.1\build\native\lib\x64\Debug\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libpng_native.1.6.30\build\native\lib\x64\Debug\libpng16d.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Debug\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) $(OutDir)libpappl1.dll ..\pappl\libpappl1.def true $(Platform)\$(Configuration)\libpappl1.pdb Windows $(OutDir)libpappl1.lib MachineX64 X64 MinSpace packages\libpng_native.1.6.30\build\native\include;packages\libjpeg-turbo-v142.2.0.4.3\build\native\include;packages\libressl_native.3.7.3\build\native\include;..\vcnet;..;%(AdditionalIncludeDirectories) NDEBUG;_WINDOWS;_USRDLL;LIBPAPPL1_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase packages\libcups2_native.2.4.11.1\build\native\lib\x64\Release\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libpng_native.1.6.30\build\native\lib\x64\Release\libpng16.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Release\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) $(OutDir)libpappl1.dll ..\pappl\libpappl1.def true $(Platform)\$(Configuration)\libpappl1.pdb Windows true true $(OutDir)libpappl1.lib MachineX64 This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. pappl-1.4.9/vcnet/libpappl1.vcxproj.filters000066400000000000000000000127401476704353100207460ustar00rootroot00000000000000 Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers Headers {576e4523-9a4c-4e9e-b10e-56c059ee8296} Headers Headers pappl-1.4.9/vcnet/libpappl1.vcxproj.user000066400000000000000000000002451476704353100202510ustar00rootroot00000000000000 pappl-1.4.9/vcnet/libpappl1_native.nuspec000066400000000000000000000047601476704353100204520ustar00rootroot00000000000000 libpappl1_native Printer Application Framework (PAPPL) for VS2019+ 1.4.9.0 Michael R Sweet michaelrsweet https://github.com/michaelrsweet/pappl Apache-2.0 build/native/pappl-128.png build/native/README.md false Printer Application Framework (PAPPL) for VS2019+ PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. PAPPL is licensed under the Apache License Version 2.0 with an exception to allow linking against GNU GPL2-only software. Copyright © 2019-2025 by Michael R Sweet airprint everywhere http ipp mopria native pappl-1.4.9/vcnet/libpappl1_native.props000066400000000000000000000007701476704353100203150ustar00rootroot00000000000000 $(MSBuildThisFileDirectory)\include $(MSBuildThisFileDirectory)\lib\$(Platform)\$(Configuration)\libpappl1.lib;%(AdditionalDependencies) pappl-1.4.9/vcnet/libpappl1_native.redist.nuspec000066400000000000000000000036531476704353100217430ustar00rootroot00000000000000 libpappl1_native.redist Printer Application Framework (PAPPL) for VS2019+ Redist 1.4.9.0 Michael R Sweet michaelrsweet https://github.com/michaelrsweet/pappl Apache-2.0 build/native/pappl-128.png build/native/README.md false Redistributable components for package 'libpappl1_native'. This package should only be installed as a dependency. PAPPL is a simple C-based framework/library for developing CUPS Printer Applications, which are the recommended replacement for printer drivers. This package provides the redistributable content for PAPPL. PAPPL is licensed under the Apache License Version 2.0 with an exception to allow linking against GNU GPL2-only software. Copyright © 2019-2025 by Michael R Sweet airprint everywhere http ipp mopria native pappl-1.4.9/vcnet/packages.config000066400000000000000000000014171476704353100167420ustar00rootroot00000000000000 pappl-1.4.9/vcnet/pappl.sln000066400000000000000000000035331476704353100156300ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30204.135 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpappl1", "libpappl1.vcxproj", "{5435F0D7-04B1-4C78-8713-4F109F507FD1}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpappl", "testpappl.vcxproj", "{9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug-Messages|x64 = Debug-Messages|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Debug|x64.ActiveCfg = Debug|x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Debug|x64.Build.0 = Debug|x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Debug-Messages|x64.ActiveCfg = Debug-Messages|x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Debug-Messages|x64.Build.0 = Debug-Messages|x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Release|x64.ActiveCfg = Release|x64 {5435F0D7-04B1-4C78-8713-4F109F507FD1}.Release|x64.Build.0 = Release|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Debug|x64.ActiveCfg = Debug|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Debug|x64.Build.0 = Debug|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Debug-Messages|x64.ActiveCfg = Debug-Messages|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Debug-Messages|x64.Build.0 = Debug-Messages|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Release|x64.ActiveCfg = Release|x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {32935B57-C6C7-4226-8BEE-63542B7B793F} EndGlobalSection EndGlobal pappl-1.4.9/vcnet/testpappl.vcxproj000066400000000000000000000265261476704353100174360ustar00rootroot00000000000000 Debug-Messages x64 Debug x64 Release x64 {9B67ACCB-EE1A-47A0-AEE1-642AF30B2253} Win32Proj 10.0 Application v142 Unicode Application v142 Unicode Application v142 Unicode <_ProjectFileVersion>12.0.30501.0 $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ true $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ true $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\$(ProjectName)\ false Disabled ..\vcnet;..;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase $(OutDir)testpappl.exe true $(OutDir)testpappl.pdb Console false packages\libcups2_native.2.4.11.1\build\native\lib\x64\Debug\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Debug\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) Disabled ..\vcnet;..;%(AdditionalIncludeDirectories) WIN32;DEBUG;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase $(OutDir)testpappl.exe true $(OutDir)testpappl.pdb Console false packages\libcups2_native.2.4.11.1\build\native\lib\x64\Debug\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Debug\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) ..\vcnet;..;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreaded Level3 $(OutDir)testpappl.exe true Console true true false packages\libcups2_native.2.4.11.1\build\native\lib\x64\Release\libcups2.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\ssl.lib;packages\libressl_native.3.7.3\build\native\lib\x64\Release\crypto.lib;packages\libjpeg-turbo-v142.2.0.4.3\build\native\lib\x64\v142\Release\jpeg.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies) {5435F0D7-04B1-4C78-8713-4F109F507FD1} false This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. pappl-1.4.9/vcnet/testpappl.vcxproj.user000066400000000000000000000030111476704353100203730ustar00rootroot00000000000000 -c -l testpappl.log -o testpappl.output -t all false WindowsLocalDebugger $(ProjectDir)\$(Platform)\$(Configuration) -c -l testpappl.log -o testpappl.output -t api,client,pwg-raster WindowsLocalDebugger $(ProjectDir)\$(Platform)\$(Configuration) -c -l testpappl.log -o testpappl.output -t api,client,pwg-raster WindowsLocalDebugger $(ProjectDir)\$(Platform)\$(Configuration) CUPS_DEBUG_LOG=testpappl-cups.log CUPS_DEBUG_LEVEL=4 CUPS_DEBUG_FILTER=^(http|_http|ipp|_ipp|cupsDo|cupsGet|cupsSend) pappl-1.4.9/xcode/000077500000000000000000000000001476704353100137555ustar00rootroot00000000000000pappl-1.4.9/xcode/Info.plist000066400000000000000000000015711476704353100157310ustar00rootroot00000000000000 CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString $(CURRENT_PROJECT_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright Copyright © 2019-2023 Michael Sweet. All rights reserved. pappl-1.4.9/xcode/config.h000066400000000000000000000022421476704353100153730ustar00rootroot00000000000000// // Xcode configuration header file for the Printer Application Framework // // Copyright © 2019-2025 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Version numbers #define PAPPL_VERSION "1.4.9" #define PAPPL_VERSION_MAJOR 1 #define PAPPL_VERSION_MINOR 4 // Location of PAPPL state and spool data (when run as root) #define PAPPL_STATEDIR "/Library" // Location of PAPPL domain socket (when run as root) #define PAPPL_SOCKDIR "/private/var/run" // Location of CUPS config files #define CUPS_SERVERROOT "/private/etc/cups" // DNS-SD (mDNSResponder or Avahi) #define HAVE_DNSSD 1 #define HAVE_MDNSRESPONDER 1 /* #undef HAVE_AVAHI */ // GNU TLS, LibreSSL/OpenSSL /* #undef HAVE_GNUTLS */ #define HAVE_OPENSSL 1 // libjpeg #define HAVE_LIBJPEG 1 // libpng #define HAVE_LIBPNG 1 // libusb #define HAVE_LIBUSB 1 // libpam #define HAVE_LIBPAM 1 #define HAVE_SECURITY_PAM_APPL_H 1 /* #undef HAVE_PAM_PAM_APPL_H */ // String functions #define HAVE_STRLCPY 1 // Random number support #define HAVE_SYS_RANDOM_H 1 #define HAVE_ARC4RANDOM 1 /* #undef HAVE_GETRANDOM */ /* #undef HAVE_GNUTLS_RND */ pappl-1.4.9/xcode/pappl.xcodeproj/000077500000000000000000000000001476704353100170655ustar00rootroot00000000000000pappl-1.4.9/xcode/pappl.xcodeproj/project.pbxproj000066400000000000000000003253141476704353100221510ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ 27FFF2FA24328E24003C0B8F /* All */ = { isa = PBXAggregateTarget; buildConfigurationList = 27FFF2FB24328E24003C0B8F /* Build configuration list for PBXAggregateTarget "All" */; buildPhases = ( ); dependencies = ( 27FFF39E24329D3B003C0B8F /* PBXTargetDependency */, 27FFF3A024329D3B003C0B8F /* PBXTargetDependency */, 27E8659025F1774C00A8F8D9 /* PBXTargetDependency */, 274AD665253F52C90033CAAB /* PBXTargetDependency */, 27FFF30124328E31003C0B8F /* PBXTargetDependency */, ); name = All; productName = All; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ 27134E6C2548D1CD004D9027 /* system-printer.c in Sources */ = {isa = PBXBuildFile; fileRef = 27134E6B2548D1CD004D9027 /* system-printer.c */; }; 27134E6D2548D1CD004D9027 /* system-printer.c in Sources */ = {isa = PBXBuildFile; fileRef = 27134E6B2548D1CD004D9027 /* system-printer.c */; }; 2719D1B524732B1800299DA1 /* dnssd-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2719D1B424732B1700299DA1 /* dnssd-private.h */; }; 2719D1B624732B1800299DA1 /* dnssd-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2719D1B424732B1700299DA1 /* dnssd-private.h */; }; 27214FA524ED72B400E36FFC /* device-network.c in Sources */ = {isa = PBXBuildFile; fileRef = 27214FA324ED72B300E36FFC /* device-network.c */; }; 27214FA624ED72B400E36FFC /* device-network.c in Sources */ = {isa = PBXBuildFile; fileRef = 27214FA324ED72B300E36FFC /* device-network.c */; }; 27214FA724ED72B400E36FFC /* device-usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 27214FA424ED72B400E36FFC /* device-usb.c */; }; 27214FA824ED72B400E36FFC /* device-usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 27214FA424ED72B400E36FFC /* device-usb.c */; }; 27214FAA24ED72D600E36FFC /* device-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27214FA924ED72D600E36FFC /* device-private.h */; }; 27214FAB24ED72D600E36FFC /* device-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27214FA924ED72D600E36FFC /* device-private.h */; }; 2725631A243D629000A38E9F /* system-loadsave.c in Sources */ = {isa = PBXBuildFile; fileRef = 27256319243D628F00A38E9F /* system-loadsave.c */; }; 2725631B243D629000A38E9F /* system-loadsave.c in Sources */ = {isa = PBXBuildFile; fileRef = 27256319243D628F00A38E9F /* system-loadsave.c */; }; 2737B04824B3598400E6F38C /* log-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2737B04624B3598400E6F38C /* log-private.h */; }; 2737B04924B3598400E6F38C /* log-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2737B04624B3598400E6F38C /* log-private.h */; }; 2737B04A24B3598400E6F38C /* resource-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2737B04724B3598400E6F38C /* resource-private.h */; }; 2737B04B24B3598400E6F38C /* resource-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2737B04724B3598400E6F38C /* resource-private.h */; }; 274AD642253F52B10033CAAB /* pwg-driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 274A1ED7242E7E1300DE387E /* pwg-driver.c */; }; 274AD645253F52B10033CAAB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */; }; 274AD646253F52B10033CAAB /* libusb-1.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */; }; 274AD647253F52B10033CAAB /* libpng16.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31824329B4A003C0B8F /* libpng16.a */; }; 274AD648253F52B10033CAAB /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E62415EBD70082CEA3 /* libjpeg.a */; }; 274AD649253F52B10033CAAB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31324329B2D003C0B8F /* Security.framework */; }; 274AD64A253F52B10033CAAB /* libpappl_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF30824329AAF003C0B8F /* libpappl_static.a */; }; 274AD64B253F52B10033CAAB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E32415EBA80082CEA3 /* IOKit.framework */; }; 274AD64C253F52B10033CAAB /* libpam.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */; }; 274AD64D253F52B10033CAAB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */; }; 274AD64E253F52B10033CAAB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */; }; 274AD64F253F52B10033CAAB /* libcups.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DF2415EB980082CEA3 /* libcups.tbd */; }; 274AD667253F52E30033CAAB /* testmainloop.c in Sources */ = {isa = PBXBuildFile; fileRef = 274AD666253F52E30033CAAB /* testmainloop.c */; }; 2763648425223F3200949C0B /* printer-usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 2763648325223F3200949C0B /* printer-usb.c */; }; 2763648525223F3200949C0B /* printer-usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 2763648325223F3200949C0B /* printer-usb.c */; }; 2767F42F2797841E00BE323A /* system-subscription.c in Sources */ = {isa = PBXBuildFile; fileRef = 2767F42E2797841E00BE323A /* system-subscription.c */; }; 2767F4302797841E00BE323A /* system-subscription.c in Sources */ = {isa = PBXBuildFile; fileRef = 2767F42E2797841E00BE323A /* system-subscription.c */; }; 2767F4322797AC3A00BE323A /* subscription.c in Sources */ = {isa = PBXBuildFile; fileRef = 2767F4312797AC3A00BE323A /* subscription.c */; }; 2767F4332797AC3A00BE323A /* subscription.c in Sources */ = {isa = PBXBuildFile; fileRef = 2767F4312797AC3A00BE323A /* subscription.c */; }; 2767F4352797AD5800BE323A /* subscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 2767F4342797AD5800BE323A /* subscription.h */; }; 2767F4362797AD5800BE323A /* subscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 2767F4342797AD5800BE323A /* subscription.h */; }; 2767F4382799F0C200BE323A /* subscription-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2767F4372799F0C200BE323A /* subscription-private.h */; }; 2767F4392799F0C200BE323A /* subscription-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2767F4372799F0C200BE323A /* subscription-private.h */; }; 276EED8227AC7BEA007F9AC1 /* system-status-macos.m in Sources */ = {isa = PBXBuildFile; fileRef = 276EED7E27AC7BE9007F9AC1 /* system-status-macos.m */; }; 276EED8327AC7BEA007F9AC1 /* system-status-macos.m in Sources */ = {isa = PBXBuildFile; fileRef = 276EED7E27AC7BE9007F9AC1 /* system-status-macos.m */; }; 2774C75227DBCECE00A7C96D /* system-loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74D27DBCECE00A7C96D /* system-loc.c */; }; 2774C75327DBCECE00A7C96D /* system-loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74D27DBCECE00A7C96D /* system-loc.c */; }; 2774C75427DBCECE00A7C96D /* loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74E27DBCECE00A7C96D /* loc.c */; }; 2774C75527DBCECE00A7C96D /* loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74E27DBCECE00A7C96D /* loc.c */; }; 2774C75627DBCECE00A7C96D /* client-loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74F27DBCECE00A7C96D /* client-loc.c */; }; 2774C75727DBCECE00A7C96D /* client-loc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2774C74F27DBCECE00A7C96D /* client-loc.c */; }; 2774C75827DBCECE00A7C96D /* loc-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2774C75027DBCECE00A7C96D /* loc-private.h */; }; 2774C75927DBCECE00A7C96D /* loc-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2774C75027DBCECE00A7C96D /* loc-private.h */; }; 2774C75A27DBCECE00A7C96D /* loc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2774C75127DBCECE00A7C96D /* loc.h */; }; 2774C75B27DBCECE00A7C96D /* loc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2774C75127DBCECE00A7C96D /* loc.h */; }; 279EC3D227FA4B930079A47D /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D027FA4B930079A47D /* libcrypto.a */; }; 279EC3D327FA4B930079A47D /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D127FA4B930079A47D /* libssl.a */; }; 279EC3D427FA4BB90079A47D /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D027FA4B930079A47D /* libcrypto.a */; }; 279EC3D527FA4BB90079A47D /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D127FA4B930079A47D /* libssl.a */; }; 279EC3D627FA4BCC0079A47D /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D027FA4B930079A47D /* libcrypto.a */; }; 279EC3D727FA4BCC0079A47D /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279EC3D127FA4B930079A47D /* libssl.a */; }; 27A56492256769A9009501BD /* printer-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A56490256769A9009501BD /* printer-ipp.c */; }; 27A56493256769A9009501BD /* printer-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A56490256769A9009501BD /* printer-ipp.c */; }; 27A56494256769A9009501BD /* system-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A56491256769A9009501BD /* system-ipp.c */; }; 27A56495256769A9009501BD /* system-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A56491256769A9009501BD /* system-ipp.c */; }; 27A564A625676AE3009501BD /* client-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A564A525676AE3009501BD /* client-ipp.c */; }; 27A564A725676AE3009501BD /* client-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A564A525676AE3009501BD /* client-ipp.c */; }; 27A564B325677057009501BD /* job-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A564B225677057009501BD /* job-ipp.c */; }; 27A564B425677057009501BD /* job-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A564B225677057009501BD /* job-ipp.c */; }; 27AB72B424740B3400691FE7 /* link.c in Sources */ = {isa = PBXBuildFile; fileRef = 27AB72B324740B3300691FE7 /* link.c */; }; 27AB72B524740B3400691FE7 /* link.c in Sources */ = {isa = PBXBuildFile; fileRef = 27AB72B324740B3300691FE7 /* link.c */; }; 27BFDDCA279EF534000D073A /* subscription-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27BFDDC9279EF534000D073A /* subscription-ipp.c */; }; 27BFDDCB279EF534000D073A /* subscription-ipp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27BFDDC9279EF534000D073A /* subscription-ipp.c */; }; 27D676232493D73E008F734C /* mainloop-subcommands.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D6761F2493D73D008F734C /* mainloop-subcommands.c */; }; 27D676242493D73E008F734C /* mainloop-subcommands.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D6761F2493D73D008F734C /* mainloop-subcommands.c */; }; 27D676252493D73E008F734C /* mainloop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D676202493D73E008F734C /* mainloop.c */; }; 27D676262493D73E008F734C /* mainloop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D676202493D73E008F734C /* mainloop.c */; }; 27D676272493D73E008F734C /* mainloop.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D676212493D73E008F734C /* mainloop.h */; }; 27D676282493D73E008F734C /* mainloop.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D676212493D73E008F734C /* mainloop.h */; }; 27D676292493D73E008F734C /* mainloop-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D676222493D73E008F734C /* mainloop-private.h */; }; 27D6762A2493D73E008F734C /* mainloop-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27D676222493D73E008F734C /* mainloop-private.h */; }; 27D6762C2493EF96008F734C /* mainloop-support.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D6762B2493EF95008F734C /* mainloop-support.c */; }; 27D6762D2493EF96008F734C /* mainloop-support.c in Sources */ = {isa = PBXBuildFile; fileRef = 27D6762B2493EF95008F734C /* mainloop-support.c */; }; 27DF62F12450992D00501447 /* job-filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 27DF62F02450992D00501447 /* job-filter.c */; }; 27DF62F22450992D00501447 /* job-filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 27DF62F02450992D00501447 /* job-filter.c */; }; 27E5AEA3246B6A4800FFD958 /* printer-raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E5AEA2246B6A4700FFD958 /* printer-raw.c */; }; 27E5AEA4246B6A4800FFD958 /* printer-raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E5AEA2246B6A4700FFD958 /* printer-raw.c */; }; 27E8654725F176C700A8F8D9 /* httpmon-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E8654525F176C700A8F8D9 /* httpmon-private.h */; }; 27E8654825F176C700A8F8D9 /* httpmon-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E8654525F176C700A8F8D9 /* httpmon-private.h */; }; 27E8654925F176C700A8F8D9 /* httpmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E8654625F176C700A8F8D9 /* httpmon.c */; }; 27E8654A25F176C700A8F8D9 /* httpmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E8654625F176C700A8F8D9 /* httpmon.c */; }; 27E8655725F176FB00A8F8D9 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */; }; 27E8655825F176FB00A8F8D9 /* libusb-1.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */; }; 27E8655925F176FB00A8F8D9 /* libpng16.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31824329B4A003C0B8F /* libpng16.a */; }; 27E8655A25F176FB00A8F8D9 /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E62415EBD70082CEA3 /* libjpeg.a */; }; 27E8655B25F176FB00A8F8D9 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31324329B2D003C0B8F /* Security.framework */; }; 27E8655C25F176FB00A8F8D9 /* libpappl_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF30824329AAF003C0B8F /* libpappl_static.a */; }; 27E8655D25F176FB00A8F8D9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E32415EBA80082CEA3 /* IOKit.framework */; }; 27E8655E25F176FB00A8F8D9 /* libpam.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */; }; 27E8655F25F176FB00A8F8D9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */; }; 27E8656025F176FB00A8F8D9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */; }; 27E8656125F176FB00A8F8D9 /* libcups.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DF2415EB980082CEA3 /* libcups.tbd */; }; 27E8657425F1771700A8F8D9 /* testhttpmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E8657325F1771700A8F8D9 /* testhttpmon.c */; }; 27E8658125F1773E00A8F8D9 /* pwg-driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 274A1ED7242E7E1300DE387E /* pwg-driver.c */; }; 27E8658225F1773E00A8F8D9 /* testpappl.c in Sources */ = {isa = PBXBuildFile; fileRef = 274A1ED8242E7E1300DE387E /* testpappl.c */; }; 27F4285824F4080600C7ADCE /* device-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F4285724F4080600C7ADCE /* device-file.c */; }; 27F4285924F4080600C7ADCE /* device-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F4285724F4080600C7ADCE /* device-file.c */; }; 27FF08F9282EE88A00DAFC7D /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */; }; 27FF08FB282EE89A00DAFC7D /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */; }; 27FF08FC282EEA4200DAFC7D /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */; }; 27FF08FD282EEA4900DAFC7D /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */; }; 27FF08FE282EEA5200DAFC7D /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */; }; 27FF08FF282EEA5700DAFC7D /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */; }; 27FF0900282EEA5D00DAFC7D /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */; }; 27FF0901282EEA6200DAFC7D /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */; }; 27FFF3032432901A003C0B8F /* libcups.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DF2415EB980082CEA3 /* libcups.tbd */; }; 27FFF30E24329B2D003C0B8F /* libpappl_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF30824329AAF003C0B8F /* libpappl_static.a */; }; 27FFF30F24329B2D003C0B8F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E32415EBA80082CEA3 /* IOKit.framework */; }; 27FFF31024329B2D003C0B8F /* libpam.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */; }; 27FFF31124329B2D003C0B8F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */; }; 27FFF31224329B2D003C0B8F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */; }; 27FFF31524329B2D003C0B8F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31324329B2D003C0B8F /* Security.framework */; }; 27FFF31724329B4A003C0B8F /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E62415EBD70082CEA3 /* libjpeg.a */; }; 27FFF31924329B4A003C0B8F /* libpng16.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31824329B4A003C0B8F /* libpng16.a */; }; 27FFF31A24329B61003C0B8F /* base.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C66240D8896001D2A90 /* base.h */; }; 27FFF31B24329B61003C0B8F /* base-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5F3241E72910082CEA3 /* base-private.h */; }; 27FFF31C24329B61003C0B8F /* client.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6E240D8896001D2A90 /* client.h */; }; 27FFF31D24329B61003C0B8F /* client-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8D240D9067001D2A90 /* client-private.h */; }; 27FFF31E24329B61003C0B8F /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6C240D8896001D2A90 /* client.c */; }; 27FFF31F24329B61003C0B8F /* client-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377224119E39008AECA4 /* client-accessors.c */; }; 27FFF32024329B61003C0B8F /* client-auth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6F240D8896001D2A90 /* client-auth.c */; }; 27FFF32124329B61003C0B8F /* client-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EE39CE242AE7D800179844 /* client-webif.c */; }; 27FFF32224329B61003C0B8F /* config.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C87240D8E69001D2A90 /* config.h */; }; 27FFF32324329B61003C0B8F /* contact.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F656E72430DBFC00055A4D /* contact.c */; }; 27FFF32424329B61003C0B8F /* device.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C65240D8896001D2A90 /* device.h */; }; 27FFF32524329B61003C0B8F /* device.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6B240D8896001D2A90 /* device.c */; }; 27FFF32624329B61003C0B8F /* dnssd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C73240D8896001D2A90 /* dnssd.c */; }; 27FFF32924329B61003C0B8F /* job.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C70240D8896001D2A90 /* job.h */; }; 27FFF32A24329B61003C0B8F /* job-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8C240D9067001D2A90 /* job-private.h */; }; 27FFF32B24329B61003C0B8F /* job.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C64240D8896001D2A90 /* job.c */; }; 27FFF32C24329B61003C0B8F /* job-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377524119E3A008AECA4 /* job-accessors.c */; }; 27FFF32D24329B61003C0B8F /* job-process.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C74240D8896001D2A90 /* job-process.c */; }; 27FFF32E24329B61003C0B8F /* log.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8A240D9066001D2A90 /* log.h */; }; 27FFF32F24329B61003C0B8F /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C72240D8896001D2A90 /* log.c */; }; 27FFF33024329B61003C0B8F /* lookup.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5ED241C85DF0082CEA3 /* lookup.c */; }; 27FFF33124329B61003C0B8F /* pappl.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C68240D8896001D2A90 /* pappl.h */; }; 27FFF33224329B61003C0B8F /* pappl-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C69240D8896001D2A90 /* pappl-private.h */; }; 27FFF33324329B61003C0B8F /* printer.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C63240D8896001D2A90 /* printer.h */; }; 27FFF33424329B61003C0B8F /* printer-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8B240D9067001D2A90 /* printer-private.h */; }; 27FFF33524329B61003C0B8F /* printer.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6D240D8896001D2A90 /* printer.c */; }; 27FFF33624329B61003C0B8F /* printer-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377124119E37008AECA4 /* printer-accessors.c */; }; 27FFF33724329B61003C0B8F /* printer-driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 27910A192421626800D01A3F /* printer-driver.c */; }; 27FFF33824329B61003C0B8F /* printer-support.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377424119E3A008AECA4 /* printer-support.c */; }; 27FFF33924329B61003C0B8F /* printer-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 273FA876240FED97007982BE /* printer-webif.c */; }; 27FFF33A24329B61003C0B8F /* resource.c in Sources */ = {isa = PBXBuildFile; fileRef = 273FA875240FED96007982BE /* resource.c */; }; 27FFF33B24329B61003C0B8F /* snmp-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5EF241DB8380082CEA3 /* snmp-private.h */; }; 27FFF33C24329B61003C0B8F /* snmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5F0241DB8390082CEA3 /* snmp.c */; }; 27FFF33D24329B61003C0B8F /* system.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6A240D8896001D2A90 /* system.h */; }; 27FFF33E24329B61003C0B8F /* system-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C89240D9066001D2A90 /* system-private.h */; }; 27FFF33F24329B61003C0B8F /* system.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C67240D8896001D2A90 /* system.c */; }; 27FFF34024329B61003C0B8F /* system-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377324119E39008AECA4 /* system-accessors.c */; }; 27FFF34124329B61003C0B8F /* system-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EE39CF242AE7D900179844 /* system-webif.c */; }; 27FFF34224329B61003C0B8F /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F656E52430DB8D00055A4D /* util.c */; }; 27FFF34324329B82003C0B8F /* base.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C66240D8896001D2A90 /* base.h */; }; 27FFF34424329B82003C0B8F /* base-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27EFC5F3241E72910082CEA3 /* base-private.h */; }; 27FFF34524329B82003C0B8F /* client.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C6E240D8896001D2A90 /* client.h */; }; 27FFF34624329B82003C0B8F /* client-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8D240D9067001D2A90 /* client-private.h */; }; 27FFF34724329B82003C0B8F /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C87240D8E69001D2A90 /* config.h */; }; 27FFF34824329B82003C0B8F /* device.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C65240D8896001D2A90 /* device.h */; }; 27FFF34924329B83003C0B8F /* job.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C70240D8896001D2A90 /* job.h */; }; 27FFF34A24329B83003C0B8F /* job-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8C240D9067001D2A90 /* job-private.h */; }; 27FFF34B24329B83003C0B8F /* log.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8A240D9066001D2A90 /* log.h */; }; 27FFF34C24329B83003C0B8F /* pappl.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C68240D8896001D2A90 /* pappl.h */; }; 27FFF34D24329B83003C0B8F /* pappl-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C69240D8896001D2A90 /* pappl-private.h */; }; 27FFF34E24329B83003C0B8F /* printer.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C63240D8896001D2A90 /* printer.h */; }; 27FFF34F24329B83003C0B8F /* printer-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8B240D9067001D2A90 /* printer-private.h */; }; 27FFF35024329B83003C0B8F /* snmp-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27EFC5EF241DB8380082CEA3 /* snmp-private.h */; }; 27FFF35124329B83003C0B8F /* system.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C6A240D8896001D2A90 /* system.h */; }; 27FFF35224329B83003C0B8F /* system-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C89240D9066001D2A90 /* system-private.h */; }; 27FFF35524329C9E003C0B8F /* base.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C66240D8896001D2A90 /* base.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35624329C9E003C0B8F /* client.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C6E240D8896001D2A90 /* client.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35724329C9E003C0B8F /* device.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C65240D8896001D2A90 /* device.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35824329C9E003C0B8F /* job.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C70240D8896001D2A90 /* job.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35924329C9E003C0B8F /* log.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8A240D9066001D2A90 /* log.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35A24329C9E003C0B8F /* pappl.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C68240D8896001D2A90 /* pappl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35B24329C9E003C0B8F /* printer.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C63240D8896001D2A90 /* printer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35C24329C9E003C0B8F /* system.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C6A240D8896001D2A90 /* system.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FFF35D24329C9E003C0B8F /* base-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27EFC5F3241E72910082CEA3 /* base-private.h */; }; 27FFF35E24329C9E003C0B8F /* client-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8D240D9067001D2A90 /* client-private.h */; }; 27FFF35F24329C9E003C0B8F /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C87240D8E69001D2A90 /* config.h */; }; 27FFF36024329C9E003C0B8F /* job-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8C240D9067001D2A90 /* job-private.h */; }; 27FFF36124329C9E003C0B8F /* pappl-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C69240D8896001D2A90 /* pappl-private.h */; }; 27FFF36224329C9E003C0B8F /* printer-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C8B240D9067001D2A90 /* printer-private.h */; }; 27FFF36324329C9E003C0B8F /* snmp-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27EFC5EF241DB8380082CEA3 /* snmp-private.h */; }; 27FFF36424329C9E003C0B8F /* system-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27905C89240D9066001D2A90 /* system-private.h */; }; 27FFF36624329C9E003C0B8F /* base.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C66240D8896001D2A90 /* base.h */; }; 27FFF36724329C9E003C0B8F /* base-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5F3241E72910082CEA3 /* base-private.h */; }; 27FFF36824329C9E003C0B8F /* client.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6E240D8896001D2A90 /* client.h */; }; 27FFF36924329C9E003C0B8F /* client-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8D240D9067001D2A90 /* client-private.h */; }; 27FFF36A24329C9E003C0B8F /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6C240D8896001D2A90 /* client.c */; }; 27FFF36B24329C9E003C0B8F /* client-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377224119E39008AECA4 /* client-accessors.c */; }; 27FFF36C24329C9E003C0B8F /* client-auth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6F240D8896001D2A90 /* client-auth.c */; }; 27FFF36D24329C9E003C0B8F /* client-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EE39CE242AE7D800179844 /* client-webif.c */; }; 27FFF36E24329C9E003C0B8F /* config.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C87240D8E69001D2A90 /* config.h */; }; 27FFF36F24329C9E003C0B8F /* contact.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F656E72430DBFC00055A4D /* contact.c */; }; 27FFF37024329C9E003C0B8F /* device.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C65240D8896001D2A90 /* device.h */; }; 27FFF37124329C9E003C0B8F /* device.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6B240D8896001D2A90 /* device.c */; }; 27FFF37224329C9E003C0B8F /* dnssd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C73240D8896001D2A90 /* dnssd.c */; }; 27FFF37524329C9E003C0B8F /* job.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C70240D8896001D2A90 /* job.h */; }; 27FFF37624329C9E003C0B8F /* job-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8C240D9067001D2A90 /* job-private.h */; }; 27FFF37724329C9E003C0B8F /* job.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C64240D8896001D2A90 /* job.c */; }; 27FFF37824329C9E003C0B8F /* job-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377524119E3A008AECA4 /* job-accessors.c */; }; 27FFF37924329C9E003C0B8F /* job-process.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C74240D8896001D2A90 /* job-process.c */; }; 27FFF37A24329C9E003C0B8F /* log.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8A240D9066001D2A90 /* log.h */; }; 27FFF37B24329C9E003C0B8F /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C72240D8896001D2A90 /* log.c */; }; 27FFF37C24329C9E003C0B8F /* lookup.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5ED241C85DF0082CEA3 /* lookup.c */; }; 27FFF37D24329C9E003C0B8F /* pappl.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C68240D8896001D2A90 /* pappl.h */; }; 27FFF37E24329C9E003C0B8F /* pappl-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C69240D8896001D2A90 /* pappl-private.h */; }; 27FFF37F24329C9E003C0B8F /* printer.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C63240D8896001D2A90 /* printer.h */; }; 27FFF38024329C9E003C0B8F /* printer-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C8B240D9067001D2A90 /* printer-private.h */; }; 27FFF38124329C9E003C0B8F /* printer.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6D240D8896001D2A90 /* printer.c */; }; 27FFF38224329C9E003C0B8F /* printer-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377124119E37008AECA4 /* printer-accessors.c */; }; 27FFF38324329C9E003C0B8F /* printer-driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 27910A192421626800D01A3F /* printer-driver.c */; }; 27FFF38424329C9E003C0B8F /* printer-support.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377424119E3A008AECA4 /* printer-support.c */; }; 27FFF38524329C9E003C0B8F /* printer-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 273FA876240FED97007982BE /* printer-webif.c */; }; 27FFF38624329C9E003C0B8F /* resource.c in Sources */ = {isa = PBXBuildFile; fileRef = 273FA875240FED96007982BE /* resource.c */; }; 27FFF38724329C9E003C0B8F /* snmp-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5EF241DB8380082CEA3 /* snmp-private.h */; }; 27FFF38824329C9E003C0B8F /* snmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EFC5F0241DB8390082CEA3 /* snmp.c */; }; 27FFF38924329C9E003C0B8F /* system.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C6A240D8896001D2A90 /* system.h */; }; 27FFF38A24329C9E003C0B8F /* system-private.h in Sources */ = {isa = PBXBuildFile; fileRef = 27905C89240D9066001D2A90 /* system-private.h */; }; 27FFF38B24329C9E003C0B8F /* system.c in Sources */ = {isa = PBXBuildFile; fileRef = 27905C67240D8896001D2A90 /* system.c */; }; 27FFF38C24329C9E003C0B8F /* system-accessors.c in Sources */ = {isa = PBXBuildFile; fileRef = 279D377324119E39008AECA4 /* system-accessors.c */; }; 27FFF38D24329C9E003C0B8F /* system-webif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27EE39CF242AE7D900179844 /* system-webif.c */; }; 27FFF38E24329C9E003C0B8F /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 27F656E52430DB8D00055A4D /* util.c */; }; 27FFF39424329D16003C0B8F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */; }; 27FFF39524329D16003C0B8F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E32415EBA80082CEA3 /* IOKit.framework */; }; 27FFF39624329D16003C0B8F /* libcups.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DF2415EB980082CEA3 /* libcups.tbd */; }; 27FFF39724329D16003C0B8F /* libpam.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */; }; 27FFF39824329D16003C0B8F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */; }; 27FFF39924329D16003C0B8F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */; }; 27FFF39A24329D30003C0B8F /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E62415EBD70082CEA3 /* libjpeg.a */; }; 27FFF39B24329D30003C0B8F /* libpng16.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27FFF31824329B4A003C0B8F /* libpng16.a */; }; 27FFF39C24329D30003C0B8F /* libusb-1.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */; }; 27FFF3A124329E59003C0B8F /* libusb-1.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */; }; 27FFF3A224329E6F003C0B8F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 274AD640253F52B10033CAAB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27FFF30724329AAF003C0B8F; remoteInfo = libpappl; }; 274AD664253F52C90033CAAB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 274AD63E253F52B10033CAAB; remoteInfo = testmainloop; }; 27E8655225F176FB00A8F8D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27FFF30724329AAF003C0B8F; remoteInfo = libpappl; }; 27E8658F25F1774C00A8F8D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27E8655025F176FB00A8F8D9; remoteInfo = testhttpmon; }; 27FFF30024328E31003C0B8F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 274A1ECF242E7DEA00DE387E; remoteInfo = testsuite; }; 27FFF30C24329AC7003C0B8F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27FFF30724329AAF003C0B8F; remoteInfo = libpappl; }; 27FFF39D24329D3B003C0B8F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27FFF35324329C9E003C0B8F; remoteInfo = libpappl; }; 27FFF39F24329D3B003C0B8F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273C6EEC240D8729000F85E7 /* Project object */; proxyType = 1; remoteGlobalIDString = 27FFF30724329AAF003C0B8F; remoteInfo = libpappl_static; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 274A1ECE242E7DEA00DE387E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 274AD650253F52B10033CAAB /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 27E8656225F176FB00A8F8D9 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 27134E6B2548D1CD004D9027 /* system-printer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-printer.c"; path = "../pappl/system-printer.c"; sourceTree = ""; }; 2719D1B424732B1700299DA1 /* dnssd-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "dnssd-private.h"; path = "../pappl/dnssd-private.h"; sourceTree = ""; }; 27214FA324ED72B300E36FFC /* device-network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "device-network.c"; path = "../pappl/device-network.c"; sourceTree = ""; }; 27214FA424ED72B400E36FFC /* device-usb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "device-usb.c"; path = "../pappl/device-usb.c"; sourceTree = ""; }; 27214FA924ED72D600E36FFC /* device-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "device-private.h"; path = "../pappl/device-private.h"; sourceTree = ""; }; 27256319243D628F00A38E9F /* system-loadsave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-loadsave.c"; path = "../pappl/system-loadsave.c"; sourceTree = ""; }; 2737B04624B3598400E6F38C /* log-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "log-private.h"; path = "../pappl/log-private.h"; sourceTree = ""; }; 2737B04724B3598400E6F38C /* resource-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "resource-private.h"; path = "../pappl/resource-private.h"; sourceTree = ""; }; 273C6EF9240D8729000F85E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 273FA875240FED96007982BE /* resource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resource.c; path = ../pappl/resource.c; sourceTree = ""; }; 273FA876240FED97007982BE /* printer-webif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-webif.c"; path = "../pappl/printer-webif.c"; sourceTree = ""; }; 274A1ED0242E7DEA00DE387E /* testpappl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testpappl; sourceTree = BUILT_PRODUCTS_DIR; }; 274A1ED7242E7E1300DE387E /* pwg-driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "pwg-driver.c"; path = "../testsuite/pwg-driver.c"; sourceTree = ""; }; 274A1ED8242E7E1300DE387E /* testpappl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testpappl.c; path = ../testsuite/testpappl.c; sourceTree = ""; }; 274A1ED9242E7E1400DE387E /* testpappl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = testpappl.h; path = ../testsuite/testpappl.h; sourceTree = ""; }; 274AD654253F52B10033CAAB /* testmainloop */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testmainloop; sourceTree = BUILT_PRODUCTS_DIR; }; 274AD666253F52E30033CAAB /* testmainloop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testmainloop.c; path = ../testsuite/testmainloop.c; sourceTree = ""; }; 274D76BC27AAD83000FC3529 /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../testsuite/test.h; sourceTree = ""; }; 2763648325223F3200949C0B /* printer-usb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-usb.c"; path = "../pappl/printer-usb.c"; sourceTree = ""; }; 2767F42E2797841E00BE323A /* system-subscription.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-subscription.c"; path = "../pappl/system-subscription.c"; sourceTree = ""; }; 2767F4312797AC3A00BE323A /* subscription.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = subscription.c; path = ../pappl/subscription.c; sourceTree = ""; }; 2767F4342797AD5800BE323A /* subscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = subscription.h; path = ../pappl/subscription.h; sourceTree = ""; }; 2767F4372799F0C200BE323A /* subscription-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "subscription-private.h"; path = "../pappl/subscription-private.h"; sourceTree = ""; }; 276EE2672550620200429BCE /* pappl-client-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-client-body.man"; path = "../man/pappl-client-body.man"; sourceTree = ""; }; 276EE2682550620200429BCE /* pappl-printer-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-printer-body.man"; path = "../man/pappl-printer-body.man"; sourceTree = ""; }; 276EE2692550620200429BCE /* pappl-footer.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-footer.man"; path = "../man/pappl-footer.man"; sourceTree = ""; }; 276EE26A2550620200429BCE /* pappl.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = pappl.1; path = ../man/pappl.1; sourceTree = ""; }; 276EE26B2550620200429BCE /* pappl-resource-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-resource-body.man"; path = "../man/pappl-resource-body.man"; sourceTree = ""; }; 276EE26C2550620200429BCE /* pappl-printer.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-printer.3"; path = "../man/pappl-printer.3"; sourceTree = ""; }; 276EE26D2550620200429BCE /* pappl-mainloop-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-mainloop-body.man"; path = "../man/pappl-mainloop-body.man"; sourceTree = ""; }; 276EE26E2550620200429BCE /* pappl-client.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-client.3"; path = "../man/pappl-client.3"; sourceTree = ""; }; 276EE26F2550620200429BCE /* pappl-log.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-log.3"; path = "../man/pappl-log.3"; sourceTree = ""; }; 276EE2702550620200429BCE /* pappl-job.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-job.3"; path = "../man/pappl-job.3"; sourceTree = ""; }; 276EE2712550620200429BCE /* pappl-device-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-device-body.man"; path = "../man/pappl-device-body.man"; sourceTree = ""; }; 276EE2722550620200429BCE /* pappl-makeresheader.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "pappl-makeresheader.1"; path = "../man/pappl-makeresheader.1"; sourceTree = ""; }; 276EE2732550620200429BCE /* pappl-job-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-job-body.man"; path = "../man/pappl-job-body.man"; sourceTree = ""; }; 276EE2742550620200429BCE /* pappl-system.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-system.3"; path = "../man/pappl-system.3"; sourceTree = ""; }; 276EE2752550620200429BCE /* pappl-system-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-system-body.man"; path = "../man/pappl-system-body.man"; sourceTree = ""; }; 276EE2762550620200429BCE /* pappl-log-body.man */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-log-body.man"; path = "../man/pappl-log-body.man"; sourceTree = ""; }; 276EE2772550620200429BCE /* pappl-device.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-device.3"; path = "../man/pappl-device.3"; sourceTree = ""; }; 276EE2782550620200429BCE /* pappl-mainloop.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-mainloop.3"; path = "../man/pappl-mainloop.3"; sourceTree = ""; }; 276EE2792550620300429BCE /* pappl-resource.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pappl-resource.3"; path = "../man/pappl-resource.3"; sourceTree = ""; }; 276EE27A2550621400429BCE /* pappl-body.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = "pappl-body.md"; path = "../doc/pappl-body.md"; sourceTree = ""; }; 276EE27B2550621400429BCE /* pappl.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = pappl.html; path = ../doc/pappl.html; sourceTree = ""; }; 276EE27C2550621400429BCE /* pappl-512.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "pappl-512.png"; path = "../doc/pappl-512.png"; sourceTree = ""; }; 276EED7D27AC7BE9007F9AC1 /* system-status-gnome.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-status-gnome.c"; path = "../pappl/system-status-gnome.c"; sourceTree = ""; }; 276EED7E27AC7BE9007F9AC1 /* system-status-macos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "system-status-macos.m"; path = "../pappl/system-status-macos.m"; sourceTree = ""; }; 276EED7F27AC7BEA007F9AC1 /* system-status-win32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-status-win32.c"; path = "../pappl/system-status-win32.c"; sourceTree = ""; }; 2774C74D27DBCECE00A7C96D /* system-loc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-loc.c"; path = "../pappl/system-loc.c"; sourceTree = ""; }; 2774C74E27DBCECE00A7C96D /* loc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = loc.c; path = ../pappl/loc.c; sourceTree = ""; }; 2774C74F27DBCECE00A7C96D /* client-loc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "client-loc.c"; path = "../pappl/client-loc.c"; sourceTree = ""; }; 2774C75027DBCECE00A7C96D /* loc-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "loc-private.h"; path = "../pappl/loc-private.h"; sourceTree = ""; }; 2774C75127DBCECE00A7C96D /* loc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = loc.h; path = ../pappl/loc.h; sourceTree = ""; }; 27905C63240D8896001D2A90 /* printer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = printer.h; path = ../pappl/printer.h; sourceTree = ""; }; 27905C64240D8896001D2A90 /* job.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = job.c; path = ../pappl/job.c; sourceTree = ""; }; 27905C65240D8896001D2A90 /* device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = device.h; path = ../pappl/device.h; sourceTree = ""; }; 27905C66240D8896001D2A90 /* base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base.h; path = ../pappl/base.h; sourceTree = ""; }; 27905C67240D8896001D2A90 /* system.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = system.c; path = ../pappl/system.c; sourceTree = ""; }; 27905C68240D8896001D2A90 /* pappl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pappl.h; path = ../pappl/pappl.h; sourceTree = ""; }; 27905C69240D8896001D2A90 /* pappl-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pappl-private.h"; path = "../pappl/pappl-private.h"; sourceTree = ""; }; 27905C6A240D8896001D2A90 /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = system.h; path = ../pappl/system.h; sourceTree = ""; }; 27905C6B240D8896001D2A90 /* device.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = device.c; path = ../pappl/device.c; sourceTree = ""; }; 27905C6C240D8896001D2A90 /* client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = client.c; path = ../pappl/client.c; sourceTree = ""; }; 27905C6D240D8896001D2A90 /* printer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = printer.c; path = ../pappl/printer.c; sourceTree = ""; }; 27905C6E240D8896001D2A90 /* client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = client.h; path = ../pappl/client.h; sourceTree = ""; }; 27905C6F240D8896001D2A90 /* client-auth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "client-auth.c"; path = "../pappl/client-auth.c"; sourceTree = ""; }; 27905C70240D8896001D2A90 /* job.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = job.h; path = ../pappl/job.h; sourceTree = ""; }; 27905C72240D8896001D2A90 /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = log.c; path = ../pappl/log.c; sourceTree = ""; }; 27905C73240D8896001D2A90 /* dnssd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd.c; path = ../pappl/dnssd.c; sourceTree = ""; }; 27905C74240D8896001D2A90 /* job-process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "job-process.c"; path = "../pappl/job-process.c"; sourceTree = ""; }; 27905C87240D8E69001D2A90 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; 27905C89240D9066001D2A90 /* system-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "system-private.h"; path = "../pappl/system-private.h"; sourceTree = ""; }; 27905C8A240D9066001D2A90 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = log.h; path = ../pappl/log.h; sourceTree = ""; }; 27905C8B240D9067001D2A90 /* printer-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "printer-private.h"; path = "../pappl/printer-private.h"; sourceTree = ""; }; 27905C8C240D9067001D2A90 /* job-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "job-private.h"; path = "../pappl/job-private.h"; sourceTree = ""; }; 27905C8D240D9067001D2A90 /* client-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "client-private.h"; path = "../pappl/client-private.h"; sourceTree = ""; }; 27910A192421626800D01A3F /* printer-driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-driver.c"; path = "../pappl/printer-driver.c"; sourceTree = ""; }; 279D377124119E37008AECA4 /* printer-accessors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-accessors.c"; path = "../pappl/printer-accessors.c"; sourceTree = ""; }; 279D377224119E39008AECA4 /* client-accessors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "client-accessors.c"; path = "../pappl/client-accessors.c"; sourceTree = ""; }; 279D377324119E39008AECA4 /* system-accessors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-accessors.c"; path = "../pappl/system-accessors.c"; sourceTree = ""; }; 279D377424119E3A008AECA4 /* printer-support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-support.c"; path = "../pappl/printer-support.c"; sourceTree = ""; }; 279D377524119E3A008AECA4 /* job-accessors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "job-accessors.c"; path = "../pappl/job-accessors.c"; sourceTree = ""; }; 279EC3D027FA4B930079A47D /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = ../../../../../usr/local/lib/libcrypto.a; sourceTree = ""; }; 279EC3D127FA4B930079A47D /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = ../../../../../usr/local/lib/libssl.a; sourceTree = ""; }; 27A56490256769A9009501BD /* printer-ipp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-ipp.c"; path = "../pappl/printer-ipp.c"; sourceTree = ""; }; 27A56491256769A9009501BD /* system-ipp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-ipp.c"; path = "../pappl/system-ipp.c"; sourceTree = ""; }; 27A564A525676AE3009501BD /* client-ipp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "client-ipp.c"; path = "../pappl/client-ipp.c"; sourceTree = ""; }; 27A564B225677057009501BD /* job-ipp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "job-ipp.c"; path = "../pappl/job-ipp.c"; sourceTree = ""; }; 27AB72B324740B3300691FE7 /* link.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = link.c; path = ../pappl/link.c; sourceTree = ""; }; 27BFB1BB240DF06A00CE29F0 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 27BFDDC9279EF534000D073A /* subscription-ipp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "subscription-ipp.c"; path = "../pappl/subscription-ipp.c"; sourceTree = ""; }; 27D6761F2493D73D008F734C /* mainloop-subcommands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mainloop-subcommands.c"; path = "../pappl/mainloop-subcommands.c"; sourceTree = ""; }; 27D676202493D73E008F734C /* mainloop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mainloop.c; path = ../pappl/mainloop.c; sourceTree = ""; }; 27D676212493D73E008F734C /* mainloop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mainloop.h; path = ../pappl/mainloop.h; sourceTree = ""; }; 27D676222493D73E008F734C /* mainloop-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "mainloop-private.h"; path = "../pappl/mainloop-private.h"; sourceTree = ""; }; 27D6762B2493EF95008F734C /* mainloop-support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mainloop-support.c"; path = "../pappl/mainloop-support.c"; sourceTree = ""; }; 27DF62F02450992D00501447 /* job-filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "job-filter.c"; path = "../pappl/job-filter.c"; sourceTree = ""; }; 27E5AEA2246B6A4700FFD958 /* printer-raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "printer-raw.c"; path = "../pappl/printer-raw.c"; sourceTree = ""; }; 27E8654525F176C700A8F8D9 /* httpmon-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "httpmon-private.h"; path = "../pappl/httpmon-private.h"; sourceTree = ""; }; 27E8654625F176C700A8F8D9 /* httpmon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = httpmon.c; path = ../pappl/httpmon.c; sourceTree = ""; }; 27E8656625F176FB00A8F8D9 /* testhttpmon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testhttpmon; sourceTree = BUILT_PRODUCTS_DIR; }; 27E8657325F1771700A8F8D9 /* testhttpmon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testhttpmon.c; path = ../testsuite/testhttpmon.c; sourceTree = ""; }; 27EE39CE242AE7D800179844 /* client-webif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "client-webif.c"; path = "../pappl/client-webif.c"; sourceTree = ""; }; 27EE39CF242AE7D900179844 /* system-webif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "system-webif.c"; path = "../pappl/system-webif.c"; sourceTree = ""; }; 27EFC5D52415EB550082CEA3 /* libcups.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcups.2.tbd; path = usr/lib/libcups.2.tbd; sourceTree = SDKROOT; }; 27EFC5D72415EB610082CEA3 /* libcupsimage.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcupsimage.2.tbd; path = usr/lib/libcupsimage.2.tbd; sourceTree = SDKROOT; }; 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 27EFC5DF2415EB980082CEA3 /* libcups.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcups.tbd; path = usr/lib/libcups.tbd; sourceTree = SDKROOT; }; 27EFC5E02415EB980082CEA3 /* libcupsimage.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcupsimage.tbd; path = usr/lib/libcupsimage.tbd; sourceTree = SDKROOT; }; 27EFC5E32415EBA80082CEA3 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libusb-1.0.a"; path = "../../../../../usr/local/lib/libusb-1.0.a"; sourceTree = ""; }; 27EFC5E62415EBD70082CEA3 /* libjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjpeg.a; path = ../../../../../usr/local/lib/libjpeg.a; sourceTree = ""; }; 27EFC5E72415EBD70082CEA3 /* libpng16.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng16.a; path = ../../../../../usr/local/Cellar/libpng/1.6.34/lib/libpng16.a; sourceTree = ""; }; 27EFC5ED241C85DF0082CEA3 /* lookup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lookup.c; path = ../pappl/lookup.c; sourceTree = ""; }; 27EFC5EF241DB8380082CEA3 /* snmp-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "snmp-private.h"; path = "../pappl/snmp-private.h"; sourceTree = ""; }; 27EFC5F0241DB8390082CEA3 /* snmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snmp.c; path = ../pappl/snmp.c; sourceTree = ""; }; 27EFC5F3241E72910082CEA3 /* base-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "base-private.h"; path = "../pappl/base-private.h"; sourceTree = ""; }; 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libpam.tbd; path = usr/lib/libpam.tbd; sourceTree = SDKROOT; }; 27F4285724F4080600C7ADCE /* device-file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "device-file.c"; path = "../pappl/device-file.c"; sourceTree = ""; }; 27F656E52430DB8D00055A4D /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = util.c; path = ../pappl/util.c; sourceTree = ""; }; 27F656E72430DBFC00055A4D /* contact.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = contact.c; path = ../pappl/contact.c; sourceTree = ""; }; 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; 27FFF30824329AAF003C0B8F /* libpappl_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpappl_static.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27FFF31324329B2D003C0B8F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 27FFF31424329B2D003C0B8F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 27FFF31824329B4A003C0B8F /* libpng16.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng16.a; path = ../../../../../usr/local/lib/libpng16.a; sourceTree = ""; }; 27FFF39324329C9E003C0B8F /* libpappl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpappl.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 274A1ECD242E7DEA00DE387E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 27FF0901282EEA6200DAFC7D /* libresolv.tbd in Frameworks */, 27FF0900282EEA5D00DAFC7D /* libiconv.tbd in Frameworks */, 279EC3D627FA4BCC0079A47D /* libcrypto.a in Frameworks */, 279EC3D727FA4BCC0079A47D /* libssl.a in Frameworks */, 27FFF3A224329E6F003C0B8F /* CoreFoundation.framework in Frameworks */, 27FFF3A124329E59003C0B8F /* libusb-1.0.a in Frameworks */, 27FFF31924329B4A003C0B8F /* libpng16.a in Frameworks */, 27FFF31724329B4A003C0B8F /* libjpeg.a in Frameworks */, 27FFF31524329B2D003C0B8F /* Security.framework in Frameworks */, 27FFF30E24329B2D003C0B8F /* libpappl_static.a in Frameworks */, 27FFF30F24329B2D003C0B8F /* IOKit.framework in Frameworks */, 27FFF31024329B2D003C0B8F /* libpam.tbd in Frameworks */, 27FFF31124329B2D003C0B8F /* libz.tbd in Frameworks */, 27FFF31224329B2D003C0B8F /* SystemConfiguration.framework in Frameworks */, 27FFF3032432901A003C0B8F /* libcups.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 274AD644253F52B10033CAAB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 27FF08FF282EEA5700DAFC7D /* libresolv.tbd in Frameworks */, 27FF08FE282EEA5200DAFC7D /* libiconv.tbd in Frameworks */, 279EC3D427FA4BB90079A47D /* libcrypto.a in Frameworks */, 279EC3D527FA4BB90079A47D /* libssl.a in Frameworks */, 274AD645253F52B10033CAAB /* CoreFoundation.framework in Frameworks */, 274AD646253F52B10033CAAB /* libusb-1.0.a in Frameworks */, 274AD647253F52B10033CAAB /* libpng16.a in Frameworks */, 274AD648253F52B10033CAAB /* libjpeg.a in Frameworks */, 274AD649253F52B10033CAAB /* Security.framework in Frameworks */, 274AD64A253F52B10033CAAB /* libpappl_static.a in Frameworks */, 274AD64B253F52B10033CAAB /* IOKit.framework in Frameworks */, 274AD64C253F52B10033CAAB /* libpam.tbd in Frameworks */, 274AD64D253F52B10033CAAB /* libz.tbd in Frameworks */, 274AD64E253F52B10033CAAB /* SystemConfiguration.framework in Frameworks */, 274AD64F253F52B10033CAAB /* libcups.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 27E8655625F176FB00A8F8D9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 27FF08FD282EEA4900DAFC7D /* libresolv.tbd in Frameworks */, 27FF08FC282EEA4200DAFC7D /* libiconv.tbd in Frameworks */, 27E8655725F176FB00A8F8D9 /* CoreFoundation.framework in Frameworks */, 27E8655825F176FB00A8F8D9 /* libusb-1.0.a in Frameworks */, 27E8655925F176FB00A8F8D9 /* libpng16.a in Frameworks */, 27E8655A25F176FB00A8F8D9 /* libjpeg.a in Frameworks */, 27E8655B25F176FB00A8F8D9 /* Security.framework in Frameworks */, 27E8655C25F176FB00A8F8D9 /* libpappl_static.a in Frameworks */, 27E8655D25F176FB00A8F8D9 /* IOKit.framework in Frameworks */, 27E8655E25F176FB00A8F8D9 /* libpam.tbd in Frameworks */, 27E8655F25F176FB00A8F8D9 /* libz.tbd in Frameworks */, 27E8656025F176FB00A8F8D9 /* SystemConfiguration.framework in Frameworks */, 27E8656125F176FB00A8F8D9 /* libcups.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 27FFF30624329AAF003C0B8F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 27FFF38F24329C9E003C0B8F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 27FF08FB282EE89A00DAFC7D /* libresolv.tbd in Frameworks */, 27FF08F9282EE88A00DAFC7D /* libiconv.tbd in Frameworks */, 279EC3D227FA4B930079A47D /* libcrypto.a in Frameworks */, 279EC3D327FA4B930079A47D /* libssl.a in Frameworks */, 27FFF39A24329D30003C0B8F /* libjpeg.a in Frameworks */, 27FFF39B24329D30003C0B8F /* libpng16.a in Frameworks */, 27FFF39C24329D30003C0B8F /* libusb-1.0.a in Frameworks */, 27FFF39424329D16003C0B8F /* CoreFoundation.framework in Frameworks */, 27FFF39524329D16003C0B8F /* IOKit.framework in Frameworks */, 27FFF39624329D16003C0B8F /* libcups.tbd in Frameworks */, 27FFF39724329D16003C0B8F /* libpam.tbd in Frameworks */, 27FFF39824329D16003C0B8F /* libz.tbd in Frameworks */, 27FFF39924329D16003C0B8F /* SystemConfiguration.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 273C6EEB240D8729000F85E7 = { isa = PBXGroup; children = ( 27BFB1BB240DF06A00CE29F0 /* README.md */, 276EE266255061D300429BCE /* Documentation */, 27905C62240D8861001D2A90 /* pappl */, 274A1ECB242E7DAD00DE387E /* testsuite */, 273C6EF6240D8729000F85E7 /* Products */, 27EFC5D42415EB550082CEA3 /* Frameworks */, ); sourceTree = ""; }; 273C6EF6240D8729000F85E7 /* Products */ = { isa = PBXGroup; children = ( 274A1ED0242E7DEA00DE387E /* testpappl */, 27FFF30824329AAF003C0B8F /* libpappl_static.a */, 27FFF39324329C9E003C0B8F /* libpappl.a */, 274AD654253F52B10033CAAB /* testmainloop */, 27E8656625F176FB00A8F8D9 /* testhttpmon */, ); name = Products; sourceTree = ""; }; 274A1ECB242E7DAD00DE387E /* testsuite */ = { isa = PBXGroup; children = ( 274A1ED7242E7E1300DE387E /* pwg-driver.c */, 274D76BC27AAD83000FC3529 /* test.h */, 27E8657325F1771700A8F8D9 /* testhttpmon.c */, 274AD666253F52E30033CAAB /* testmainloop.c */, 274A1ED8242E7E1300DE387E /* testpappl.c */, 274A1ED9242E7E1400DE387E /* testpappl.h */, ); name = testsuite; sourceTree = ""; }; 276EE266255061D300429BCE /* Documentation */ = { isa = PBXGroup; children = ( 276EE27C2550621400429BCE /* pappl-512.png */, 276EE27A2550621400429BCE /* pappl-body.md */, 276EE2672550620200429BCE /* pappl-client-body.man */, 276EE26E2550620200429BCE /* pappl-client.3 */, 276EE2712550620200429BCE /* pappl-device-body.man */, 276EE2772550620200429BCE /* pappl-device.3 */, 276EE2692550620200429BCE /* pappl-footer.man */, 276EE2732550620200429BCE /* pappl-job-body.man */, 276EE2702550620200429BCE /* pappl-job.3 */, 276EE2762550620200429BCE /* pappl-log-body.man */, 276EE26F2550620200429BCE /* pappl-log.3 */, 276EE26D2550620200429BCE /* pappl-mainloop-body.man */, 276EE2782550620200429BCE /* pappl-mainloop.3 */, 276EE2722550620200429BCE /* pappl-makeresheader.1 */, 276EE2682550620200429BCE /* pappl-printer-body.man */, 276EE26C2550620200429BCE /* pappl-printer.3 */, 276EE26B2550620200429BCE /* pappl-resource-body.man */, 276EE2792550620300429BCE /* pappl-resource.3 */, 276EE2752550620200429BCE /* pappl-system-body.man */, 276EE2742550620200429BCE /* pappl-system.3 */, 276EE26A2550620200429BCE /* pappl.1 */, 276EE27B2550621400429BCE /* pappl.html */, ); name = Documentation; sourceTree = ""; }; 27905C62240D8861001D2A90 /* pappl */ = { isa = PBXGroup; children = ( 273C6EF9240D8729000F85E7 /* Info.plist */, 27905C66240D8896001D2A90 /* base.h */, 27EFC5F3241E72910082CEA3 /* base-private.h */, 27905C6E240D8896001D2A90 /* client.h */, 27905C8D240D9067001D2A90 /* client-private.h */, 27905C6C240D8896001D2A90 /* client.c */, 279D377224119E39008AECA4 /* client-accessors.c */, 27905C6F240D8896001D2A90 /* client-auth.c */, 27A564A525676AE3009501BD /* client-ipp.c */, 2774C74F27DBCECE00A7C96D /* client-loc.c */, 27EE39CE242AE7D800179844 /* client-webif.c */, 27905C87240D8E69001D2A90 /* config.h */, 27F656E72430DBFC00055A4D /* contact.c */, 27905C65240D8896001D2A90 /* device.h */, 27214FA924ED72D600E36FFC /* device-private.h */, 27905C6B240D8896001D2A90 /* device.c */, 27F4285724F4080600C7ADCE /* device-file.c */, 27214FA324ED72B300E36FFC /* device-network.c */, 27214FA424ED72B400E36FFC /* device-usb.c */, 2719D1B424732B1700299DA1 /* dnssd-private.h */, 27905C73240D8896001D2A90 /* dnssd.c */, 27E8654525F176C700A8F8D9 /* httpmon-private.h */, 27E8654625F176C700A8F8D9 /* httpmon.c */, 27905C70240D8896001D2A90 /* job.h */, 27905C8C240D9067001D2A90 /* job-private.h */, 27905C64240D8896001D2A90 /* job.c */, 279D377524119E3A008AECA4 /* job-accessors.c */, 27DF62F02450992D00501447 /* job-filter.c */, 27A564B225677057009501BD /* job-ipp.c */, 27905C74240D8896001D2A90 /* job-process.c */, 27AB72B324740B3300691FE7 /* link.c */, 2774C75127DBCECE00A7C96D /* loc.h */, 2774C75027DBCECE00A7C96D /* loc-private.h */, 2774C74E27DBCECE00A7C96D /* loc.c */, 27905C8A240D9066001D2A90 /* log.h */, 2737B04624B3598400E6F38C /* log-private.h */, 27905C72240D8896001D2A90 /* log.c */, 27EFC5ED241C85DF0082CEA3 /* lookup.c */, 27D676212493D73E008F734C /* mainloop.h */, 27D676222493D73E008F734C /* mainloop-private.h */, 27D676202493D73E008F734C /* mainloop.c */, 27D6761F2493D73D008F734C /* mainloop-subcommands.c */, 27D6762B2493EF95008F734C /* mainloop-support.c */, 27905C68240D8896001D2A90 /* pappl.h */, 27905C69240D8896001D2A90 /* pappl-private.h */, 27905C63240D8896001D2A90 /* printer.h */, 27905C8B240D9067001D2A90 /* printer-private.h */, 27905C6D240D8896001D2A90 /* printer.c */, 279D377124119E37008AECA4 /* printer-accessors.c */, 27910A192421626800D01A3F /* printer-driver.c */, 27A56490256769A9009501BD /* printer-ipp.c */, 27E5AEA2246B6A4700FFD958 /* printer-raw.c */, 279D377424119E3A008AECA4 /* printer-support.c */, 2763648325223F3200949C0B /* printer-usb.c */, 273FA876240FED97007982BE /* printer-webif.c */, 2737B04724B3598400E6F38C /* resource-private.h */, 273FA875240FED96007982BE /* resource.c */, 27EFC5EF241DB8380082CEA3 /* snmp-private.h */, 27EFC5F0241DB8390082CEA3 /* snmp.c */, 2767F4342797AD5800BE323A /* subscription.h */, 2767F4372799F0C200BE323A /* subscription-private.h */, 2767F4312797AC3A00BE323A /* subscription.c */, 27BFDDC9279EF534000D073A /* subscription-ipp.c */, 27905C6A240D8896001D2A90 /* system.h */, 27905C89240D9066001D2A90 /* system-private.h */, 27905C67240D8896001D2A90 /* system.c */, 279D377324119E39008AECA4 /* system-accessors.c */, 27A56491256769A9009501BD /* system-ipp.c */, 27256319243D628F00A38E9F /* system-loadsave.c */, 2774C74D27DBCECE00A7C96D /* system-loc.c */, 27134E6B2548D1CD004D9027 /* system-printer.c */, 276EED7D27AC7BE9007F9AC1 /* system-status-gnome.c */, 276EED7E27AC7BE9007F9AC1 /* system-status-macos.m */, 276EED7F27AC7BEA007F9AC1 /* system-status-win32.c */, 2767F42E2797841E00BE323A /* system-subscription.c */, 27EE39CF242AE7D900179844 /* system-webif.c */, 27F656E52430DB8D00055A4D /* util.c */, ); name = pappl; sourceTree = ""; }; 27EFC5D42415EB550082CEA3 /* Frameworks */ = { isa = PBXGroup; children = ( 27FF08FA282EE89A00DAFC7D /* libresolv.tbd */, 27FF08F8282EE88A00DAFC7D /* libiconv.tbd */, 279EC3D027FA4B930079A47D /* libcrypto.a */, 279EC3D127FA4B930079A47D /* libssl.a */, 27FFF31824329B4A003C0B8F /* libpng16.a */, 27FFF31424329B2D003C0B8F /* CoreGraphics.framework */, 27FFF31324329B2D003C0B8F /* Security.framework */, 27EFC5F5241E72AE0082CEA3 /* libpam.tbd */, 27EFC5E62415EBD70082CEA3 /* libjpeg.a */, 27EFC5E72415EBD70082CEA3 /* libpng16.a */, 27EFC5E52415EBD70082CEA3 /* libusb-1.0.a */, 27EFC5E32415EBA80082CEA3 /* IOKit.framework */, 27EFC5DF2415EB980082CEA3 /* libcups.tbd */, 27EFC5E02415EB980082CEA3 /* libcupsimage.tbd */, 27EFC5DD2415EB8A0082CEA3 /* libz.tbd */, 27EFC5DB2415EB740082CEA3 /* CoreFoundation.framework */, 27EFC5D92415EB6C0082CEA3 /* SystemConfiguration.framework */, 27EFC5D72415EB610082CEA3 /* libcupsimage.2.tbd */, 27EFC5D52415EB550082CEA3 /* libcups.2.tbd */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 27FFF30424329AAF003C0B8F /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 27FFF34324329B82003C0B8F /* base.h in Headers */, 2737B04924B3598400E6F38C /* log-private.h in Headers */, 27214FAB24ED72D600E36FFC /* device-private.h in Headers */, 27FFF34524329B82003C0B8F /* client.h in Headers */, 27FFF34824329B82003C0B8F /* device.h in Headers */, 27FFF34924329B83003C0B8F /* job.h in Headers */, 27FFF34B24329B83003C0B8F /* log.h in Headers */, 27FFF34C24329B83003C0B8F /* pappl.h in Headers */, 27FFF34E24329B83003C0B8F /* printer.h in Headers */, 2719D1B624732B1800299DA1 /* dnssd-private.h in Headers */, 27FFF35124329B83003C0B8F /* system.h in Headers */, 27FFF34424329B82003C0B8F /* base-private.h in Headers */, 27FFF34624329B82003C0B8F /* client-private.h in Headers */, 27E8654825F176C700A8F8D9 /* httpmon-private.h in Headers */, 27D6762A2493D73E008F734C /* mainloop-private.h in Headers */, 2774C75B27DBCECE00A7C96D /* loc.h in Headers */, 27FFF34724329B82003C0B8F /* config.h in Headers */, 27FFF34A24329B83003C0B8F /* job-private.h in Headers */, 2767F4362797AD5800BE323A /* subscription.h in Headers */, 27FFF34D24329B83003C0B8F /* pappl-private.h in Headers */, 27FFF34F24329B83003C0B8F /* printer-private.h in Headers */, 2767F4392799F0C200BE323A /* subscription-private.h in Headers */, 2737B04B24B3598400E6F38C /* resource-private.h in Headers */, 27D676282493D73E008F734C /* mainloop.h in Headers */, 27FFF35024329B83003C0B8F /* snmp-private.h in Headers */, 27FFF35224329B83003C0B8F /* system-private.h in Headers */, 2774C75927DBCECE00A7C96D /* loc-private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 27FFF35424329C9E003C0B8F /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 27FFF35524329C9E003C0B8F /* base.h in Headers */, 2737B04824B3598400E6F38C /* log-private.h in Headers */, 27214FAA24ED72D600E36FFC /* device-private.h in Headers */, 27FFF35624329C9E003C0B8F /* client.h in Headers */, 27FFF35724329C9E003C0B8F /* device.h in Headers */, 27FFF35824329C9E003C0B8F /* job.h in Headers */, 27FFF35924329C9E003C0B8F /* log.h in Headers */, 27FFF35A24329C9E003C0B8F /* pappl.h in Headers */, 27FFF35B24329C9E003C0B8F /* printer.h in Headers */, 2719D1B524732B1800299DA1 /* dnssd-private.h in Headers */, 27FFF35C24329C9E003C0B8F /* system.h in Headers */, 27FFF35D24329C9E003C0B8F /* base-private.h in Headers */, 27FFF35E24329C9E003C0B8F /* client-private.h in Headers */, 27E8654725F176C700A8F8D9 /* httpmon-private.h in Headers */, 27D676292493D73E008F734C /* mainloop-private.h in Headers */, 2774C75A27DBCECE00A7C96D /* loc.h in Headers */, 27FFF35F24329C9E003C0B8F /* config.h in Headers */, 27FFF36024329C9E003C0B8F /* job-private.h in Headers */, 2767F4352797AD5800BE323A /* subscription.h in Headers */, 27FFF36124329C9E003C0B8F /* pappl-private.h in Headers */, 27FFF36224329C9E003C0B8F /* printer-private.h in Headers */, 2767F4382799F0C200BE323A /* subscription-private.h in Headers */, 2737B04A24B3598400E6F38C /* resource-private.h in Headers */, 27D676272493D73E008F734C /* mainloop.h in Headers */, 27FFF36324329C9E003C0B8F /* snmp-private.h in Headers */, 27FFF36424329C9E003C0B8F /* system-private.h in Headers */, 2774C75827DBCECE00A7C96D /* loc-private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 274A1ECF242E7DEA00DE387E /* testpappl */ = { isa = PBXNativeTarget; buildConfigurationList = 274A1ED4242E7DEA00DE387E /* Build configuration list for PBXNativeTarget "testpappl" */; buildPhases = ( 274A1ECC242E7DEA00DE387E /* Sources */, 274A1ECD242E7DEA00DE387E /* Frameworks */, 274A1ECE242E7DEA00DE387E /* CopyFiles */, ); buildRules = ( ); dependencies = ( 27FFF30D24329AC7003C0B8F /* PBXTargetDependency */, ); name = testpappl; productName = testsuite; productReference = 274A1ED0242E7DEA00DE387E /* testpappl */; productType = "com.apple.product-type.tool"; }; 274AD63E253F52B10033CAAB /* testmainloop */ = { isa = PBXNativeTarget; buildConfigurationList = 274AD651253F52B10033CAAB /* Build configuration list for PBXNativeTarget "testmainloop" */; buildPhases = ( 274AD641253F52B10033CAAB /* Sources */, 274AD644253F52B10033CAAB /* Frameworks */, 274AD650253F52B10033CAAB /* CopyFiles */, ); buildRules = ( ); dependencies = ( 274AD63F253F52B10033CAAB /* PBXTargetDependency */, ); name = testmainloop; productName = testsuite; productReference = 274AD654253F52B10033CAAB /* testmainloop */; productType = "com.apple.product-type.tool"; }; 27E8655025F176FB00A8F8D9 /* testhttpmon */ = { isa = PBXNativeTarget; buildConfigurationList = 27E8656325F176FB00A8F8D9 /* Build configuration list for PBXNativeTarget "testhttpmon" */; buildPhases = ( 27E8655325F176FB00A8F8D9 /* Sources */, 27E8655625F176FB00A8F8D9 /* Frameworks */, 27E8656225F176FB00A8F8D9 /* CopyFiles */, ); buildRules = ( ); dependencies = ( 27E8655125F176FB00A8F8D9 /* PBXTargetDependency */, ); name = testhttpmon; productName = testsuite; productReference = 27E8656625F176FB00A8F8D9 /* testhttpmon */; productType = "com.apple.product-type.tool"; }; 27FFF30724329AAF003C0B8F /* libpappl_static */ = { isa = PBXNativeTarget; buildConfigurationList = 27FFF30B24329AAF003C0B8F /* Build configuration list for PBXNativeTarget "libpappl_static" */; buildPhases = ( 27FFF30424329AAF003C0B8F /* Headers */, 27FFF30524329AAF003C0B8F /* Sources */, 27FFF30624329AAF003C0B8F /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = libpappl_static; productName = libpappl; productReference = 27FFF30824329AAF003C0B8F /* libpappl_static.a */; productType = "com.apple.product-type.library.static"; }; 27FFF35324329C9E003C0B8F /* libpappl */ = { isa = PBXNativeTarget; buildConfigurationList = 27FFF39024329C9E003C0B8F /* Build configuration list for PBXNativeTarget "libpappl" */; buildPhases = ( 27FFF35424329C9E003C0B8F /* Headers */, 27FFF36524329C9E003C0B8F /* Sources */, 27FFF38F24329C9E003C0B8F /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = libpappl; productName = libpappl; productReference = 27FFF39324329C9E003C0B8F /* libpappl.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 273C6EEC240D8729000F85E7 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1520; ORGANIZATIONNAME = "Michael Sweet"; TargetAttributes = { 274A1ECF242E7DEA00DE387E = { CreatedOnToolsVersion = 11.4; }; 27FFF2FA24328E24003C0B8F = { CreatedOnToolsVersion = 11.4; }; 27FFF30724329AAF003C0B8F = { CreatedOnToolsVersion = 11.4; }; }; }; buildConfigurationList = 273C6EEF240D8729000F85E7 /* Build configuration list for PBXProject "pappl" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 273C6EEB240D8729000F85E7; productRefGroup = 273C6EF6240D8729000F85E7 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 27FFF2FA24328E24003C0B8F /* All */, 27FFF35324329C9E003C0B8F /* libpappl */, 27FFF30724329AAF003C0B8F /* libpappl_static */, 27E8655025F176FB00A8F8D9 /* testhttpmon */, 274AD63E253F52B10033CAAB /* testmainloop */, 274A1ECF242E7DEA00DE387E /* testpappl */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 274A1ECC242E7DEA00DE387E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 27E8658125F1773E00A8F8D9 /* pwg-driver.c in Sources */, 27E8658225F1773E00A8F8D9 /* testpappl.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 274AD641253F52B10033CAAB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 274AD642253F52B10033CAAB /* pwg-driver.c in Sources */, 274AD667253F52E30033CAAB /* testmainloop.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 27E8655325F176FB00A8F8D9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 27E8657425F1771700A8F8D9 /* testhttpmon.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 27FFF30524329AAF003C0B8F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 27FFF31A24329B61003C0B8F /* base.h in Sources */, 27FFF31B24329B61003C0B8F /* base-private.h in Sources */, 27D6762D2493EF96008F734C /* mainloop-support.c in Sources */, 27FFF31C24329B61003C0B8F /* client.h in Sources */, 27D676242493D73E008F734C /* mainloop-subcommands.c in Sources */, 27D676262493D73E008F734C /* mainloop.c in Sources */, 27A56495256769A9009501BD /* system-ipp.c in Sources */, 27FFF31D24329B61003C0B8F /* client-private.h in Sources */, 27FFF31E24329B61003C0B8F /* client.c in Sources */, 27FFF31F24329B61003C0B8F /* client-accessors.c in Sources */, 27FFF32024329B61003C0B8F /* client-auth.c in Sources */, 27FFF32124329B61003C0B8F /* client-webif.c in Sources */, 27FFF32224329B61003C0B8F /* config.h in Sources */, 27FFF32324329B61003C0B8F /* contact.c in Sources */, 27FFF32424329B61003C0B8F /* device.h in Sources */, 27FFF32524329B61003C0B8F /* device.c in Sources */, 27FFF32624329B61003C0B8F /* dnssd.c in Sources */, 27DF62F22450992D00501447 /* job-filter.c in Sources */, 27BFDDCB279EF534000D073A /* subscription-ipp.c in Sources */, 27FFF32924329B61003C0B8F /* job.h in Sources */, 276EED8327AC7BEA007F9AC1 /* system-status-macos.m in Sources */, 27FFF32A24329B61003C0B8F /* job-private.h in Sources */, 27FFF32B24329B61003C0B8F /* job.c in Sources */, 27FFF32C24329B61003C0B8F /* job-accessors.c in Sources */, 27FFF32D24329B61003C0B8F /* job-process.c in Sources */, 27FFF32E24329B61003C0B8F /* log.h in Sources */, 2774C75527DBCECE00A7C96D /* loc.c in Sources */, 27214FA624ED72B400E36FFC /* device-network.c in Sources */, 27AB72B524740B3400691FE7 /* link.c in Sources */, 27FFF32F24329B61003C0B8F /* log.c in Sources */, 27FFF33024329B61003C0B8F /* lookup.c in Sources */, 27E8654A25F176C700A8F8D9 /* httpmon.c in Sources */, 2767F4302797841E00BE323A /* system-subscription.c in Sources */, 27FFF33124329B61003C0B8F /* pappl.h in Sources */, 27FFF33224329B61003C0B8F /* pappl-private.h in Sources */, 27FFF33324329B61003C0B8F /* printer.h in Sources */, 27FFF33424329B61003C0B8F /* printer-private.h in Sources */, 27FFF33524329B61003C0B8F /* printer.c in Sources */, 2774C75327DBCECE00A7C96D /* system-loc.c in Sources */, 27FFF33624329B61003C0B8F /* printer-accessors.c in Sources */, 27214FA824ED72B400E36FFC /* device-usb.c in Sources */, 27E5AEA4246B6A4800FFD958 /* printer-raw.c in Sources */, 27FFF33724329B61003C0B8F /* printer-driver.c in Sources */, 27FFF33824329B61003C0B8F /* printer-support.c in Sources */, 27FFF33924329B61003C0B8F /* printer-webif.c in Sources */, 27FFF33A24329B61003C0B8F /* resource.c in Sources */, 27FFF33B24329B61003C0B8F /* snmp-private.h in Sources */, 27A564B425677057009501BD /* job-ipp.c in Sources */, 27FFF33C24329B61003C0B8F /* snmp.c in Sources */, 27FFF33D24329B61003C0B8F /* system.h in Sources */, 2763648525223F3200949C0B /* printer-usb.c in Sources */, 27FFF33E24329B61003C0B8F /* system-private.h in Sources */, 27FFF33F24329B61003C0B8F /* system.c in Sources */, 27FFF34024329B61003C0B8F /* system-accessors.c in Sources */, 27134E6D2548D1CD004D9027 /* system-printer.c in Sources */, 27FFF34124329B61003C0B8F /* system-webif.c in Sources */, 2725631B243D629000A38E9F /* system-loadsave.c in Sources */, 27FFF34224329B61003C0B8F /* util.c in Sources */, 27F4285924F4080600C7ADCE /* device-file.c in Sources */, 27A564A725676AE3009501BD /* client-ipp.c in Sources */, 2767F4332797AC3A00BE323A /* subscription.c in Sources */, 2774C75727DBCECE00A7C96D /* client-loc.c in Sources */, 27A56493256769A9009501BD /* printer-ipp.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 27FFF36524329C9E003C0B8F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 27FFF36624329C9E003C0B8F /* base.h in Sources */, 27FFF36724329C9E003C0B8F /* base-private.h in Sources */, 27D6762C2493EF96008F734C /* mainloop-support.c in Sources */, 27FFF36824329C9E003C0B8F /* client.h in Sources */, 27D676232493D73E008F734C /* mainloop-subcommands.c in Sources */, 27D676252493D73E008F734C /* mainloop.c in Sources */, 27A56494256769A9009501BD /* system-ipp.c in Sources */, 27FFF36924329C9E003C0B8F /* client-private.h in Sources */, 27FFF36A24329C9E003C0B8F /* client.c in Sources */, 27FFF36B24329C9E003C0B8F /* client-accessors.c in Sources */, 27FFF36C24329C9E003C0B8F /* client-auth.c in Sources */, 27FFF36D24329C9E003C0B8F /* client-webif.c in Sources */, 27FFF36E24329C9E003C0B8F /* config.h in Sources */, 27FFF36F24329C9E003C0B8F /* contact.c in Sources */, 27FFF37024329C9E003C0B8F /* device.h in Sources */, 27FFF37124329C9E003C0B8F /* device.c in Sources */, 27FFF37224329C9E003C0B8F /* dnssd.c in Sources */, 27DF62F12450992D00501447 /* job-filter.c in Sources */, 27BFDDCA279EF534000D073A /* subscription-ipp.c in Sources */, 27FFF37524329C9E003C0B8F /* job.h in Sources */, 276EED8227AC7BEA007F9AC1 /* system-status-macos.m in Sources */, 27FFF37624329C9E003C0B8F /* job-private.h in Sources */, 27FFF37724329C9E003C0B8F /* job.c in Sources */, 27FFF37824329C9E003C0B8F /* job-accessors.c in Sources */, 27FFF37924329C9E003C0B8F /* job-process.c in Sources */, 27FFF37A24329C9E003C0B8F /* log.h in Sources */, 2774C75427DBCECE00A7C96D /* loc.c in Sources */, 27214FA524ED72B400E36FFC /* device-network.c in Sources */, 27AB72B424740B3400691FE7 /* link.c in Sources */, 27FFF37B24329C9E003C0B8F /* log.c in Sources */, 27FFF37C24329C9E003C0B8F /* lookup.c in Sources */, 27E8654925F176C700A8F8D9 /* httpmon.c in Sources */, 2767F42F2797841E00BE323A /* system-subscription.c in Sources */, 27FFF37D24329C9E003C0B8F /* pappl.h in Sources */, 27FFF37E24329C9E003C0B8F /* pappl-private.h in Sources */, 27FFF37F24329C9E003C0B8F /* printer.h in Sources */, 27FFF38024329C9E003C0B8F /* printer-private.h in Sources */, 27FFF38124329C9E003C0B8F /* printer.c in Sources */, 2774C75227DBCECE00A7C96D /* system-loc.c in Sources */, 27FFF38224329C9E003C0B8F /* printer-accessors.c in Sources */, 27214FA724ED72B400E36FFC /* device-usb.c in Sources */, 27E5AEA3246B6A4800FFD958 /* printer-raw.c in Sources */, 27FFF38324329C9E003C0B8F /* printer-driver.c in Sources */, 27FFF38424329C9E003C0B8F /* printer-support.c in Sources */, 27FFF38524329C9E003C0B8F /* printer-webif.c in Sources */, 27FFF38624329C9E003C0B8F /* resource.c in Sources */, 27FFF38724329C9E003C0B8F /* snmp-private.h in Sources */, 27A564B325677057009501BD /* job-ipp.c in Sources */, 27FFF38824329C9E003C0B8F /* snmp.c in Sources */, 27FFF38924329C9E003C0B8F /* system.h in Sources */, 2763648425223F3200949C0B /* printer-usb.c in Sources */, 27FFF38A24329C9E003C0B8F /* system-private.h in Sources */, 27FFF38B24329C9E003C0B8F /* system.c in Sources */, 27FFF38C24329C9E003C0B8F /* system-accessors.c in Sources */, 27134E6C2548D1CD004D9027 /* system-printer.c in Sources */, 27FFF38D24329C9E003C0B8F /* system-webif.c in Sources */, 2725631A243D629000A38E9F /* system-loadsave.c in Sources */, 27FFF38E24329C9E003C0B8F /* util.c in Sources */, 27F4285824F4080600C7ADCE /* device-file.c in Sources */, 27A564A625676AE3009501BD /* client-ipp.c in Sources */, 2767F4322797AC3A00BE323A /* subscription.c in Sources */, 2774C75627DBCECE00A7C96D /* client-loc.c in Sources */, 27A56492256769A9009501BD /* printer-ipp.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 274AD63F253F52B10033CAAB /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27FFF30724329AAF003C0B8F /* libpappl_static */; targetProxy = 274AD640253F52B10033CAAB /* PBXContainerItemProxy */; }; 274AD665253F52C90033CAAB /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 274AD63E253F52B10033CAAB /* testmainloop */; targetProxy = 274AD664253F52C90033CAAB /* PBXContainerItemProxy */; }; 27E8655125F176FB00A8F8D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27FFF30724329AAF003C0B8F /* libpappl_static */; targetProxy = 27E8655225F176FB00A8F8D9 /* PBXContainerItemProxy */; }; 27E8659025F1774C00A8F8D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27E8655025F176FB00A8F8D9 /* testhttpmon */; targetProxy = 27E8658F25F1774C00A8F8D9 /* PBXContainerItemProxy */; }; 27FFF30124328E31003C0B8F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 274A1ECF242E7DEA00DE387E /* testpappl */; targetProxy = 27FFF30024328E31003C0B8F /* PBXContainerItemProxy */; }; 27FFF30D24329AC7003C0B8F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27FFF30724329AAF003C0B8F /* libpappl_static */; targetProxy = 27FFF30C24329AC7003C0B8F /* PBXContainerItemProxy */; }; 27FFF39E24329D3B003C0B8F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27FFF35324329C9E003C0B8F /* libpappl */; targetProxy = 27FFF39D24329D3B003C0B8F /* PBXContainerItemProxy */; }; 27FFF3A024329D3B003C0B8F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 27FFF30724329AAF003C0B8F /* libpappl_static */; targetProxy = 27FFF39F24329D3B003C0B8F /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 273C6EFB240D8729000F85E7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_GCD_PERFORMANCE = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES; CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_FLOAT_CONVERSION = YES; CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1.4.1; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_PEDANTIC = YES; GCC_WARN_SHADOW = YES; GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( ., .., "/usr/local/include/libusb-1.0", /usr/local/include, ); LIBRARY_SEARCH_PATHS = /usr/local/lib; MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; WARNING_CFLAGS = ( "-Wno-format-pedantic", "-Wno-overlength-strings", ); }; name = Debug; }; 273C6EFC240D8729000F85E7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_GCD_PERFORMANCE = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES; CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_FLOAT_CONVERSION = YES; CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "Apple Development"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1.4.1; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_HARDENED_RUNTIME = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_PEDANTIC = YES; GCC_WARN_SHADOW = YES; GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( ., .., "/usr/local/include/libusb-1.0", /usr/local/include, ); LIBRARY_SEARCH_PATHS = /usr/local/lib; MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; WARNING_CFLAGS = ( "-Wno-format-pedantic", "-Wno-overlength-strings", ); }; name = Release; }; 274A1ED5242E7DEA00DE387E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_BUNDLE_IDENTIFIER = org.msweet.testpappl; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 274A1ED6242E7DEA00DE387E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_BUNDLE_IDENTIFIER = org.msweet.testpappl; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; 274AD652253F52B10033CAAB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 274AD653253F52B10033CAAB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; 27E8656425F176FB00A8F8D9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_BUNDLE_IDENTIFIER = org.msweet.testpappl; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 27E8656525F176FB00A8F8D9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_BUNDLE_IDENTIFIER = org.msweet.testpappl; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; 27FFF2FC24328E24003C0B8F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 27FFF2FD24328E24003C0B8F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 27FFF30924329AAF003C0B8F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; EXECUTABLE_PREFIX = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 27FFF30A24329AAF003C0B8F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; EXECUTABLE_PREFIX = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 27FFF39124329C9E003C0B8F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; EXECUTABLE_PREFIX = ""; MACH_O_TYPE = mh_dylib; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 27FFF39224329C9E003C0B8F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = RU58A2256H; EXECUTABLE_PREFIX = ""; MACH_O_TYPE = mh_dylib; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 273C6EEF240D8729000F85E7 /* Build configuration list for PBXProject "pappl" */ = { isa = XCConfigurationList; buildConfigurations = ( 273C6EFB240D8729000F85E7 /* Debug */, 273C6EFC240D8729000F85E7 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 274A1ED4242E7DEA00DE387E /* Build configuration list for PBXNativeTarget "testpappl" */ = { isa = XCConfigurationList; buildConfigurations = ( 274A1ED5242E7DEA00DE387E /* Debug */, 274A1ED6242E7DEA00DE387E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 274AD651253F52B10033CAAB /* Build configuration list for PBXNativeTarget "testmainloop" */ = { isa = XCConfigurationList; buildConfigurations = ( 274AD652253F52B10033CAAB /* Debug */, 274AD653253F52B10033CAAB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 27E8656325F176FB00A8F8D9 /* Build configuration list for PBXNativeTarget "testhttpmon" */ = { isa = XCConfigurationList; buildConfigurations = ( 27E8656425F176FB00A8F8D9 /* Debug */, 27E8656525F176FB00A8F8D9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 27FFF2FB24328E24003C0B8F /* Build configuration list for PBXAggregateTarget "All" */ = { isa = XCConfigurationList; buildConfigurations = ( 27FFF2FC24328E24003C0B8F /* Debug */, 27FFF2FD24328E24003C0B8F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 27FFF30B24329AAF003C0B8F /* Build configuration list for PBXNativeTarget "libpappl_static" */ = { isa = XCConfigurationList; buildConfigurations = ( 27FFF30924329AAF003C0B8F /* Debug */, 27FFF30A24329AAF003C0B8F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 27FFF39024329C9E003C0B8F /* Build configuration list for PBXNativeTarget "libpappl" */ = { isa = XCConfigurationList; buildConfigurations = ( 27FFF39124329C9E003C0B8F /* Debug */, 27FFF39224329C9E003C0B8F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 273C6EEC240D8729000F85E7 /* Project object */; } pappl-1.4.9/xcode/pappl.xcodeproj/project.xcworkspace/000077500000000000000000000000001476704353100230635ustar00rootroot00000000000000pappl-1.4.9/xcode/pappl.xcodeproj/project.xcworkspace/contents.xcworkspacedata000066400000000000000000000002261476704353100300250ustar00rootroot00000000000000 pappl-1.4.9/xcode/pappl.xcodeproj/project.xcworkspace/xcshareddata/000077500000000000000000000000001476704353100255165ustar00rootroot00000000000000pappl-1.4.9/xcode/pappl.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist000066400000000000000000000003561476704353100322000ustar00rootroot00000000000000 IDEDidComputeMac32BitWarning