]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/cupspm.md
Support <hex> strings in IPP files.
[thirdparty/cups.git] / cups / cupspm.md
index 5bbce4b5ae5d0cd7fbc2bb2a82524fd66159cc46..260b261f512033293c9f547703b75b9705ee8350 100644 (file)
@@ -1,14 +1,12 @@
 ---
 title: CUPS Programming Manual
 author: Michael R Sweet
-copyright: Copyright © 2007-2017 by Apple Inc. All Rights Reserved.
-version: 2.2.4
+copyright: Copyright © 2007-2019 by Apple Inc. All Rights Reserved.
+version: 2.3.0
 ...
 
-> Note: This document is under active development and is incomplete, with a goal
-> completing it prior to releasing CUPS 2.2.4.  Please
-> [file issues on Github](https://github.com/apple/cups/issues)
-> to provide any feedback.
+> Please [file issues on Github](https://github.com/apple/cups/issues) to
+> provide feedback on this document.
 
 
 # Introduction
@@ -27,7 +25,7 @@ the CUPS scheduler.
 
 ## Guidelines
 
-When writing software that uses the "cups" library:
+When writing software (other than printer drivers) that uses the "cups" library:
 
 - Do not use undocumented or deprecated APIs,
 - Do not rely on pre-configured printers,
@@ -44,16 +42,23 @@ Similarly, printer and job management applications can use standard query
 operations to obtain the status information in a common, generic form and use
 standard management operations to control the state of those printers and jobs.
 
+> **Note:**
+>
+> CUPS printer drivers necessarily depend on specific file formats and certain
+> implementation details of the CUPS software.  Please consult the Postscript
+> and raster printer driver developer documentation on
+> [CUPS.org](https://www.cups.org/documentation.html) for more information.
+
 
 ## Terms Used in This Document
 
 A *Destination* is a printer or print queue that accepts print jobs.  A
-*Print Job* is one or more documents that are processed by a destination
-using options supplied when creating the job.  A *Document* is a file (JPEG
-image, PDF file, etc.) suitable for printing.  An *Option* controls some aspect
-of printing, such as the media used. *Media* is the sheets or roll that is
-printed on.  An *Attribute* is an option encoded for an Internet Printing
-Protocol (IPP) request.
+*Print Job* is a collection of one or more documents that are processed by a
+destination using options supplied when creating the job.  A *Document* is a
+file (JPEG image, PDF file, etc.) suitable for printing.  An *Option* controls
+some aspect of printing, such as the media used. *Media* is the sheets or roll
+that is printed on.  An *Attribute* is an option encoded for an Internet
+Printing Protocol (IPP) request.
 
 
 ## Compiling Programs That Use the CUPS API
@@ -197,6 +202,12 @@ can have any of the following constant (bit) values set:
 
 The callback function returns 0 to stop enumeration or 1 to continue.
 
+> **Note:**
+>
+> The callback function will likely be called multiple times for the
+> same destination, so it is up to the caller to suppress any duplicate
+> destinations.
+
 The following example shows how to use `cupsEnumDests` to get a filtered array
 of destinations:
 
@@ -605,8 +616,9 @@ Finally, the `cupsGetDestMediaDefault` function returns the default media size:
 
 ### Localizing Options and Values
 
-CUPS provides three functions to get localized versions of options and values:
-`cupsLocalizeDestMedia`, `cupsLocalizeDestOption`, and `cupsLocalizeDestValue`:
+CUPS provides three functions to get localized, human-readable strings in the
+user's current locale for options and values: `cupsLocalizeDestMedia`,
+`cupsLocalizeDestOption`, and `cupsLocalizeDestValue`:
 
     const char *
     cupsLocalizeDestMedia(http_t *http, cups_dest_t *dest,
@@ -725,3 +737,269 @@ created:
     }
 
     fclose(fp);
+
+
+# Sending IPP Requests
+
+CUPS provides a rich API for sending IPP requests to the scheduler or printers,
+typically from management or utility applications whose primary purpose is not
+to send print jobs.
+
+
+## Connecting to the Scheduler or Printer
+
+The connection to the scheduler or printer is represented by the HTTP connection
+type `http_t`.  The `cupsConnectDest` function connects to the scheduler or
+printer associated with the destination:
+
+    http_t *
+    cupsConnectDest(cups_dest_t *dest, unsigned flags, int msec,
+                    int *cancel, char *resource,
+                    size_t resourcesize, cups_dest_cb_t cb,
+                    void *user_data);
+
+The `dest` argument specifies the destination to connect to.
+
+The `flags` argument specifies whether you want to connect to the scheduler
+(`CUPS_DEST_FLAGS_NONE`) or device/printer (`CUPS_DEST_FLAGS_DEVICE`) associated
+with the destination.
+
+The `msec` argument specifies how long you are willing to wait for the
+connection to be established in milliseconds.  Specify a value of `-1` to wait
+indefinitely.
+
+The `cancel` argument specifies the address of an integer variable that can be
+set to a non-zero value to cancel the connection.  Specify a value of `NULL`
+to not provide a cancel variable.
+
+The `resource` and `resourcesize` arguments specify the address and size of a
+character string array to hold the path to use when sending an IPP request.
+
+The `cb` and `user_data` arguments specify a destination callback function that
+returns 1 to continue connecting or 0 to stop.  The destination callback work
+the same way as the one used for the `cupsEnumDests` function.
+
+On success, a HTTP connection is returned that can be used to send IPP requests
+and get IPP responses.
+
+For example, the following code connects to the printer associated with a
+destination with a 30 second timeout:
+
+    char resource[256];
+    http_t *http = cupsConnectDest(dest, CUPS_DEST_FLAGS_DEVICE,
+                                   30000, NULL, resource,
+                                   sizeof(resource), NULL, NULL);
+
+
+## Creating an IPP Request
+
+IPP requests are represented by the IPP message type `ipp_t` and each IPP
+attribute in the request is representing using the type `ipp_attribute_t`.  Each
+IPP request includes an operation code (`IPP_OP_CREATE_JOB`,
+`IPP_OP_GET_PRINTER_ATTRIBUTES`, etc.) and a 32-bit integer identifier.
+
+The `ippNewRequest` function creates a new IPP request:
+
+    ipp_t *
+    ippNewRequest(ipp_op_t op);
+
+The `op` argument specifies the IPP operation code for the request.  For
+example, the following code creates an IPP Get-Printer-Attributes request:
+
+    ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+
+The request identifier is automatically set to a unique value for the current
+process.
+
+Each IPP request starts with two IPP attributes, "attributes-charset" and
+"attributes-natural-language", followed by IPP attribute(s) that specify the
+target of the operation.  The `ippNewRequest` automatically adds the correct
+"attributes-charset" and "attributes-natural-language" attributes, but you must
+add the target attribute(s).  For example, the following code adds the
+"printer-uri" attribute to the IPP Get-Printer-Attributes request to specify
+which printer is being queried:
+
+    const char *printer_uri = cupsGetOption("device-uri",
+                                            dest->num_options,
+                                            dest->options);
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+                 "printer-uri", NULL, printer_uri);
+
+> **Note:**
+>
+> If we wanted to query the scheduler instead of the device, we would look
+> up the "printer-uri-supported" option instead of the "device-uri" value.
+
+The `ippAddString` function adds the "printer-uri" attribute the the IPP
+request.  The `IPP_TAG_OPERATION` argument specifies that the attribute is part
+of the operation.  The `IPP_TAG_URI` argument specifies that the value is a
+Universal Resource Identifier (URI) string.  The `NULL` argument specifies there
+is no language (English, French, Japanese, etc.) associated with the string, and
+the `printer_uri` argument specifies the string value.
+
+The IPP Get-Printer-Attributes request also supports an IPP attribute called
+"requested-attributes" that lists the attributes and values you are interested
+in.  For example, the following code requests the printer state attributes:
+
+    static const char * const requested_attributes[] =
+    {
+      "printer-state",
+      "printer-state-message",
+      "printer-state-reasons"
+    };
+
+    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                  "requested-attributes", 3, NULL,
+                  requested_attributes);
+
+The `ippAddStrings` function adds an attribute with one or more strings, in this
+case three.  The `IPP_TAG_KEYWORD` argument specifies that the strings are
+keyword values, which are used for attribute names.  All strings use the same
+language (`NULL`), and the attribute will contain the three strings in the
+array `requested_attributes`.
+
+CUPS provides many functions to adding attributes of different types:
+
+- `ippAddBoolean` adds a boolean (`IPP_TAG_BOOLEAN`) attribute with one value.
+- `ippAddInteger` adds an enum (`IPP_TAG_ENUM`) or integer (`IPP_TAG_INTEGER`)
+  attribute with one value.
+- `ippAddIntegers` adds an enum or integer attribute with one or more values.
+- `ippAddOctetString` adds an octetString attribute with one value.
+- `ippAddOutOfBand` adds a admin-defined (`IPP_TAG_ADMINDEFINE`), default
+  (`IPP_TAG_DEFAULT`), delete-attribute (`IPP_TAG_DELETEATTR`), no-value
+  (`IPP_TAG_NOVALUE`), not-settable (`IPP_TAG_NOTSETTABLE`), unknown
+  (`IPP_TAG_UNKNOWN`), or unsupported (`IPP_TAG_UNSUPPORTED_VALUE`) out-of-band
+  attribute.
+- `ippAddRange` adds a rangeOfInteger attribute with one range.
+- `ippAddRanges` adds a rangeOfInteger attribute with one or more ranges.
+- `ippAddResolution` adds a resolution attribute with one resolution.
+- `ippAddResolutions` adds a resolution attribute with one or more resolutions.
+- `ippAddString` adds a charset (`IPP_TAG_CHARSET`), keyword (`IPP_TAG_KEYWORD`),
+  mimeMediaType (`IPP_TAG_MIMETYPE`), name (`IPP_TAG_NAME` and
+  `IPP_TAG_NAMELANG`), naturalLanguage (`IPP_TAG_NATURAL_LANGUAGE`), text
+  (`IPP_TAG_TEXT` and `IPP_TAG_TEXTLANG`), uri (`IPP_TAG_URI`), or uriScheme
+  (`IPP_TAG_URISCHEME`) attribute with one value.
+- `ippAddStrings` adds a charset, keyword, mimeMediaType, name, naturalLanguage,
+  text, uri, or uriScheme attribute with one or more values.
+
+
+## Sending the IPP Request
+
+Once you have created the IPP request, you can send it using the
+`cupsDoRequest` function.  For example, the following code sends the IPP
+Get-Printer-Attributes request to the destination and saves the response:
+
+    ipp_t *response = cupsDoRequest(http, request, resource);
+
+For requests like Send-Document that include a file, the `cupsDoFileRequest`
+function should be used:
+
+    ipp_t *response = cupsDoFileRequest(http, request, resource,
+                                        filename);
+
+Both `cupsDoRequest` and `cupsDoFileRequest` free the IPP request.  If a valid
+IPP response is received, it is stored in a new IPP message (`ipp_t`) and
+returned to the caller.  Otherwise `NULL` is returned.
+
+The status from the most recent request can be queried using the `cupsLastError`
+function, for example:
+
+    if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
+    {
+      /* request failed */
+    }
+
+A human-readable error message is also available using the `cupsLastErrorString`
+function:
+
+    if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
+    {
+      /* request failed */
+      printf("Request failed: %s\n", cupsLastErrorString());
+    }
+
+
+## Processing the IPP Response
+
+Each response to an IPP request is also an IPP message (`ipp_t`) with its own
+IPP attributes (`ipp_attribute_t`) that includes a status code (`IPP_STATUS_OK`,
+`IPP_STATUS_ERROR_BAD_REQUEST`, etc.) and the corresponding 32-bit integer
+identifier from the request.
+
+For example, the following code finds the printer state attributes and prints
+their values:
+
+    ipp_attribute_t *attr;
+
+    if ((attr = ippFindAttribute(response, "printer-state",
+                                 IPP_TAG_ENUM)) != NULL)
+    {
+      printf("printer-state=%s\n",
+             ippEnumString("printer-state", ippGetInteger(attr, 0)));
+    }
+    else
+      puts("printer-state=unknown");
+
+    if ((attr = ippFindAttribute(response, "printer-state-message",
+                                 IPP_TAG_TEXT)) != NULL)
+    {
+      printf("printer-state-message=\"%s\"\n",
+             ippGetString(attr, 0, NULL)));
+    }
+
+    if ((attr = ippFindAttribute(response, "printer-state-reasons",
+                                 IPP_TAG_KEYWORD)) != NULL)
+    {
+      int i, count = ippGetCount(attr);
+
+      puts("printer-state-reasons=");
+      for (i = 0; i < count; i ++)
+        printf("    %s\n", ippGetString(attr, i, NULL)));
+    }
+
+The `ippGetCount` function returns the number of values in an attribute.
+
+The `ippGetInteger` and `ippGetString` functions return a single integer or
+string value from an attribute.
+
+The `ippEnumString` function converts a enum value to its keyword (string)
+equivalent.
+
+Once you are done using the IPP response message, free it using the `ippDelete`
+function:
+
+    ippDelete(response);
+
+
+## Authentication
+
+CUPS normally handles authentication through the console.  GUI applications
+should set a password callback using the `cupsSetPasswordCB2` function:
+
+    void
+    cupsSetPasswordCB2(cups_password_cb2_t cb, void *user_data);
+
+The password callback will be called when needed and is responsible for setting
+the current user name using `cupsSetUser` and returning a string:
+
+    const char *
+    cups_password_cb2(const char *prompt, http_t *http,
+                      const char *method, const char *resource,
+                      void *user_data);
+
+The `prompt` argument is a string from CUPS that should be displayed to the
+user.
+
+The `http` argument is the connection hosting the request that is being
+authenticated.  The password callback can call the `httpGetField` and
+`httpGetSubField` functions to look for additional details concerning the
+authentication challenge.
+
+The `method` argument specifies the HTTP method used for the request and is
+typically "POST".
+
+The `resource` argument specifies the path used for the request.
+
+The `user_data` argument provides the user data pointer from the
+`cupsSetPasswordCB2` call.