HTTP and IPP API introduction for CUPS.
- Copyright 2007-2011 by Apple Inc.
+ Copyright 2007-2012 by Apple Inc.
Copyright 1997-2006 by Easy Software Products, all rights reserved.
These coded instructions, statements, and computer programs are the
<code>cups</code> functions to refer to the default CUPS server - the functions
create a per-thread <a href='#http_t'><code>http_t</code></a> as needed.</p>
-<p>The IPP APIs use two structures for requests (messages sent to the CUPS
-scheduler) and responses (messages sent back to your application from the
-scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> structure holds a
-complete request or response and is allocated using the
-<a href='#ippNew'><code>ippNew</code></a> or
-<a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and
-freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
-
-<p>The second structure is called
-<a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a
-single IPP attribute which consists of a group tag (<code>group_tag</code>), a
-value type tag (<code>value_tag</code>), the attribute name (<code>name</code>),
-and 1 or more values (<code>values[]</code>). Attributes are added to an
-<a href='#ipp_t'><code>ipp_t</code></a> structure using one of the
-<code>ippAdd</code> functions. For example, use
-<a href='#ippAddString'><code>ippAddString</code></a> to add a
-"requesting-user-name" string attribute to a request:</p>
+<p>The IPP APIs use two opaque structures for requests (messages sent to the CUPS scheduler) and responses (messages sent back to your application from the scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> type holds a complete request or response and is allocated using the <a href='#ippNew'><code>ippNew</code></a> or <a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
+
+<p>The second opaque structure is called <a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a single IPP attribute which consists of a group tag (<a href='#ippGetGroupTag'><code>ippGetGroupTag</code></a>), a value type tag (<a href='#ippGetValueTag'><code>ippGetValueTag</code></a>), the attribute name (<a href='#ippGetName'><code>ippGetName</code></a>), and 1 or more values (<a href='#ippGetCount'><code>ippGetCount</code></a>, <a href='#ippGetBoolean'><code>ippGetBoolean</code></a>, <a href='#ippGetCollection'><code>ippGetCollection</code></a>, <a href='#ippGetDate'><code>ippGetDate</code></a>, <a href='#ippGetInteger'><code>ippGetInteger</code></a>, <a href='#ippGetRange'><code>ippGetRange</code></a>, <a href='#ippGetResolution'><code>ippGetResolution</code></a>, and <a href='#ippGetString'><code>ippGetString</code></a>). Attributes are added to an <a href='#ipp_t'><code>ipp_t</code></a> pointer using one of the <code>ippAdd</code> functions. For example, use <a href='#ippAddString'><code>ippAddString</code></a> to add the "printer-uri" and "requesting-user-name" string attributes to a request:</p>
<pre class='example'>
<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
+<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
</pre>
-<p>Once you have created an IPP request, use the <code>cups</code>
-functions to send the request to and read the response from the server.
-For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a>
-function can be used for simple query operations that do not involve files:</p>
+<p>Once you have created an IPP request, use the <code>cups</code> functions to send the request to and read the response from the server. For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function can be used for simple query operations that do not involve files:</p>
<pre class='example'>
#include <cups/cups.h>
{
<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
+ <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
}
</pre>
-<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees
-the request structure and returns an IPP response structure or NULL pointer if
-the request could not be sent to the server. Once you have a response from
-the server, you can either use the
-<a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and
-<a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions
-to find specific attributes, for example:</p>
+<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees the request and returns an IPP response or <code>NULL</code> pointer if the request could not be sent to the server. Once you have a response from the server, you can either use the <a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and <a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions to find specific attributes, for example:</p>
<pre class='example'>
<a href='#ipp_t'>ipp_t</a> *response;
attr = <a href='#ippFindAttribute'>ippFindAttribute</a>(response, "printer-state", IPP_TAG_ENUM);
</pre>
-<p>You can also walk the list of attributes with a simple <code>for</code> loop
-like this:</p>
+<p>You can also walk the list of attributes with a simple <code>for</code> loop like this:</p>
<pre class='example'>
<a href='#ipp_t'>ipp_t</a> *response;
<a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
-for (attr = response->attrs; attr != NULL; attr = attr->next)
- if (attr->name == NULL)
+for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
+ if (ippGetName(attr) == NULL)
puts("--SEPARATOR--");
else
- puts(attr->name);
+ puts(ippGetName(attr));
</pre>
-<p>The <code>for</code> loop approach is normally used when collecting
-attributes for multiple objects (jobs, printers, etc.) in a response. Attributes
-with <code>NULL</code> names indicate a separator between the attributes of
-each object. For example, the following code will list the jobs returned from
-our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
+<p>The <code>for</code> loop approach is normally used when collecting attributes for multiple objects (jobs, printers, etc.) in a response. Attributes with <code>NULL</code> names indicate a separator between the attributes of each object. For example, the following code will list the jobs returned from our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
<pre class='example'>
<a href='#ipp_t'>ipp_t</a> *response = <a href='#get_jobs'>get_jobs</a>();
if (response != NULL)
{
<a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
+ const char *attrname;
int job_id = 0;
- char *job_name = NULL;
- char *job_originating_user_name = NULL;
+ const char *job_name = NULL;
+ const char *job_originating_user_name = NULL;
puts("Job ID Owner Title");
puts("------ ---------------- ---------------------------------");
- for (attr = response->attrs; attr != NULL; attr = attr->next)
+ for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
{
/* Attributes without names are separators between jobs */
- if (attr->name == NULL)
+ attrname = ippGetName(attr);
+ if (attrname == NULL)
{
- if (job_id > 0 && job_name != NULL && job_originating_user_name != NULL)
+ if (job_id > 0)
+ {
+ if (job_name == NULL)
+ job_name = "(withheld)";
+
+ if (job_originating_user_name == NULL)
+ job_originating_user_name = "(withheld)";
+
printf("%5d %-16s %s\n", job_id, job_originating_user_name, job_name);
+ }
job_id = 0;
job_name = NULL;
job_originating_user_name = NULL;
continue;
}
- else if (!strcmp(attr->name, "job-id") && attr->value_tag == IPP_TAG_INTEGER)
- job_id = attr->values[0].integer;
- else if (!strcmp(attr->name, "job-name") && attr->value_tag == IPP_TAG_NAME)
- job_name = attr->values[0].string.text;
- else if (!strcmp(attr->name, "job-originating-user-name") &&
- attr->value_tag == IPP_TAG_NAME)
- job_originating_user_name = attr->values[0].string.text;
+ else if (!strcmp(attrname, "job-id") && ippGetValueTag(attr) == IPP_TAG_INTEGER)
+ job_id = ippGetInteger(attr, 0);
+ else if (!strcmp(attrname, "job-name") && ippGetValueTag(attr) == IPP_TAG_NAME)
+ job_name = ippGetString(attr, 0, NULL);
+ else if (!strcmp(attrname, "job-originating-user-name") &&
+ ippGetValueTag(attr) == IPP_TAG_NAME)
+ job_originating_user_name = ippGetString(attr, 0, NULL);
}
- if (job_id > 0 && job_name != NULL && job_originating_user_name != NULL)
+ if (job_id > 0)
+ {
+ if (job_name == NULL)
+ job_name = "(withheld)";
+
+ if (job_originating_user_name == NULL)
+ job_originating_user_name = "(withheld)";
+
printf("%5d %-16s %s\n", job_id, job_originating_user_name, job_name);
+ }
}
</pre>