xref: /aosp_15_r20/external/libcups/cups/ipp.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Internet Printing Protocol functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2021 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <regex.h>
18*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
19*5e7646d2SAndroid Build Coastguard Worker #  include <io.h>
20*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker 
23*5e7646d2SAndroid Build Coastguard Worker /*
24*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
25*5e7646d2SAndroid Build Coastguard Worker  */
26*5e7646d2SAndroid Build Coastguard Worker 
27*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t	*ipp_add_attr(ipp_t *ipp, const char *name,
28*5e7646d2SAndroid Build Coastguard Worker 			              ipp_tag_t  group_tag, ipp_tag_t value_tag,
29*5e7646d2SAndroid Build Coastguard Worker 			              int num_values);
30*5e7646d2SAndroid Build Coastguard Worker static void		ipp_free_values(ipp_attribute_t *attr, int element,
31*5e7646d2SAndroid Build Coastguard Worker 			                int count);
32*5e7646d2SAndroid Build Coastguard Worker static char		*ipp_get_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL(1,2);
33*5e7646d2SAndroid Build Coastguard Worker static char		*ipp_lang_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL(1,2);
34*5e7646d2SAndroid Build Coastguard Worker static size_t		ipp_length(ipp_t *ipp, int collection);
35*5e7646d2SAndroid Build Coastguard Worker static ssize_t		ipp_read_http(http_t *http, ipp_uchar_t *buffer,
36*5e7646d2SAndroid Build Coastguard Worker 			              size_t length);
37*5e7646d2SAndroid Build Coastguard Worker static ssize_t		ipp_read_file(int *fd, ipp_uchar_t *buffer,
38*5e7646d2SAndroid Build Coastguard Worker 			              size_t length);
39*5e7646d2SAndroid Build Coastguard Worker static void		ipp_set_error(ipp_status_t status, const char *format,
40*5e7646d2SAndroid Build Coastguard Worker 			              ...);
41*5e7646d2SAndroid Build Coastguard Worker static _ipp_value_t	*ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr,
42*5e7646d2SAndroid Build Coastguard Worker 			               int element);
43*5e7646d2SAndroid Build Coastguard Worker static ssize_t		ipp_write_file(int *fd, ipp_uchar_t *buffer,
44*5e7646d2SAndroid Build Coastguard Worker 			               size_t length);
45*5e7646d2SAndroid Build Coastguard Worker 
46*5e7646d2SAndroid Build Coastguard Worker 
47*5e7646d2SAndroid Build Coastguard Worker /*
48*5e7646d2SAndroid Build Coastguard Worker  * '_cupsBufferGet()' - Get a read/write buffer.
49*5e7646d2SAndroid Build Coastguard Worker  */
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker char *					/* O - Buffer */
_cupsBufferGet(size_t size)52*5e7646d2SAndroid Build Coastguard Worker _cupsBufferGet(size_t size)		/* I - Size required */
53*5e7646d2SAndroid Build Coastguard Worker {
54*5e7646d2SAndroid Build Coastguard Worker   _cups_buffer_t	*buffer;	/* Current buffer */
55*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t	*cg = _cupsGlobals();
56*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
57*5e7646d2SAndroid Build Coastguard Worker 
58*5e7646d2SAndroid Build Coastguard Worker 
59*5e7646d2SAndroid Build Coastguard Worker   for (buffer = cg->cups_buffers; buffer; buffer = buffer->next)
60*5e7646d2SAndroid Build Coastguard Worker     if (!buffer->used && buffer->size >= size)
61*5e7646d2SAndroid Build Coastguard Worker       break;
62*5e7646d2SAndroid Build Coastguard Worker 
63*5e7646d2SAndroid Build Coastguard Worker   if (!buffer)
64*5e7646d2SAndroid Build Coastguard Worker   {
65*5e7646d2SAndroid Build Coastguard Worker     if ((buffer = malloc(sizeof(_cups_buffer_t) + size - 1)) == NULL)
66*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
67*5e7646d2SAndroid Build Coastguard Worker 
68*5e7646d2SAndroid Build Coastguard Worker     buffer->next     = cg->cups_buffers;
69*5e7646d2SAndroid Build Coastguard Worker     buffer->size     = size;
70*5e7646d2SAndroid Build Coastguard Worker     cg->cups_buffers = buffer;
71*5e7646d2SAndroid Build Coastguard Worker   }
72*5e7646d2SAndroid Build Coastguard Worker 
73*5e7646d2SAndroid Build Coastguard Worker   buffer->used = 1;
74*5e7646d2SAndroid Build Coastguard Worker 
75*5e7646d2SAndroid Build Coastguard Worker   return (buffer->d);
76*5e7646d2SAndroid Build Coastguard Worker }
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker 
79*5e7646d2SAndroid Build Coastguard Worker /*
80*5e7646d2SAndroid Build Coastguard Worker  * '_cupsBufferRelease()' - Release a read/write buffer.
81*5e7646d2SAndroid Build Coastguard Worker  */
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker void
_cupsBufferRelease(char * b)84*5e7646d2SAndroid Build Coastguard Worker _cupsBufferRelease(char *b)		/* I - Buffer to release */
85*5e7646d2SAndroid Build Coastguard Worker {
86*5e7646d2SAndroid Build Coastguard Worker   _cups_buffer_t	*buffer;	/* Buffer */
87*5e7646d2SAndroid Build Coastguard Worker 
88*5e7646d2SAndroid Build Coastguard Worker 
89*5e7646d2SAndroid Build Coastguard Worker  /*
90*5e7646d2SAndroid Build Coastguard Worker   * Mark this buffer as unused...
91*5e7646d2SAndroid Build Coastguard Worker   */
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker   buffer       = (_cups_buffer_t *)(b - offsetof(_cups_buffer_t, d));
94*5e7646d2SAndroid Build Coastguard Worker   buffer->used = 0;
95*5e7646d2SAndroid Build Coastguard Worker }
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker 
98*5e7646d2SAndroid Build Coastguard Worker /*
99*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
100*5e7646d2SAndroid Build Coastguard Worker  *
101*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
102*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
103*5e7646d2SAndroid Build Coastguard Worker  *
104*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
105*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
106*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
107*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
108*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
109*5e7646d2SAndroid Build Coastguard Worker  */
110*5e7646d2SAndroid Build Coastguard Worker 
111*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddBoolean(ipp_t * ipp,ipp_tag_t group,const char * name,char value)112*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(ipp_t      *ipp,		/* I - IPP message */
113*5e7646d2SAndroid Build Coastguard Worker               ipp_tag_t  group,		/* I - IPP group */
114*5e7646d2SAndroid Build Coastguard Worker               const char *name,		/* I - Name of attribute */
115*5e7646d2SAndroid Build Coastguard Worker               char       value)		/* I - Value of attribute */
116*5e7646d2SAndroid Build Coastguard Worker {
117*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
118*5e7646d2SAndroid Build Coastguard Worker 
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)", (void *)ipp, group, ippTagString(group), name, value));
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker  /*
123*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
124*5e7646d2SAndroid Build Coastguard Worker   */
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
127*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
128*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
129*5e7646d2SAndroid Build Coastguard Worker 
130*5e7646d2SAndroid Build Coastguard Worker  /*
131*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
132*5e7646d2SAndroid Build Coastguard Worker   */
133*5e7646d2SAndroid Build Coastguard Worker 
134*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, 1)) == NULL)
135*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].boolean = value;
138*5e7646d2SAndroid Build Coastguard Worker 
139*5e7646d2SAndroid Build Coastguard Worker   return (attr);
140*5e7646d2SAndroid Build Coastguard Worker }
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker 
143*5e7646d2SAndroid Build Coastguard Worker /*
144*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddBooleans()' - Add an array of boolean values.
145*5e7646d2SAndroid Build Coastguard Worker  *
146*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
147*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
148*5e7646d2SAndroid Build Coastguard Worker  *
149*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
150*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
151*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
152*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
153*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
154*5e7646d2SAndroid Build Coastguard Worker  */
155*5e7646d2SAndroid Build Coastguard Worker 
156*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddBooleans(ipp_t * ipp,ipp_tag_t group,const char * name,int num_values,const char * values)157*5e7646d2SAndroid Build Coastguard Worker ippAddBooleans(ipp_t      *ipp,		/* I - IPP message */
158*5e7646d2SAndroid Build Coastguard Worker                ipp_tag_t  group,	/* I - IPP group */
159*5e7646d2SAndroid Build Coastguard Worker 	       const char *name,	/* I - Name of attribute */
160*5e7646d2SAndroid Build Coastguard Worker 	       int        num_values,	/* I - Number of values */
161*5e7646d2SAndroid Build Coastguard Worker 	       const char *values)	/* I - Values */
162*5e7646d2SAndroid Build Coastguard Worker {
163*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
164*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
165*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", num_values=%d, values=%p)", (void *)ipp, group, ippTagString(group), name, num_values, (void *)values));
169*5e7646d2SAndroid Build Coastguard Worker 
170*5e7646d2SAndroid Build Coastguard Worker  /*
171*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
172*5e7646d2SAndroid Build Coastguard Worker   */
173*5e7646d2SAndroid Build Coastguard Worker 
174*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
175*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
176*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
177*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
178*5e7646d2SAndroid Build Coastguard Worker 
179*5e7646d2SAndroid Build Coastguard Worker  /*
180*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
181*5e7646d2SAndroid Build Coastguard Worker   */
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, num_values)) == NULL)
184*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker   if (values)
187*5e7646d2SAndroid Build Coastguard Worker   {
188*5e7646d2SAndroid Build Coastguard Worker     for (i = num_values, value = attr->values;
189*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
190*5e7646d2SAndroid Build Coastguard Worker 	 i --, value ++)
191*5e7646d2SAndroid Build Coastguard Worker       value->boolean = *values++;
192*5e7646d2SAndroid Build Coastguard Worker   }
193*5e7646d2SAndroid Build Coastguard Worker 
194*5e7646d2SAndroid Build Coastguard Worker   return (attr);
195*5e7646d2SAndroid Build Coastguard Worker }
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker /*
199*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddCollection()' - Add a collection value.
200*5e7646d2SAndroid Build Coastguard Worker  *
201*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
202*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
203*5e7646d2SAndroid Build Coastguard Worker  *
204*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
205*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
206*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
207*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
208*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
209*5e7646d2SAndroid Build Coastguard Worker  *
210*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
211*5e7646d2SAndroid Build Coastguard Worker  */
212*5e7646d2SAndroid Build Coastguard Worker 
213*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddCollection(ipp_t * ipp,ipp_tag_t group,const char * name,ipp_t * value)214*5e7646d2SAndroid Build Coastguard Worker ippAddCollection(ipp_t      *ipp,	/* I - IPP message */
215*5e7646d2SAndroid Build Coastguard Worker                  ipp_tag_t  group,	/* I - IPP group */
216*5e7646d2SAndroid Build Coastguard Worker 		 const char *name,	/* I - Name of attribute */
217*5e7646d2SAndroid Build Coastguard Worker 		 ipp_t      *value)	/* I - Value */
218*5e7646d2SAndroid Build Coastguard Worker {
219*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
220*5e7646d2SAndroid Build Coastguard Worker 
221*5e7646d2SAndroid Build Coastguard Worker 
222*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)", (void *)ipp, group, ippTagString(group), name, (void *)value));
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker  /*
225*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
226*5e7646d2SAndroid Build Coastguard Worker   */
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
229*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
230*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
231*5e7646d2SAndroid Build Coastguard Worker 
232*5e7646d2SAndroid Build Coastguard Worker  /*
233*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
234*5e7646d2SAndroid Build Coastguard Worker   */
235*5e7646d2SAndroid Build Coastguard Worker 
236*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION, 1)) == NULL)
237*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
238*5e7646d2SAndroid Build Coastguard Worker 
239*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].collection = value;
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker   if (value)
242*5e7646d2SAndroid Build Coastguard Worker     value->use ++;
243*5e7646d2SAndroid Build Coastguard Worker 
244*5e7646d2SAndroid Build Coastguard Worker   return (attr);
245*5e7646d2SAndroid Build Coastguard Worker }
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker 
248*5e7646d2SAndroid Build Coastguard Worker /*
249*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddCollections()' - Add an array of collection values.
250*5e7646d2SAndroid Build Coastguard Worker  *
251*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
252*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
253*5e7646d2SAndroid Build Coastguard Worker  *
254*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
255*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
256*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
257*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
258*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
259*5e7646d2SAndroid Build Coastguard Worker  *
260*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
261*5e7646d2SAndroid Build Coastguard Worker  */
262*5e7646d2SAndroid Build Coastguard Worker 
263*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddCollections(ipp_t * ipp,ipp_tag_t group,const char * name,int num_values,const ipp_t ** values)264*5e7646d2SAndroid Build Coastguard Worker ippAddCollections(
265*5e7646d2SAndroid Build Coastguard Worker     ipp_t       *ipp,			/* I - IPP message */
266*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t   group,			/* I - IPP group */
267*5e7646d2SAndroid Build Coastguard Worker     const char  *name,			/* I - Name of attribute */
268*5e7646d2SAndroid Build Coastguard Worker     int         num_values,		/* I - Number of values */
269*5e7646d2SAndroid Build Coastguard Worker     const ipp_t **values)		/* I - Values */
270*5e7646d2SAndroid Build Coastguard Worker {
271*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
272*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
273*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker 
276*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", num_values=%d, values=%p)", (void *)ipp, group, ippTagString(group), name, num_values, (void *)values));
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker  /*
279*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
280*5e7646d2SAndroid Build Coastguard Worker   */
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
283*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
284*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
285*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
286*5e7646d2SAndroid Build Coastguard Worker 
287*5e7646d2SAndroid Build Coastguard Worker  /*
288*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
289*5e7646d2SAndroid Build Coastguard Worker   */
290*5e7646d2SAndroid Build Coastguard Worker 
291*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION,
292*5e7646d2SAndroid Build Coastguard Worker                            num_values)) == NULL)
293*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker   if (values)
296*5e7646d2SAndroid Build Coastguard Worker   {
297*5e7646d2SAndroid Build Coastguard Worker     for (i = num_values, value = attr->values;
298*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
299*5e7646d2SAndroid Build Coastguard Worker 	 i --, value ++)
300*5e7646d2SAndroid Build Coastguard Worker     {
301*5e7646d2SAndroid Build Coastguard Worker       value->collection = (ipp_t *)*values++;
302*5e7646d2SAndroid Build Coastguard Worker       value->collection->use ++;
303*5e7646d2SAndroid Build Coastguard Worker     }
304*5e7646d2SAndroid Build Coastguard Worker   }
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker   return (attr);
307*5e7646d2SAndroid Build Coastguard Worker }
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker /*
311*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddDate()' - Add a dateTime attribute to an IPP message.
312*5e7646d2SAndroid Build Coastguard Worker  *
313*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
314*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
315*5e7646d2SAndroid Build Coastguard Worker  *
316*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
317*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
318*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
319*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
320*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
321*5e7646d2SAndroid Build Coastguard Worker  */
322*5e7646d2SAndroid Build Coastguard Worker 
323*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddDate(ipp_t * ipp,ipp_tag_t group,const char * name,const ipp_uchar_t * value)324*5e7646d2SAndroid Build Coastguard Worker ippAddDate(ipp_t             *ipp,	/* I - IPP message */
325*5e7646d2SAndroid Build Coastguard Worker            ipp_tag_t         group,	/* I - IPP group */
326*5e7646d2SAndroid Build Coastguard Worker 	   const char        *name,	/* I - Name of attribute */
327*5e7646d2SAndroid Build Coastguard Worker 	   const ipp_uchar_t *value)	/* I - Value */
328*5e7646d2SAndroid Build Coastguard Worker {
329*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
330*5e7646d2SAndroid Build Coastguard Worker 
331*5e7646d2SAndroid Build Coastguard Worker 
332*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)", (void *)ipp, group, ippTagString(group), name, (void *)value));
333*5e7646d2SAndroid Build Coastguard Worker 
334*5e7646d2SAndroid Build Coastguard Worker  /*
335*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
336*5e7646d2SAndroid Build Coastguard Worker   */
337*5e7646d2SAndroid Build Coastguard Worker 
338*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || !value || group < IPP_TAG_ZERO ||
339*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
340*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
341*5e7646d2SAndroid Build Coastguard Worker 
342*5e7646d2SAndroid Build Coastguard Worker  /*
343*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
344*5e7646d2SAndroid Build Coastguard Worker   */
345*5e7646d2SAndroid Build Coastguard Worker 
346*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_DATE, 1)) == NULL)
347*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
348*5e7646d2SAndroid Build Coastguard Worker 
349*5e7646d2SAndroid Build Coastguard Worker   memcpy(attr->values[0].date, value, 11);
350*5e7646d2SAndroid Build Coastguard Worker 
351*5e7646d2SAndroid Build Coastguard Worker   return (attr);
352*5e7646d2SAndroid Build Coastguard Worker }
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker /*
356*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddInteger()' - Add a integer attribute to an IPP message.
357*5e7646d2SAndroid Build Coastguard Worker  *
358*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
359*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
360*5e7646d2SAndroid Build Coastguard Worker  *
361*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
362*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
363*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
364*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
365*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
366*5e7646d2SAndroid Build Coastguard Worker  *
367*5e7646d2SAndroid Build Coastguard Worker  * Supported values include enum (@code IPP_TAG_ENUM@) and integer
368*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_INTEGER@).
369*5e7646d2SAndroid Build Coastguard Worker  */
370*5e7646d2SAndroid Build Coastguard Worker 
371*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddInteger(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,int value)372*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(ipp_t      *ipp,		/* I - IPP message */
373*5e7646d2SAndroid Build Coastguard Worker               ipp_tag_t  group,		/* I - IPP group */
374*5e7646d2SAndroid Build Coastguard Worker 	      ipp_tag_t  value_tag,	/* I - Type of attribute */
375*5e7646d2SAndroid Build Coastguard Worker               const char *name,		/* I - Name of attribute */
376*5e7646d2SAndroid Build Coastguard Worker               int        value)		/* I - Value of attribute */
377*5e7646d2SAndroid Build Coastguard Worker {
378*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), name=\"%s\", value=%d)", (void *)ipp, group, ippTagString(group), value_tag, ippTagString(value_tag), name, value));
382*5e7646d2SAndroid Build Coastguard Worker 
383*5e7646d2SAndroid Build Coastguard Worker   value_tag &= IPP_TAG_CUPS_MASK;
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker  /*
386*5e7646d2SAndroid Build Coastguard Worker   * Special-case for legacy usage: map out-of-band attributes to new ippAddOutOfBand
387*5e7646d2SAndroid Build Coastguard Worker   * function...
388*5e7646d2SAndroid Build Coastguard Worker   */
389*5e7646d2SAndroid Build Coastguard Worker 
390*5e7646d2SAndroid Build Coastguard Worker   if (value_tag >= IPP_TAG_UNSUPPORTED_VALUE && value_tag <= IPP_TAG_ADMINDEFINE)
391*5e7646d2SAndroid Build Coastguard Worker     return (ippAddOutOfBand(ipp, group, value_tag, name));
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker  /*
394*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
395*5e7646d2SAndroid Build Coastguard Worker   */
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker #if 0
398*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
399*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
400*5e7646d2SAndroid Build Coastguard Worker       (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM))
401*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
402*5e7646d2SAndroid Build Coastguard Worker #else
403*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
404*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
405*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
406*5e7646d2SAndroid Build Coastguard Worker #endif /* 0 */
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker  /*
409*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
410*5e7646d2SAndroid Build Coastguard Worker   */
411*5e7646d2SAndroid Build Coastguard Worker 
412*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL)
413*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
414*5e7646d2SAndroid Build Coastguard Worker 
415*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].integer = value;
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker   return (attr);
418*5e7646d2SAndroid Build Coastguard Worker }
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker 
421*5e7646d2SAndroid Build Coastguard Worker /*
422*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddIntegers()' - Add an array of integer values.
423*5e7646d2SAndroid Build Coastguard Worker  *
424*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
425*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
426*5e7646d2SAndroid Build Coastguard Worker  *
427*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
428*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
429*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
430*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
431*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
432*5e7646d2SAndroid Build Coastguard Worker  *
433*5e7646d2SAndroid Build Coastguard Worker  * Supported values include enum (@code IPP_TAG_ENUM@) and integer
434*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_INTEGER@).
435*5e7646d2SAndroid Build Coastguard Worker  */
436*5e7646d2SAndroid Build Coastguard Worker 
437*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddIntegers(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,int num_values,const int * values)438*5e7646d2SAndroid Build Coastguard Worker ippAddIntegers(ipp_t      *ipp,		/* I - IPP message */
439*5e7646d2SAndroid Build Coastguard Worker                ipp_tag_t  group,	/* I - IPP group */
440*5e7646d2SAndroid Build Coastguard Worker 	       ipp_tag_t  value_tag,	/* I - Type of attribute */
441*5e7646d2SAndroid Build Coastguard Worker 	       const char *name,	/* I - Name of attribute */
442*5e7646d2SAndroid Build Coastguard Worker 	       int        num_values,	/* I - Number of values */
443*5e7646d2SAndroid Build Coastguard Worker 	       const int  *values)	/* I - Values */
444*5e7646d2SAndroid Build Coastguard Worker {
445*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
446*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
447*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
448*5e7646d2SAndroid Build Coastguard Worker 
449*5e7646d2SAndroid Build Coastguard Worker 
450*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), name=\"%s\", num_values=%d, values=%p)", (void *)ipp, group, ippTagString(group), value_tag, ippTagString(value_tag), name, num_values, (void *)values));
451*5e7646d2SAndroid Build Coastguard Worker 
452*5e7646d2SAndroid Build Coastguard Worker   value_tag &= IPP_TAG_CUPS_MASK;
453*5e7646d2SAndroid Build Coastguard Worker 
454*5e7646d2SAndroid Build Coastguard Worker  /*
455*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
456*5e7646d2SAndroid Build Coastguard Worker   */
457*5e7646d2SAndroid Build Coastguard Worker 
458*5e7646d2SAndroid Build Coastguard Worker #if 0
459*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
460*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
461*5e7646d2SAndroid Build Coastguard Worker       (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM) ||
462*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
463*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
464*5e7646d2SAndroid Build Coastguard Worker #else
465*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
466*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
467*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
468*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
469*5e7646d2SAndroid Build Coastguard Worker #endif /* 0 */
470*5e7646d2SAndroid Build Coastguard Worker 
471*5e7646d2SAndroid Build Coastguard Worker  /*
472*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
473*5e7646d2SAndroid Build Coastguard Worker   */
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL)
476*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
477*5e7646d2SAndroid Build Coastguard Worker 
478*5e7646d2SAndroid Build Coastguard Worker   if (values)
479*5e7646d2SAndroid Build Coastguard Worker   {
480*5e7646d2SAndroid Build Coastguard Worker     for (i = num_values, value = attr->values;
481*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
482*5e7646d2SAndroid Build Coastguard Worker 	 i --, value ++)
483*5e7646d2SAndroid Build Coastguard Worker       value->integer = *values++;
484*5e7646d2SAndroid Build Coastguard Worker   }
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker   return (attr);
487*5e7646d2SAndroid Build Coastguard Worker }
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker 
490*5e7646d2SAndroid Build Coastguard Worker /*
491*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddOctetString()' - Add an octetString value to an IPP message.
492*5e7646d2SAndroid Build Coastguard Worker  *
493*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
494*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
495*5e7646d2SAndroid Build Coastguard Worker  *
496*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
497*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
498*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
499*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
500*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
501*5e7646d2SAndroid Build Coastguard Worker  *
502*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
503*5e7646d2SAndroid Build Coastguard Worker  */
504*5e7646d2SAndroid Build Coastguard Worker 
505*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - New attribute */
ippAddOctetString(ipp_t * ipp,ipp_tag_t group,const char * name,const void * data,int datalen)506*5e7646d2SAndroid Build Coastguard Worker ippAddOctetString(ipp_t      *ipp,	/* I - IPP message */
507*5e7646d2SAndroid Build Coastguard Worker                   ipp_tag_t  group,	/* I - IPP group */
508*5e7646d2SAndroid Build Coastguard Worker                   const char *name,	/* I - Name of attribute */
509*5e7646d2SAndroid Build Coastguard Worker                   const void *data,	/* I - octetString data */
510*5e7646d2SAndroid Build Coastguard Worker 		  int        datalen)	/* I - Length of data in bytes */
511*5e7646d2SAndroid Build Coastguard Worker {
512*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
513*5e7646d2SAndroid Build Coastguard Worker 
514*5e7646d2SAndroid Build Coastguard Worker 
515*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
516*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
517*5e7646d2SAndroid Build Coastguard Worker       datalen < 0 || datalen > IPP_MAX_LENGTH)
518*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_STRING, 1)) == NULL)
521*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker  /*
524*5e7646d2SAndroid Build Coastguard Worker   * Initialize the attribute data...
525*5e7646d2SAndroid Build Coastguard Worker   */
526*5e7646d2SAndroid Build Coastguard Worker 
527*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].unknown.length = datalen;
528*5e7646d2SAndroid Build Coastguard Worker 
529*5e7646d2SAndroid Build Coastguard Worker   if (data)
530*5e7646d2SAndroid Build Coastguard Worker   {
531*5e7646d2SAndroid Build Coastguard Worker     if ((attr->values[0].unknown.data = malloc((size_t)datalen)) == NULL)
532*5e7646d2SAndroid Build Coastguard Worker     {
533*5e7646d2SAndroid Build Coastguard Worker       ippDeleteAttribute(ipp, attr);
534*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
535*5e7646d2SAndroid Build Coastguard Worker     }
536*5e7646d2SAndroid Build Coastguard Worker 
537*5e7646d2SAndroid Build Coastguard Worker     memcpy(attr->values[0].unknown.data, data, (size_t)datalen);
538*5e7646d2SAndroid Build Coastguard Worker   }
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker  /*
541*5e7646d2SAndroid Build Coastguard Worker   * Return the new attribute...
542*5e7646d2SAndroid Build Coastguard Worker   */
543*5e7646d2SAndroid Build Coastguard Worker 
544*5e7646d2SAndroid Build Coastguard Worker   return (attr);
545*5e7646d2SAndroid Build Coastguard Worker }
546*5e7646d2SAndroid Build Coastguard Worker 
547*5e7646d2SAndroid Build Coastguard Worker 
548*5e7646d2SAndroid Build Coastguard Worker /*
549*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddOutOfBand()' - Add an out-of-band value to an IPP message.
550*5e7646d2SAndroid Build Coastguard Worker  *
551*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
552*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
553*5e7646d2SAndroid Build Coastguard Worker  *
554*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
555*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
556*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
557*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
558*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
559*5e7646d2SAndroid Build Coastguard Worker  *
560*5e7646d2SAndroid Build Coastguard Worker  * Supported out-of-band values include unsupported-value
561*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_UNSUPPORTED_VALUE@), default (@code IPP_TAG_DEFAULT@), unknown
562*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_UNKNOWN@), no-value (@code IPP_TAG_NOVALUE@), not-settable
563*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NOTSETTABLE@), delete-attribute (@code IPP_TAG_DELETEATTR@), and
564*5e7646d2SAndroid Build Coastguard Worker  * admin-define (@code IPP_TAG_ADMINDEFINE@).
565*5e7646d2SAndroid Build Coastguard Worker  *
566*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
567*5e7646d2SAndroid Build Coastguard Worker  */
568*5e7646d2SAndroid Build Coastguard Worker 
569*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - New attribute */
ippAddOutOfBand(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name)570*5e7646d2SAndroid Build Coastguard Worker ippAddOutOfBand(ipp_t      *ipp,	/* I - IPP message */
571*5e7646d2SAndroid Build Coastguard Worker                 ipp_tag_t  group,	/* I - IPP group */
572*5e7646d2SAndroid Build Coastguard Worker                 ipp_tag_t  value_tag,	/* I - Type of attribute */
573*5e7646d2SAndroid Build Coastguard Worker 		const char *name)	/* I - Name of attribute */
574*5e7646d2SAndroid Build Coastguard Worker {
575*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddOutOfBand(ipp=%p, group=%02x(%s), value_tag=%02x(%s), name=\"%s\")", (void *)ipp, group, ippTagString(group), value_tag, ippTagString(value_tag), name));
576*5e7646d2SAndroid Build Coastguard Worker 
577*5e7646d2SAndroid Build Coastguard Worker   value_tag &= IPP_TAG_CUPS_MASK;
578*5e7646d2SAndroid Build Coastguard Worker 
579*5e7646d2SAndroid Build Coastguard Worker  /*
580*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
581*5e7646d2SAndroid Build Coastguard Worker   */
582*5e7646d2SAndroid Build Coastguard Worker 
583*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
584*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
585*5e7646d2SAndroid Build Coastguard Worker       (value_tag != IPP_TAG_UNSUPPORTED_VALUE &&
586*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_DEFAULT &&
587*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_UNKNOWN &&
588*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_NOVALUE &&
589*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_NOTSETTABLE &&
590*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_DELETEATTR &&
591*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_ADMINDEFINE))
592*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker  /*
595*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
596*5e7646d2SAndroid Build Coastguard Worker   */
597*5e7646d2SAndroid Build Coastguard Worker 
598*5e7646d2SAndroid Build Coastguard Worker   return (ipp_add_attr(ipp, name, group, value_tag, 1));
599*5e7646d2SAndroid Build Coastguard Worker }
600*5e7646d2SAndroid Build Coastguard Worker 
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker /*
603*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddRange()' - Add a range of values to an IPP message.
604*5e7646d2SAndroid Build Coastguard Worker  *
605*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
606*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
607*5e7646d2SAndroid Build Coastguard Worker  *
608*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
609*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
610*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
611*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
612*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
613*5e7646d2SAndroid Build Coastguard Worker  *
614*5e7646d2SAndroid Build Coastguard Worker  * The @code lower@ parameter must be less than or equal to the @code upper@ parameter.
615*5e7646d2SAndroid Build Coastguard Worker  */
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddRange(ipp_t * ipp,ipp_tag_t group,const char * name,int lower,int upper)618*5e7646d2SAndroid Build Coastguard Worker ippAddRange(ipp_t      *ipp,		/* I - IPP message */
619*5e7646d2SAndroid Build Coastguard Worker             ipp_tag_t  group,		/* I - IPP group */
620*5e7646d2SAndroid Build Coastguard Worker 	    const char *name,		/* I - Name of attribute */
621*5e7646d2SAndroid Build Coastguard Worker 	    int        lower,		/* I - Lower value */
622*5e7646d2SAndroid Build Coastguard Worker 	    int        upper)		/* I - Upper value */
623*5e7646d2SAndroid Build Coastguard Worker {
624*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
625*5e7646d2SAndroid Build Coastguard Worker 
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, upper=%d)", (void *)ipp, group, ippTagString(group), name, lower, upper));
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker  /*
630*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
631*5e7646d2SAndroid Build Coastguard Worker   */
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
634*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
635*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
636*5e7646d2SAndroid Build Coastguard Worker 
637*5e7646d2SAndroid Build Coastguard Worker  /*
638*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
639*5e7646d2SAndroid Build Coastguard Worker   */
640*5e7646d2SAndroid Build Coastguard Worker 
641*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, 1)) == NULL)
642*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
643*5e7646d2SAndroid Build Coastguard Worker 
644*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].range.lower = lower;
645*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].range.upper = upper;
646*5e7646d2SAndroid Build Coastguard Worker 
647*5e7646d2SAndroid Build Coastguard Worker   return (attr);
648*5e7646d2SAndroid Build Coastguard Worker }
649*5e7646d2SAndroid Build Coastguard Worker 
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker /*
652*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddRanges()' - Add ranges of values to an IPP message.
653*5e7646d2SAndroid Build Coastguard Worker  *
654*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
655*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
656*5e7646d2SAndroid Build Coastguard Worker  *
657*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
658*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
659*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
660*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
661*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
662*5e7646d2SAndroid Build Coastguard Worker  */
663*5e7646d2SAndroid Build Coastguard Worker 
664*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddRanges(ipp_t * ipp,ipp_tag_t group,const char * name,int num_values,const int * lower,const int * upper)665*5e7646d2SAndroid Build Coastguard Worker ippAddRanges(ipp_t      *ipp,		/* I - IPP message */
666*5e7646d2SAndroid Build Coastguard Worker              ipp_tag_t  group,		/* I - IPP group */
667*5e7646d2SAndroid Build Coastguard Worker 	     const char *name,		/* I - Name of attribute */
668*5e7646d2SAndroid Build Coastguard Worker 	     int        num_values,	/* I - Number of values */
669*5e7646d2SAndroid Build Coastguard Worker 	     const int  *lower,		/* I - Lower values */
670*5e7646d2SAndroid Build Coastguard Worker 	     const int  *upper)		/* I - Upper values */
671*5e7646d2SAndroid Build Coastguard Worker {
672*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
673*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
674*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
675*5e7646d2SAndroid Build Coastguard Worker 
676*5e7646d2SAndroid Build Coastguard Worker 
677*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", num_values=%d, lower=%p, upper=%p)", (void *)ipp, group, ippTagString(group), name, num_values, (void *)lower, (void *)upper));
678*5e7646d2SAndroid Build Coastguard Worker 
679*5e7646d2SAndroid Build Coastguard Worker  /*
680*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
681*5e7646d2SAndroid Build Coastguard Worker   */
682*5e7646d2SAndroid Build Coastguard Worker 
683*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
684*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
685*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
686*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
687*5e7646d2SAndroid Build Coastguard Worker 
688*5e7646d2SAndroid Build Coastguard Worker  /*
689*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
690*5e7646d2SAndroid Build Coastguard Worker   */
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, num_values)) == NULL)
693*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
694*5e7646d2SAndroid Build Coastguard Worker 
695*5e7646d2SAndroid Build Coastguard Worker   if (lower && upper)
696*5e7646d2SAndroid Build Coastguard Worker   {
697*5e7646d2SAndroid Build Coastguard Worker     for (i = num_values, value = attr->values;
698*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
699*5e7646d2SAndroid Build Coastguard Worker 	 i --, value ++)
700*5e7646d2SAndroid Build Coastguard Worker     {
701*5e7646d2SAndroid Build Coastguard Worker       value->range.lower = *lower++;
702*5e7646d2SAndroid Build Coastguard Worker       value->range.upper = *upper++;
703*5e7646d2SAndroid Build Coastguard Worker     }
704*5e7646d2SAndroid Build Coastguard Worker   }
705*5e7646d2SAndroid Build Coastguard Worker 
706*5e7646d2SAndroid Build Coastguard Worker   return (attr);
707*5e7646d2SAndroid Build Coastguard Worker }
708*5e7646d2SAndroid Build Coastguard Worker 
709*5e7646d2SAndroid Build Coastguard Worker 
710*5e7646d2SAndroid Build Coastguard Worker /*
711*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddResolution()' - Add a resolution value to an IPP message.
712*5e7646d2SAndroid Build Coastguard Worker  *
713*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
714*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
715*5e7646d2SAndroid Build Coastguard Worker  *
716*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
717*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
718*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
719*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
720*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
721*5e7646d2SAndroid Build Coastguard Worker  */
722*5e7646d2SAndroid Build Coastguard Worker 
723*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddResolution(ipp_t * ipp,ipp_tag_t group,const char * name,ipp_res_t units,int xres,int yres)724*5e7646d2SAndroid Build Coastguard Worker ippAddResolution(ipp_t      *ipp,	/* I - IPP message */
725*5e7646d2SAndroid Build Coastguard Worker         	 ipp_tag_t  group,	/* I - IPP group */
726*5e7646d2SAndroid Build Coastguard Worker 		 const char *name,	/* I - Name of attribute */
727*5e7646d2SAndroid Build Coastguard Worker 		 ipp_res_t  units,	/* I - Units for resolution */
728*5e7646d2SAndroid Build Coastguard Worker 		 int        xres,	/* I - X resolution */
729*5e7646d2SAndroid Build Coastguard Worker 		 int        yres)	/* I - Y resolution */
730*5e7646d2SAndroid Build Coastguard Worker {
731*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker 
734*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", units=%d, xres=%d, yres=%d)", (void *)ipp, group,
735*5e7646d2SAndroid Build Coastguard Worker 		ippTagString(group), name, units, xres, yres));
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker  /*
738*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
739*5e7646d2SAndroid Build Coastguard Worker   */
740*5e7646d2SAndroid Build Coastguard Worker 
741*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
742*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
743*5e7646d2SAndroid Build Coastguard Worker       units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM ||
744*5e7646d2SAndroid Build Coastguard Worker       xres < 0 || yres < 0)
745*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
746*5e7646d2SAndroid Build Coastguard Worker 
747*5e7646d2SAndroid Build Coastguard Worker  /*
748*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
749*5e7646d2SAndroid Build Coastguard Worker   */
750*5e7646d2SAndroid Build Coastguard Worker 
751*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, 1)) == NULL)
752*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
753*5e7646d2SAndroid Build Coastguard Worker 
754*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].resolution.xres  = xres;
755*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].resolution.yres  = yres;
756*5e7646d2SAndroid Build Coastguard Worker   attr->values[0].resolution.units = units;
757*5e7646d2SAndroid Build Coastguard Worker 
758*5e7646d2SAndroid Build Coastguard Worker   return (attr);
759*5e7646d2SAndroid Build Coastguard Worker }
760*5e7646d2SAndroid Build Coastguard Worker 
761*5e7646d2SAndroid Build Coastguard Worker 
762*5e7646d2SAndroid Build Coastguard Worker /*
763*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddResolutions()' - Add resolution values to an IPP message.
764*5e7646d2SAndroid Build Coastguard Worker  *
765*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
766*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
767*5e7646d2SAndroid Build Coastguard Worker  *
768*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
769*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
770*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
771*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
772*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
773*5e7646d2SAndroid Build Coastguard Worker  */
774*5e7646d2SAndroid Build Coastguard Worker 
775*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddResolutions(ipp_t * ipp,ipp_tag_t group,const char * name,int num_values,ipp_res_t units,const int * xres,const int * yres)776*5e7646d2SAndroid Build Coastguard Worker ippAddResolutions(ipp_t      *ipp,	/* I - IPP message */
777*5e7646d2SAndroid Build Coastguard Worker         	  ipp_tag_t  group,	/* I - IPP group */
778*5e7646d2SAndroid Build Coastguard Worker 		  const char *name,	/* I - Name of attribute */
779*5e7646d2SAndroid Build Coastguard Worker 		  int        num_values,/* I - Number of values */
780*5e7646d2SAndroid Build Coastguard Worker 		  ipp_res_t  units,	/* I - Units for resolution */
781*5e7646d2SAndroid Build Coastguard Worker 		  const int  *xres,	/* I - X resolutions */
782*5e7646d2SAndroid Build Coastguard Worker 		  const int  *yres)	/* I - Y resolutions */
783*5e7646d2SAndroid Build Coastguard Worker {
784*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
785*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
786*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
787*5e7646d2SAndroid Build Coastguard Worker 
788*5e7646d2SAndroid Build Coastguard Worker 
789*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", num_value=%d, units=%d, xres=%p, yres=%p)", (void *)ipp, group, ippTagString(group), name, num_values, units, (void *)xres, (void *)yres));
790*5e7646d2SAndroid Build Coastguard Worker 
791*5e7646d2SAndroid Build Coastguard Worker  /*
792*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
793*5e7646d2SAndroid Build Coastguard Worker   */
794*5e7646d2SAndroid Build Coastguard Worker 
795*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
796*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
797*5e7646d2SAndroid Build Coastguard Worker       num_values < 1 ||
798*5e7646d2SAndroid Build Coastguard Worker       units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM)
799*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker  /*
802*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
803*5e7646d2SAndroid Build Coastguard Worker   */
804*5e7646d2SAndroid Build Coastguard Worker 
805*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, num_values)) == NULL)
806*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
807*5e7646d2SAndroid Build Coastguard Worker 
808*5e7646d2SAndroid Build Coastguard Worker   if (xres && yres)
809*5e7646d2SAndroid Build Coastguard Worker   {
810*5e7646d2SAndroid Build Coastguard Worker     for (i = num_values, value = attr->values;
811*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
812*5e7646d2SAndroid Build Coastguard Worker 	 i --, value ++)
813*5e7646d2SAndroid Build Coastguard Worker     {
814*5e7646d2SAndroid Build Coastguard Worker       value->resolution.xres  = *xres++;
815*5e7646d2SAndroid Build Coastguard Worker       value->resolution.yres  = *yres++;
816*5e7646d2SAndroid Build Coastguard Worker       value->resolution.units = units;
817*5e7646d2SAndroid Build Coastguard Worker     }
818*5e7646d2SAndroid Build Coastguard Worker   }
819*5e7646d2SAndroid Build Coastguard Worker 
820*5e7646d2SAndroid Build Coastguard Worker   return (attr);
821*5e7646d2SAndroid Build Coastguard Worker }
822*5e7646d2SAndroid Build Coastguard Worker 
823*5e7646d2SAndroid Build Coastguard Worker 
824*5e7646d2SAndroid Build Coastguard Worker /*
825*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddSeparator()' - Add a group separator to an IPP message.
826*5e7646d2SAndroid Build Coastguard Worker  *
827*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
828*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
829*5e7646d2SAndroid Build Coastguard Worker  */
830*5e7646d2SAndroid Build Coastguard Worker 
831*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddSeparator(ipp_t * ipp)832*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(ipp_t *ipp)		/* I - IPP message */
833*5e7646d2SAndroid Build Coastguard Worker {
834*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddSeparator(ipp=%p)", (void *)ipp));
835*5e7646d2SAndroid Build Coastguard Worker 
836*5e7646d2SAndroid Build Coastguard Worker  /*
837*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
838*5e7646d2SAndroid Build Coastguard Worker   */
839*5e7646d2SAndroid Build Coastguard Worker 
840*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
841*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
842*5e7646d2SAndroid Build Coastguard Worker 
843*5e7646d2SAndroid Build Coastguard Worker  /*
844*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
845*5e7646d2SAndroid Build Coastguard Worker   */
846*5e7646d2SAndroid Build Coastguard Worker 
847*5e7646d2SAndroid Build Coastguard Worker   return (ipp_add_attr(ipp, NULL, IPP_TAG_ZERO, IPP_TAG_ZERO, 0));
848*5e7646d2SAndroid Build Coastguard Worker }
849*5e7646d2SAndroid Build Coastguard Worker 
850*5e7646d2SAndroid Build Coastguard Worker 
851*5e7646d2SAndroid Build Coastguard Worker /*
852*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddString()' - Add a language-encoded string to an IPP message.
853*5e7646d2SAndroid Build Coastguard Worker  *
854*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
855*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
856*5e7646d2SAndroid Build Coastguard Worker  *
857*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
858*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
859*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
860*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
861*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
862*5e7646d2SAndroid Build Coastguard Worker  *
863*5e7646d2SAndroid Build Coastguard Worker  * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
864*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
865*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
866*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
867*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
868*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_URISCHEME@).
869*5e7646d2SAndroid Build Coastguard Worker  *
870*5e7646d2SAndroid Build Coastguard Worker  * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and
871*5e7646d2SAndroid Build Coastguard Worker  * textWithLanguage string values and must be @code NULL@ for all other string values.
872*5e7646d2SAndroid Build Coastguard Worker  */
873*5e7646d2SAndroid Build Coastguard Worker 
874*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddString(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,const char * language,const char * value)875*5e7646d2SAndroid Build Coastguard Worker ippAddString(ipp_t      *ipp,		/* I - IPP message */
876*5e7646d2SAndroid Build Coastguard Worker              ipp_tag_t  group,		/* I - IPP group */
877*5e7646d2SAndroid Build Coastguard Worker 	     ipp_tag_t  value_tag,	/* I - Type of attribute */
878*5e7646d2SAndroid Build Coastguard Worker              const char *name,		/* I - Name of attribute */
879*5e7646d2SAndroid Build Coastguard Worker              const char *language,	/* I - Language code */
880*5e7646d2SAndroid Build Coastguard Worker              const char *value)		/* I - Value */
881*5e7646d2SAndroid Build Coastguard Worker {
882*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		temp_tag;	/* Temporary value tag (masked) */
883*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
884*5e7646d2SAndroid Build Coastguard Worker   char			code[IPP_MAX_LANGUAGE];
885*5e7646d2SAndroid Build Coastguard Worker 					/* Charset/language code buffer */
886*5e7646d2SAndroid Build Coastguard Worker 
887*5e7646d2SAndroid Build Coastguard Worker 
888*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), value_tag=%02x(%s), name=\"%s\", language=\"%s\", value=\"%s\")", (void *)ipp, group, ippTagString(group), value_tag, ippTagString(value_tag), name, language, value));
889*5e7646d2SAndroid Build Coastguard Worker 
890*5e7646d2SAndroid Build Coastguard Worker  /*
891*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
892*5e7646d2SAndroid Build Coastguard Worker   */
893*5e7646d2SAndroid Build Coastguard Worker 
894*5e7646d2SAndroid Build Coastguard Worker   temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_CUPS_MASK);
895*5e7646d2SAndroid Build Coastguard Worker 
896*5e7646d2SAndroid Build Coastguard Worker #if 0
897*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
898*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
899*5e7646d2SAndroid Build Coastguard Worker       (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG &&
900*5e7646d2SAndroid Build Coastguard Worker        temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE)
901*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
902*5e7646d2SAndroid Build Coastguard Worker 
903*5e7646d2SAndroid Build Coastguard Worker   if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG)
904*5e7646d2SAndroid Build Coastguard Worker           != (language != NULL))
905*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
906*5e7646d2SAndroid Build Coastguard Worker #else
907*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
908*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
909*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
910*5e7646d2SAndroid Build Coastguard Worker #endif /* 0 */
911*5e7646d2SAndroid Build Coastguard Worker 
912*5e7646d2SAndroid Build Coastguard Worker  /*
913*5e7646d2SAndroid Build Coastguard Worker   * See if we need to map charset, language, or locale values...
914*5e7646d2SAndroid Build Coastguard Worker   */
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker   if (language && ((int)value_tag & IPP_TAG_CUPS_CONST) &&
917*5e7646d2SAndroid Build Coastguard Worker       strcmp(language, ipp_lang_code(language, code, sizeof(code))))
918*5e7646d2SAndroid Build Coastguard Worker     value_tag = temp_tag;		/* Don't do a fast copy */
919*5e7646d2SAndroid Build Coastguard Worker   else if (value && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_CUPS_CONST) &&
920*5e7646d2SAndroid Build Coastguard Worker            strcmp(value, ipp_get_code(value, code, sizeof(code))))
921*5e7646d2SAndroid Build Coastguard Worker     value_tag = temp_tag;		/* Don't do a fast copy */
922*5e7646d2SAndroid Build Coastguard Worker   else if (value && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_CUPS_CONST) &&
923*5e7646d2SAndroid Build Coastguard Worker            strcmp(value, ipp_lang_code(value, code, sizeof(code))))
924*5e7646d2SAndroid Build Coastguard Worker     value_tag = temp_tag;		/* Don't do a fast copy */
925*5e7646d2SAndroid Build Coastguard Worker 
926*5e7646d2SAndroid Build Coastguard Worker  /*
927*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
928*5e7646d2SAndroid Build Coastguard Worker   */
929*5e7646d2SAndroid Build Coastguard Worker 
930*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL)
931*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
932*5e7646d2SAndroid Build Coastguard Worker 
933*5e7646d2SAndroid Build Coastguard Worker  /*
934*5e7646d2SAndroid Build Coastguard Worker   * Initialize the attribute data...
935*5e7646d2SAndroid Build Coastguard Worker   */
936*5e7646d2SAndroid Build Coastguard Worker 
937*5e7646d2SAndroid Build Coastguard Worker   if ((int)value_tag & IPP_TAG_CUPS_CONST)
938*5e7646d2SAndroid Build Coastguard Worker   {
939*5e7646d2SAndroid Build Coastguard Worker     attr->values[0].string.language = (char *)language;
940*5e7646d2SAndroid Build Coastguard Worker     attr->values[0].string.text     = (char *)value;
941*5e7646d2SAndroid Build Coastguard Worker   }
942*5e7646d2SAndroid Build Coastguard Worker   else
943*5e7646d2SAndroid Build Coastguard Worker   {
944*5e7646d2SAndroid Build Coastguard Worker     if (language)
945*5e7646d2SAndroid Build Coastguard Worker       attr->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language, code,
946*5e7646d2SAndroid Build Coastguard Worker 						      sizeof(code)));
947*5e7646d2SAndroid Build Coastguard Worker 
948*5e7646d2SAndroid Build Coastguard Worker     if (value)
949*5e7646d2SAndroid Build Coastguard Worker     {
950*5e7646d2SAndroid Build Coastguard Worker       if (value_tag == IPP_TAG_CHARSET)
951*5e7646d2SAndroid Build Coastguard Worker 	attr->values[0].string.text = _cupsStrAlloc(ipp_get_code(value, code,
952*5e7646d2SAndroid Build Coastguard Worker 								 sizeof(code)));
953*5e7646d2SAndroid Build Coastguard Worker       else if (value_tag == IPP_TAG_LANGUAGE)
954*5e7646d2SAndroid Build Coastguard Worker 	attr->values[0].string.text = _cupsStrAlloc(ipp_lang_code(value, code,
955*5e7646d2SAndroid Build Coastguard Worker 								  sizeof(code)));
956*5e7646d2SAndroid Build Coastguard Worker       else
957*5e7646d2SAndroid Build Coastguard Worker 	attr->values[0].string.text = _cupsStrAlloc(value);
958*5e7646d2SAndroid Build Coastguard Worker     }
959*5e7646d2SAndroid Build Coastguard Worker   }
960*5e7646d2SAndroid Build Coastguard Worker 
961*5e7646d2SAndroid Build Coastguard Worker   return (attr);
962*5e7646d2SAndroid Build Coastguard Worker }
963*5e7646d2SAndroid Build Coastguard Worker 
964*5e7646d2SAndroid Build Coastguard Worker 
965*5e7646d2SAndroid Build Coastguard Worker /*
966*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddStringf()' - Add a formatted string to an IPP message.
967*5e7646d2SAndroid Build Coastguard Worker  *
968*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
969*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
970*5e7646d2SAndroid Build Coastguard Worker  *
971*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
972*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document
973*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_DOCUMENT@), event notification
974*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_EVENT_NOTIFICATION@), operation (@code IPP_TAG_OPERATION@),
975*5e7646d2SAndroid Build Coastguard Worker  * printer (@code IPP_TAG_PRINTER@), subscription (@code IPP_TAG_SUBSCRIPTION@),
976*5e7646d2SAndroid Build Coastguard Worker  * or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
977*5e7646d2SAndroid Build Coastguard Worker  *
978*5e7646d2SAndroid Build Coastguard Worker  * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
979*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
980*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
981*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
982*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
983*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_URISCHEME@).
984*5e7646d2SAndroid Build Coastguard Worker  *
985*5e7646d2SAndroid Build Coastguard Worker  * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage
986*5e7646d2SAndroid Build Coastguard Worker  * and textWithLanguage string values and must be @code NULL@ for all other
987*5e7646d2SAndroid Build Coastguard Worker  * string values.
988*5e7646d2SAndroid Build Coastguard Worker  *
989*5e7646d2SAndroid Build Coastguard Worker  * The @code format@ parameter uses formatting characters compatible with the
990*5e7646d2SAndroid Build Coastguard Worker  * printf family of standard functions.  Additional arguments follow it as
991*5e7646d2SAndroid Build Coastguard Worker  * needed.  The formatted string is truncated as needed to the maximum length of
992*5e7646d2SAndroid Build Coastguard Worker  * the corresponding value type.
993*5e7646d2SAndroid Build Coastguard Worker  *
994*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
995*5e7646d2SAndroid Build Coastguard Worker  */
996*5e7646d2SAndroid Build Coastguard Worker 
997*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddStringf(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,const char * language,const char * format,...)998*5e7646d2SAndroid Build Coastguard Worker ippAddStringf(ipp_t      *ipp,		/* I - IPP message */
999*5e7646d2SAndroid Build Coastguard Worker               ipp_tag_t  group,		/* I - IPP group */
1000*5e7646d2SAndroid Build Coastguard Worker 	      ipp_tag_t  value_tag,	/* I - Type of attribute */
1001*5e7646d2SAndroid Build Coastguard Worker 	      const char *name,		/* I - Name of attribute */
1002*5e7646d2SAndroid Build Coastguard Worker 	      const char *language,	/* I - Language code (@code NULL@ for default) */
1003*5e7646d2SAndroid Build Coastguard Worker 	      const char *format,	/* I - Printf-style format string */
1004*5e7646d2SAndroid Build Coastguard Worker 	      ...)			/* I - Additional arguments as needed */
1005*5e7646d2SAndroid Build Coastguard Worker {
1006*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
1007*5e7646d2SAndroid Build Coastguard Worker   va_list		ap;		/* Argument pointer */
1008*5e7646d2SAndroid Build Coastguard Worker 
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, format);
1011*5e7646d2SAndroid Build Coastguard Worker   attr = ippAddStringfv(ipp, group, value_tag, name, language, format, ap);
1012*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
1013*5e7646d2SAndroid Build Coastguard Worker 
1014*5e7646d2SAndroid Build Coastguard Worker   return (attr);
1015*5e7646d2SAndroid Build Coastguard Worker }
1016*5e7646d2SAndroid Build Coastguard Worker 
1017*5e7646d2SAndroid Build Coastguard Worker 
1018*5e7646d2SAndroid Build Coastguard Worker /*
1019*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddStringfv()' - Add a formatted string to an IPP message.
1020*5e7646d2SAndroid Build Coastguard Worker  *
1021*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
1022*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
1023*5e7646d2SAndroid Build Coastguard Worker  *
1024*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
1025*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document
1026*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_DOCUMENT@), event notification
1027*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_EVENT_NOTIFICATION@), operation (@code IPP_TAG_OPERATION@),
1028*5e7646d2SAndroid Build Coastguard Worker  * printer (@code IPP_TAG_PRINTER@), subscription (@code IPP_TAG_SUBSCRIPTION@),
1029*5e7646d2SAndroid Build Coastguard Worker  * or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
1030*5e7646d2SAndroid Build Coastguard Worker  *
1031*5e7646d2SAndroid Build Coastguard Worker  * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
1032*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
1033*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
1034*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
1035*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
1036*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_URISCHEME@).
1037*5e7646d2SAndroid Build Coastguard Worker  *
1038*5e7646d2SAndroid Build Coastguard Worker  * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage
1039*5e7646d2SAndroid Build Coastguard Worker  * and textWithLanguage string values and must be @code NULL@ for all other
1040*5e7646d2SAndroid Build Coastguard Worker  * string values.
1041*5e7646d2SAndroid Build Coastguard Worker  *
1042*5e7646d2SAndroid Build Coastguard Worker  * The @code format@ parameter uses formatting characters compatible with the
1043*5e7646d2SAndroid Build Coastguard Worker  * printf family of standard functions.  Additional arguments are passed in the
1044*5e7646d2SAndroid Build Coastguard Worker  * stdarg pointer @code ap@.  The formatted string is truncated as needed to the
1045*5e7646d2SAndroid Build Coastguard Worker  * maximum length of the corresponding value type.
1046*5e7646d2SAndroid Build Coastguard Worker  *
1047*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1048*5e7646d2SAndroid Build Coastguard Worker  */
1049*5e7646d2SAndroid Build Coastguard Worker 
1050*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddStringfv(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,const char * language,const char * format,va_list ap)1051*5e7646d2SAndroid Build Coastguard Worker ippAddStringfv(ipp_t      *ipp,		/* I - IPP message */
1052*5e7646d2SAndroid Build Coastguard Worker                ipp_tag_t  group,	/* I - IPP group */
1053*5e7646d2SAndroid Build Coastguard Worker 	       ipp_tag_t  value_tag,	/* I - Type of attribute */
1054*5e7646d2SAndroid Build Coastguard Worker 	       const char *name,	/* I - Name of attribute */
1055*5e7646d2SAndroid Build Coastguard Worker 	       const char *language,	/* I - Language code (@code NULL@ for default) */
1056*5e7646d2SAndroid Build Coastguard Worker 	       const char *format,	/* I - Printf-style format string */
1057*5e7646d2SAndroid Build Coastguard Worker 	       va_list    ap)		/* I - Additional arguments */
1058*5e7646d2SAndroid Build Coastguard Worker {
1059*5e7646d2SAndroid Build Coastguard Worker   char		buffer[IPP_MAX_TEXT + 4];
1060*5e7646d2SAndroid Build Coastguard Worker 					/* Formatted text string */
1061*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes,			/* Length of formatted value */
1062*5e7646d2SAndroid Build Coastguard Worker 		max_bytes;		/* Maximum number of bytes for value */
1063*5e7646d2SAndroid Build Coastguard Worker 
1064*5e7646d2SAndroid Build Coastguard Worker 
1065*5e7646d2SAndroid Build Coastguard Worker  /*
1066*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1067*5e7646d2SAndroid Build Coastguard Worker   */
1068*5e7646d2SAndroid Build Coastguard Worker 
1069*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
1070*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
1071*5e7646d2SAndroid Build Coastguard Worker       (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG &&
1072*5e7646d2SAndroid Build Coastguard Worker        value_tag != IPP_TAG_NAMELANG) || value_tag > IPP_TAG_MIMETYPE ||
1073*5e7646d2SAndroid Build Coastguard Worker       !format)
1074*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1075*5e7646d2SAndroid Build Coastguard Worker 
1076*5e7646d2SAndroid Build Coastguard Worker   if ((value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_NAMELANG)
1077*5e7646d2SAndroid Build Coastguard Worker           != (language != NULL))
1078*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1079*5e7646d2SAndroid Build Coastguard Worker 
1080*5e7646d2SAndroid Build Coastguard Worker  /*
1081*5e7646d2SAndroid Build Coastguard Worker   * Format the string...
1082*5e7646d2SAndroid Build Coastguard Worker   */
1083*5e7646d2SAndroid Build Coastguard Worker 
1084*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(format, "%s"))
1085*5e7646d2SAndroid Build Coastguard Worker   {
1086*5e7646d2SAndroid Build Coastguard Worker    /*
1087*5e7646d2SAndroid Build Coastguard Worker     * Optimize the simple case...
1088*5e7646d2SAndroid Build Coastguard Worker     */
1089*5e7646d2SAndroid Build Coastguard Worker 
1090*5e7646d2SAndroid Build Coastguard Worker     const char *s = va_arg(ap, char *);
1091*5e7646d2SAndroid Build Coastguard Worker 
1092*5e7646d2SAndroid Build Coastguard Worker     if (!s)
1093*5e7646d2SAndroid Build Coastguard Worker       s = "(null)";
1094*5e7646d2SAndroid Build Coastguard Worker 
1095*5e7646d2SAndroid Build Coastguard Worker     bytes = (ssize_t)strlen(s);
1096*5e7646d2SAndroid Build Coastguard Worker     strlcpy(buffer, s, sizeof(buffer));
1097*5e7646d2SAndroid Build Coastguard Worker   }
1098*5e7646d2SAndroid Build Coastguard Worker   else
1099*5e7646d2SAndroid Build Coastguard Worker   {
1100*5e7646d2SAndroid Build Coastguard Worker    /*
1101*5e7646d2SAndroid Build Coastguard Worker     * Do a full formatting of the message...
1102*5e7646d2SAndroid Build Coastguard Worker     */
1103*5e7646d2SAndroid Build Coastguard Worker 
1104*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = vsnprintf(buffer, sizeof(buffer), format, ap)) < 0)
1105*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
1106*5e7646d2SAndroid Build Coastguard Worker   }
1107*5e7646d2SAndroid Build Coastguard Worker 
1108*5e7646d2SAndroid Build Coastguard Worker  /*
1109*5e7646d2SAndroid Build Coastguard Worker   * Limit the length of the string...
1110*5e7646d2SAndroid Build Coastguard Worker   */
1111*5e7646d2SAndroid Build Coastguard Worker 
1112*5e7646d2SAndroid Build Coastguard Worker   switch (value_tag)
1113*5e7646d2SAndroid Build Coastguard Worker   {
1114*5e7646d2SAndroid Build Coastguard Worker     default :
1115*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
1116*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
1117*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_TEXT;
1118*5e7646d2SAndroid Build Coastguard Worker         break;
1119*5e7646d2SAndroid Build Coastguard Worker 
1120*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
1121*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
1122*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_NAME;
1123*5e7646d2SAndroid Build Coastguard Worker         break;
1124*5e7646d2SAndroid Build Coastguard Worker 
1125*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
1126*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_CHARSET;
1127*5e7646d2SAndroid Build Coastguard Worker         break;
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
1130*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_KEYWORD;
1131*5e7646d2SAndroid Build Coastguard Worker         break;
1132*5e7646d2SAndroid Build Coastguard Worker 
1133*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
1134*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_LANGUAGE;
1135*5e7646d2SAndroid Build Coastguard Worker         break;
1136*5e7646d2SAndroid Build Coastguard Worker 
1137*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
1138*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_MIMETYPE;
1139*5e7646d2SAndroid Build Coastguard Worker         break;
1140*5e7646d2SAndroid Build Coastguard Worker 
1141*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
1142*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_URI;
1143*5e7646d2SAndroid Build Coastguard Worker         break;
1144*5e7646d2SAndroid Build Coastguard Worker 
1145*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
1146*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_URISCHEME;
1147*5e7646d2SAndroid Build Coastguard Worker         break;
1148*5e7646d2SAndroid Build Coastguard Worker   }
1149*5e7646d2SAndroid Build Coastguard Worker 
1150*5e7646d2SAndroid Build Coastguard Worker   if (bytes >= max_bytes)
1151*5e7646d2SAndroid Build Coastguard Worker   {
1152*5e7646d2SAndroid Build Coastguard Worker     char	*bufmax,		/* Buffer at max_bytes */
1153*5e7646d2SAndroid Build Coastguard Worker 		*bufptr;		/* Pointer into buffer */
1154*5e7646d2SAndroid Build Coastguard Worker 
1155*5e7646d2SAndroid Build Coastguard Worker     bufptr = buffer + strlen(buffer) - 1;
1156*5e7646d2SAndroid Build Coastguard Worker     bufmax = buffer + max_bytes - 1;
1157*5e7646d2SAndroid Build Coastguard Worker 
1158*5e7646d2SAndroid Build Coastguard Worker     while (bufptr > bufmax)
1159*5e7646d2SAndroid Build Coastguard Worker     {
1160*5e7646d2SAndroid Build Coastguard Worker       if (*bufptr & 0x80)
1161*5e7646d2SAndroid Build Coastguard Worker       {
1162*5e7646d2SAndroid Build Coastguard Worker         while ((*bufptr & 0xc0) == 0x80 && bufptr > buffer)
1163*5e7646d2SAndroid Build Coastguard Worker           bufptr --;
1164*5e7646d2SAndroid Build Coastguard Worker       }
1165*5e7646d2SAndroid Build Coastguard Worker 
1166*5e7646d2SAndroid Build Coastguard Worker       bufptr --;
1167*5e7646d2SAndroid Build Coastguard Worker     }
1168*5e7646d2SAndroid Build Coastguard Worker 
1169*5e7646d2SAndroid Build Coastguard Worker     *bufptr = '\0';
1170*5e7646d2SAndroid Build Coastguard Worker   }
1171*5e7646d2SAndroid Build Coastguard Worker 
1172*5e7646d2SAndroid Build Coastguard Worker  /*
1173*5e7646d2SAndroid Build Coastguard Worker   * Add the formatted string and return...
1174*5e7646d2SAndroid Build Coastguard Worker   */
1175*5e7646d2SAndroid Build Coastguard Worker 
1176*5e7646d2SAndroid Build Coastguard Worker   return (ippAddString(ipp, group, value_tag, name, language, buffer));
1177*5e7646d2SAndroid Build Coastguard Worker }
1178*5e7646d2SAndroid Build Coastguard Worker 
1179*5e7646d2SAndroid Build Coastguard Worker 
1180*5e7646d2SAndroid Build Coastguard Worker /*
1181*5e7646d2SAndroid Build Coastguard Worker  * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
1182*5e7646d2SAndroid Build Coastguard Worker  *
1183*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
1184*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
1185*5e7646d2SAndroid Build Coastguard Worker  *
1186*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
1187*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
1188*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
1189*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
1190*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
1191*5e7646d2SAndroid Build Coastguard Worker  *
1192*5e7646d2SAndroid Build Coastguard Worker  * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
1193*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
1194*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
1195*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
1196*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
1197*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_URISCHEME@).
1198*5e7646d2SAndroid Build Coastguard Worker  *
1199*5e7646d2SAndroid Build Coastguard Worker  * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and
1200*5e7646d2SAndroid Build Coastguard Worker  * textWithLanguage string values and must be @code NULL@ for all other string values.
1201*5e7646d2SAndroid Build Coastguard Worker  */
1202*5e7646d2SAndroid Build Coastguard Worker 
1203*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippAddStrings(ipp_t * ipp,ipp_tag_t group,ipp_tag_t value_tag,const char * name,int num_values,const char * language,const char * const * values)1204*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(
1205*5e7646d2SAndroid Build Coastguard Worker     ipp_t              *ipp,		/* I - IPP message */
1206*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t          group,		/* I - IPP group */
1207*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t          value_tag,	/* I - Type of attribute */
1208*5e7646d2SAndroid Build Coastguard Worker     const char         *name,		/* I - Name of attribute */
1209*5e7646d2SAndroid Build Coastguard Worker     int                num_values,	/* I - Number of values */
1210*5e7646d2SAndroid Build Coastguard Worker     const char         *language,	/* I - Language code (@code NULL@ for default) */
1211*5e7646d2SAndroid Build Coastguard Worker     const char * const *values)		/* I - Values */
1212*5e7646d2SAndroid Build Coastguard Worker {
1213*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
1214*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		temp_tag;	/* Temporary value tag (masked) */
1215*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
1216*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
1217*5e7646d2SAndroid Build Coastguard Worker   char			code[32];	/* Language/charset value buffer */
1218*5e7646d2SAndroid Build Coastguard Worker 
1219*5e7646d2SAndroid Build Coastguard Worker 
1220*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), value_tag=%02x(%s), name=\"%s\", num_values=%d, language=\"%s\", values=%p)", (void *)ipp, group, ippTagString(group), value_tag, ippTagString(value_tag), name, num_values, language, (void *)values));
1221*5e7646d2SAndroid Build Coastguard Worker 
1222*5e7646d2SAndroid Build Coastguard Worker  /*
1223*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1224*5e7646d2SAndroid Build Coastguard Worker   */
1225*5e7646d2SAndroid Build Coastguard Worker 
1226*5e7646d2SAndroid Build Coastguard Worker   temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_CUPS_MASK);
1227*5e7646d2SAndroid Build Coastguard Worker 
1228*5e7646d2SAndroid Build Coastguard Worker #if 0
1229*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
1230*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
1231*5e7646d2SAndroid Build Coastguard Worker       (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG &&
1232*5e7646d2SAndroid Build Coastguard Worker        temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE ||
1233*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
1234*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1235*5e7646d2SAndroid Build Coastguard Worker 
1236*5e7646d2SAndroid Build Coastguard Worker   if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG)
1237*5e7646d2SAndroid Build Coastguard Worker           != (language != NULL))
1238*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1239*5e7646d2SAndroid Build Coastguard Worker #else
1240*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name || group < IPP_TAG_ZERO ||
1241*5e7646d2SAndroid Build Coastguard Worker       group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
1242*5e7646d2SAndroid Build Coastguard Worker       num_values < 1)
1243*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1244*5e7646d2SAndroid Build Coastguard Worker #endif /* 0 */
1245*5e7646d2SAndroid Build Coastguard Worker 
1246*5e7646d2SAndroid Build Coastguard Worker  /*
1247*5e7646d2SAndroid Build Coastguard Worker   * See if we need to map charset, language, or locale values...
1248*5e7646d2SAndroid Build Coastguard Worker   */
1249*5e7646d2SAndroid Build Coastguard Worker 
1250*5e7646d2SAndroid Build Coastguard Worker   if (language && ((int)value_tag & IPP_TAG_CUPS_CONST) &&
1251*5e7646d2SAndroid Build Coastguard Worker       strcmp(language, ipp_lang_code(language, code, sizeof(code))))
1252*5e7646d2SAndroid Build Coastguard Worker     value_tag = temp_tag;		/* Don't do a fast copy */
1253*5e7646d2SAndroid Build Coastguard Worker   else if (values && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_CUPS_CONST))
1254*5e7646d2SAndroid Build Coastguard Worker   {
1255*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_values; i ++)
1256*5e7646d2SAndroid Build Coastguard Worker       if (strcmp(values[i], ipp_get_code(values[i], code, sizeof(code))))
1257*5e7646d2SAndroid Build Coastguard Worker       {
1258*5e7646d2SAndroid Build Coastguard Worker 	value_tag = temp_tag;		/* Don't do a fast copy */
1259*5e7646d2SAndroid Build Coastguard Worker         break;
1260*5e7646d2SAndroid Build Coastguard Worker       }
1261*5e7646d2SAndroid Build Coastguard Worker   }
1262*5e7646d2SAndroid Build Coastguard Worker   else if (values && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_CUPS_CONST))
1263*5e7646d2SAndroid Build Coastguard Worker   {
1264*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_values; i ++)
1265*5e7646d2SAndroid Build Coastguard Worker       if (strcmp(values[i], ipp_lang_code(values[i], code, sizeof(code))))
1266*5e7646d2SAndroid Build Coastguard Worker       {
1267*5e7646d2SAndroid Build Coastguard Worker 	value_tag = temp_tag;		/* Don't do a fast copy */
1268*5e7646d2SAndroid Build Coastguard Worker         break;
1269*5e7646d2SAndroid Build Coastguard Worker       }
1270*5e7646d2SAndroid Build Coastguard Worker   }
1271*5e7646d2SAndroid Build Coastguard Worker 
1272*5e7646d2SAndroid Build Coastguard Worker  /*
1273*5e7646d2SAndroid Build Coastguard Worker   * Create the attribute...
1274*5e7646d2SAndroid Build Coastguard Worker   */
1275*5e7646d2SAndroid Build Coastguard Worker 
1276*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL)
1277*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1278*5e7646d2SAndroid Build Coastguard Worker 
1279*5e7646d2SAndroid Build Coastguard Worker  /*
1280*5e7646d2SAndroid Build Coastguard Worker   * Initialize the attribute data...
1281*5e7646d2SAndroid Build Coastguard Worker   */
1282*5e7646d2SAndroid Build Coastguard Worker 
1283*5e7646d2SAndroid Build Coastguard Worker   for (i = num_values, value = attr->values;
1284*5e7646d2SAndroid Build Coastguard Worker        i > 0;
1285*5e7646d2SAndroid Build Coastguard Worker        i --, value ++)
1286*5e7646d2SAndroid Build Coastguard Worker   {
1287*5e7646d2SAndroid Build Coastguard Worker     if (language)
1288*5e7646d2SAndroid Build Coastguard Worker     {
1289*5e7646d2SAndroid Build Coastguard Worker       if (value == attr->values)
1290*5e7646d2SAndroid Build Coastguard Worker       {
1291*5e7646d2SAndroid Build Coastguard Worker         if ((int)value_tag & IPP_TAG_CUPS_CONST)
1292*5e7646d2SAndroid Build Coastguard Worker           value->string.language = (char *)language;
1293*5e7646d2SAndroid Build Coastguard Worker         else
1294*5e7646d2SAndroid Build Coastguard Worker           value->string.language = _cupsStrAlloc(ipp_lang_code(language, code,
1295*5e7646d2SAndroid Build Coastguard Worker                                                                sizeof(code)));
1296*5e7646d2SAndroid Build Coastguard Worker       }
1297*5e7646d2SAndroid Build Coastguard Worker       else
1298*5e7646d2SAndroid Build Coastguard Worker 	value->string.language = attr->values[0].string.language;
1299*5e7646d2SAndroid Build Coastguard Worker     }
1300*5e7646d2SAndroid Build Coastguard Worker 
1301*5e7646d2SAndroid Build Coastguard Worker     if (values)
1302*5e7646d2SAndroid Build Coastguard Worker     {
1303*5e7646d2SAndroid Build Coastguard Worker       if ((int)value_tag & IPP_TAG_CUPS_CONST)
1304*5e7646d2SAndroid Build Coastguard Worker         value->string.text = (char *)*values++;
1305*5e7646d2SAndroid Build Coastguard Worker       else if (value_tag == IPP_TAG_CHARSET)
1306*5e7646d2SAndroid Build Coastguard Worker 	value->string.text = _cupsStrAlloc(ipp_get_code(*values++, code, sizeof(code)));
1307*5e7646d2SAndroid Build Coastguard Worker       else if (value_tag == IPP_TAG_LANGUAGE)
1308*5e7646d2SAndroid Build Coastguard Worker 	value->string.text = _cupsStrAlloc(ipp_lang_code(*values++, code, sizeof(code)));
1309*5e7646d2SAndroid Build Coastguard Worker       else
1310*5e7646d2SAndroid Build Coastguard Worker 	value->string.text = _cupsStrAlloc(*values++);
1311*5e7646d2SAndroid Build Coastguard Worker     }
1312*5e7646d2SAndroid Build Coastguard Worker   }
1313*5e7646d2SAndroid Build Coastguard Worker 
1314*5e7646d2SAndroid Build Coastguard Worker   return (attr);
1315*5e7646d2SAndroid Build Coastguard Worker }
1316*5e7646d2SAndroid Build Coastguard Worker 
1317*5e7646d2SAndroid Build Coastguard Worker 
1318*5e7646d2SAndroid Build Coastguard Worker /*
1319*5e7646d2SAndroid Build Coastguard Worker  * 'ippContainsInteger()' - Determine whether an attribute contains the
1320*5e7646d2SAndroid Build Coastguard Worker  *                          specified value or is within the list of ranges.
1321*5e7646d2SAndroid Build Coastguard Worker  *
1322*5e7646d2SAndroid Build Coastguard Worker  * Returns non-zero when the attribute contains either a matching integer or
1323*5e7646d2SAndroid Build Coastguard Worker  * enum value, or the value falls within one of the rangeOfInteger values for
1324*5e7646d2SAndroid Build Coastguard Worker  * the attribute.
1325*5e7646d2SAndroid Build Coastguard Worker  *
1326*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1327*5e7646d2SAndroid Build Coastguard Worker  */
1328*5e7646d2SAndroid Build Coastguard Worker 
1329*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on a match, 0 on no match */
ippContainsInteger(ipp_attribute_t * attr,int value)1330*5e7646d2SAndroid Build Coastguard Worker ippContainsInteger(
1331*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - Attribute */
1332*5e7646d2SAndroid Build Coastguard Worker     int             value)		/* I - Integer/enum value */
1333*5e7646d2SAndroid Build Coastguard Worker {
1334*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
1335*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*avalue;		/* Current attribute value */
1336*5e7646d2SAndroid Build Coastguard Worker 
1337*5e7646d2SAndroid Build Coastguard Worker 
1338*5e7646d2SAndroid Build Coastguard Worker  /*
1339*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1340*5e7646d2SAndroid Build Coastguard Worker   */
1341*5e7646d2SAndroid Build Coastguard Worker 
1342*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
1343*5e7646d2SAndroid Build Coastguard Worker     return (0);
1344*5e7646d2SAndroid Build Coastguard Worker 
1345*5e7646d2SAndroid Build Coastguard Worker   if (attr->value_tag != IPP_TAG_INTEGER && attr->value_tag != IPP_TAG_ENUM &&
1346*5e7646d2SAndroid Build Coastguard Worker       attr->value_tag != IPP_TAG_RANGE)
1347*5e7646d2SAndroid Build Coastguard Worker     return (0);
1348*5e7646d2SAndroid Build Coastguard Worker 
1349*5e7646d2SAndroid Build Coastguard Worker  /*
1350*5e7646d2SAndroid Build Coastguard Worker   * Compare...
1351*5e7646d2SAndroid Build Coastguard Worker   */
1352*5e7646d2SAndroid Build Coastguard Worker 
1353*5e7646d2SAndroid Build Coastguard Worker   if (attr->value_tag == IPP_TAG_RANGE)
1354*5e7646d2SAndroid Build Coastguard Worker   {
1355*5e7646d2SAndroid Build Coastguard Worker     for (i = attr->num_values, avalue = attr->values; i > 0; i --, avalue ++)
1356*5e7646d2SAndroid Build Coastguard Worker       if (value >= avalue->range.lower && value <= avalue->range.upper)
1357*5e7646d2SAndroid Build Coastguard Worker         return (1);
1358*5e7646d2SAndroid Build Coastguard Worker   }
1359*5e7646d2SAndroid Build Coastguard Worker   else
1360*5e7646d2SAndroid Build Coastguard Worker   {
1361*5e7646d2SAndroid Build Coastguard Worker     for (i = attr->num_values, avalue = attr->values; i > 0; i --, avalue ++)
1362*5e7646d2SAndroid Build Coastguard Worker       if (value == avalue->integer)
1363*5e7646d2SAndroid Build Coastguard Worker         return (1);
1364*5e7646d2SAndroid Build Coastguard Worker   }
1365*5e7646d2SAndroid Build Coastguard Worker 
1366*5e7646d2SAndroid Build Coastguard Worker   return (0);
1367*5e7646d2SAndroid Build Coastguard Worker }
1368*5e7646d2SAndroid Build Coastguard Worker 
1369*5e7646d2SAndroid Build Coastguard Worker 
1370*5e7646d2SAndroid Build Coastguard Worker /*
1371*5e7646d2SAndroid Build Coastguard Worker  * 'ippContainsString()' - Determine whether an attribute contains the
1372*5e7646d2SAndroid Build Coastguard Worker  *                         specified string value.
1373*5e7646d2SAndroid Build Coastguard Worker  *
1374*5e7646d2SAndroid Build Coastguard Worker  * Returns non-zero when the attribute contains a matching charset, keyword,
1375*5e7646d2SAndroid Build Coastguard Worker  * naturalLanguage, mimeMediaType, name, text, uri, or uriScheme value.
1376*5e7646d2SAndroid Build Coastguard Worker  *
1377*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1378*5e7646d2SAndroid Build Coastguard Worker  */
1379*5e7646d2SAndroid Build Coastguard Worker 
1380*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on a match, 0 on no match */
ippContainsString(ipp_attribute_t * attr,const char * value)1381*5e7646d2SAndroid Build Coastguard Worker ippContainsString(
1382*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - Attribute */
1383*5e7646d2SAndroid Build Coastguard Worker     const char      *value)		/* I - String value */
1384*5e7646d2SAndroid Build Coastguard Worker {
1385*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
1386*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*avalue;		/* Current attribute value */
1387*5e7646d2SAndroid Build Coastguard Worker 
1388*5e7646d2SAndroid Build Coastguard Worker 
1389*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippContainsString(attr=%p, value=\"%s\")", (void *)attr, value));
1390*5e7646d2SAndroid Build Coastguard Worker 
1391*5e7646d2SAndroid Build Coastguard Worker  /*
1392*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1393*5e7646d2SAndroid Build Coastguard Worker   */
1394*5e7646d2SAndroid Build Coastguard Worker 
1395*5e7646d2SAndroid Build Coastguard Worker   if (!attr || !value)
1396*5e7646d2SAndroid Build Coastguard Worker   {
1397*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1ippContainsString: Returning 0 (bad input)");
1398*5e7646d2SAndroid Build Coastguard Worker     return (0);
1399*5e7646d2SAndroid Build Coastguard Worker   }
1400*5e7646d2SAndroid Build Coastguard Worker 
1401*5e7646d2SAndroid Build Coastguard Worker  /*
1402*5e7646d2SAndroid Build Coastguard Worker   * Compare...
1403*5e7646d2SAndroid Build Coastguard Worker   */
1404*5e7646d2SAndroid Build Coastguard Worker 
1405*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1ippContainsString: attr %s, %s with %d values.",
1406*5e7646d2SAndroid Build Coastguard Worker 		attr->name, ippTagString(attr->value_tag),
1407*5e7646d2SAndroid Build Coastguard Worker 		attr->num_values));
1408*5e7646d2SAndroid Build Coastguard Worker 
1409*5e7646d2SAndroid Build Coastguard Worker   switch (attr->value_tag & IPP_TAG_CUPS_MASK)
1410*5e7646d2SAndroid Build Coastguard Worker   {
1411*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
1412*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
1413*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
1414*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
1415*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
1416*5e7646d2SAndroid Build Coastguard Worker 	for (i = attr->num_values, avalue = attr->values;
1417*5e7646d2SAndroid Build Coastguard Worker 	     i > 0;
1418*5e7646d2SAndroid Build Coastguard Worker 	     i --, avalue ++)
1419*5e7646d2SAndroid Build Coastguard Worker 	{
1420*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1ippContainsString: value[%d]=\"%s\"",
1421*5e7646d2SAndroid Build Coastguard Worker 	                attr->num_values - i, avalue->string.text));
1422*5e7646d2SAndroid Build Coastguard Worker 
1423*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(value, avalue->string.text))
1424*5e7646d2SAndroid Build Coastguard Worker 	  {
1425*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippContainsString: Returning 1 (match)");
1426*5e7646d2SAndroid Build Coastguard Worker 	    return (1);
1427*5e7646d2SAndroid Build Coastguard Worker 	  }
1428*5e7646d2SAndroid Build Coastguard Worker         }
1429*5e7646d2SAndroid Build Coastguard Worker 
1430*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
1431*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
1432*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
1433*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
1434*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
1435*5e7646d2SAndroid Build Coastguard Worker 	for (i = attr->num_values, avalue = attr->values;
1436*5e7646d2SAndroid Build Coastguard Worker 	     i > 0;
1437*5e7646d2SAndroid Build Coastguard Worker 	     i --, avalue ++)
1438*5e7646d2SAndroid Build Coastguard Worker 	{
1439*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1ippContainsString: value[%d]=\"%s\"",
1440*5e7646d2SAndroid Build Coastguard Worker 	                attr->num_values - i, avalue->string.text));
1441*5e7646d2SAndroid Build Coastguard Worker 
1442*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strcasecmp(value, avalue->string.text))
1443*5e7646d2SAndroid Build Coastguard Worker 	  {
1444*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippContainsString: Returning 1 (match)");
1445*5e7646d2SAndroid Build Coastguard Worker 	    return (1);
1446*5e7646d2SAndroid Build Coastguard Worker 	  }
1447*5e7646d2SAndroid Build Coastguard Worker         }
1448*5e7646d2SAndroid Build Coastguard Worker 
1449*5e7646d2SAndroid Build Coastguard Worker     default :
1450*5e7646d2SAndroid Build Coastguard Worker         break;
1451*5e7646d2SAndroid Build Coastguard Worker   }
1452*5e7646d2SAndroid Build Coastguard Worker 
1453*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("1ippContainsString: Returning 0 (no match)");
1454*5e7646d2SAndroid Build Coastguard Worker 
1455*5e7646d2SAndroid Build Coastguard Worker   return (0);
1456*5e7646d2SAndroid Build Coastguard Worker }
1457*5e7646d2SAndroid Build Coastguard Worker 
1458*5e7646d2SAndroid Build Coastguard Worker 
1459*5e7646d2SAndroid Build Coastguard Worker /*
1460*5e7646d2SAndroid Build Coastguard Worker  * 'ippCopyAttribute()' - Copy an attribute.
1461*5e7646d2SAndroid Build Coastguard Worker  *
1462*5e7646d2SAndroid Build Coastguard Worker  * The specified attribute, @code attr@, is copied to the destination IPP message.
1463*5e7646d2SAndroid Build Coastguard Worker  * When @code quickcopy@ is non-zero, a "shallow" reference copy of the attribute is
1464*5e7646d2SAndroid Build Coastguard Worker  * created - this should only be done as long as the original source IPP message will
1465*5e7646d2SAndroid Build Coastguard Worker  * not be freed for the life of the destination.
1466*5e7646d2SAndroid Build Coastguard Worker  *
1467*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
1468*5e7646d2SAndroid Build Coastguard Worker  */
1469*5e7646d2SAndroid Build Coastguard Worker 
1470*5e7646d2SAndroid Build Coastguard Worker 
1471*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - New attribute */
ippCopyAttribute(ipp_t * dst,ipp_attribute_t * srcattr,int quickcopy)1472*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(
1473*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *dst,		/* I - Destination IPP message */
1474*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *srcattr,		/* I - Attribute to copy */
1475*5e7646d2SAndroid Build Coastguard Worker     int             quickcopy)		/* I - 1 for a referenced copy, 0 for normal */
1476*5e7646d2SAndroid Build Coastguard Worker {
1477*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
1478*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		srctag;		/* Source value tag */
1479*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*dstattr;	/* Destination attribute */
1480*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*srcval,	/* Source value */
1481*5e7646d2SAndroid Build Coastguard Worker 			*dstval;	/* Destination value */
1482*5e7646d2SAndroid Build Coastguard Worker 
1483*5e7646d2SAndroid Build Coastguard Worker 
1484*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippCopyAttribute(dst=%p, srcattr=%p, quickcopy=%d)", (void *)dst, (void *)srcattr, quickcopy));
1485*5e7646d2SAndroid Build Coastguard Worker 
1486*5e7646d2SAndroid Build Coastguard Worker  /*
1487*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1488*5e7646d2SAndroid Build Coastguard Worker   */
1489*5e7646d2SAndroid Build Coastguard Worker 
1490*5e7646d2SAndroid Build Coastguard Worker   if (!dst || !srcattr)
1491*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1492*5e7646d2SAndroid Build Coastguard Worker 
1493*5e7646d2SAndroid Build Coastguard Worker  /*
1494*5e7646d2SAndroid Build Coastguard Worker   * Copy it...
1495*5e7646d2SAndroid Build Coastguard Worker   */
1496*5e7646d2SAndroid Build Coastguard Worker 
1497*5e7646d2SAndroid Build Coastguard Worker   quickcopy = (quickcopy && (srcattr->value_tag & IPP_TAG_CUPS_CONST)) ? IPP_TAG_CUPS_CONST : 0;
1498*5e7646d2SAndroid Build Coastguard Worker   srctag    = srcattr->value_tag & IPP_TAG_CUPS_MASK;
1499*5e7646d2SAndroid Build Coastguard Worker 
1500*5e7646d2SAndroid Build Coastguard Worker   switch (srctag)
1501*5e7646d2SAndroid Build Coastguard Worker   {
1502*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ZERO :
1503*5e7646d2SAndroid Build Coastguard Worker         dstattr = ippAddSeparator(dst);
1504*5e7646d2SAndroid Build Coastguard Worker 	break;
1505*5e7646d2SAndroid Build Coastguard Worker 
1506*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNSUPPORTED_VALUE :
1507*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DEFAULT :
1508*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNKNOWN :
1509*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOVALUE :
1510*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOTSETTABLE :
1511*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DELETEATTR :
1512*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ADMINDEFINE :
1513*5e7646d2SAndroid Build Coastguard Worker         dstattr = ippAddOutOfBand(dst, srcattr->group_tag, srctag, srcattr->name);
1514*5e7646d2SAndroid Build Coastguard Worker         break;
1515*5e7646d2SAndroid Build Coastguard Worker 
1516*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
1517*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
1518*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BOOLEAN :
1519*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DATE :
1520*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
1521*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
1522*5e7646d2SAndroid Build Coastguard Worker         if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) != NULL)
1523*5e7646d2SAndroid Build Coastguard Worker 	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
1524*5e7646d2SAndroid Build Coastguard Worker         break;
1525*5e7646d2SAndroid Build Coastguard Worker 
1526*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
1527*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
1528*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESERVED_STRING :
1529*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
1530*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
1531*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
1532*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
1533*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
1534*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
1535*5e7646d2SAndroid Build Coastguard Worker         if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL)
1536*5e7646d2SAndroid Build Coastguard Worker           break;
1537*5e7646d2SAndroid Build Coastguard Worker 
1538*5e7646d2SAndroid Build Coastguard Worker         if (quickcopy)
1539*5e7646d2SAndroid Build Coastguard Worker 	{
1540*5e7646d2SAndroid Build Coastguard Worker 	 /*
1541*5e7646d2SAndroid Build Coastguard Worker 	  * Can safely quick-copy these string values...
1542*5e7646d2SAndroid Build Coastguard Worker 	  */
1543*5e7646d2SAndroid Build Coastguard Worker 
1544*5e7646d2SAndroid Build Coastguard Worker 	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
1545*5e7646d2SAndroid Build Coastguard Worker         }
1546*5e7646d2SAndroid Build Coastguard Worker 	else
1547*5e7646d2SAndroid Build Coastguard Worker 	{
1548*5e7646d2SAndroid Build Coastguard Worker 	 /*
1549*5e7646d2SAndroid Build Coastguard Worker 	  * Otherwise do a normal reference counted copy...
1550*5e7646d2SAndroid Build Coastguard Worker 	  */
1551*5e7646d2SAndroid Build Coastguard Worker 
1552*5e7646d2SAndroid Build Coastguard Worker 	  for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
1553*5e7646d2SAndroid Build Coastguard Worker 	    dstval->string.text = _cupsStrAlloc(srcval->string.text);
1554*5e7646d2SAndroid Build Coastguard Worker 	}
1555*5e7646d2SAndroid Build Coastguard Worker         break;
1556*5e7646d2SAndroid Build Coastguard Worker 
1557*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
1558*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
1559*5e7646d2SAndroid Build Coastguard Worker         if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL)
1560*5e7646d2SAndroid Build Coastguard Worker           break;
1561*5e7646d2SAndroid Build Coastguard Worker 
1562*5e7646d2SAndroid Build Coastguard Worker         if (quickcopy)
1563*5e7646d2SAndroid Build Coastguard Worker 	{
1564*5e7646d2SAndroid Build Coastguard Worker 	 /*
1565*5e7646d2SAndroid Build Coastguard Worker 	  * Can safely quick-copy these string values...
1566*5e7646d2SAndroid Build Coastguard Worker 	  */
1567*5e7646d2SAndroid Build Coastguard Worker 
1568*5e7646d2SAndroid Build Coastguard Worker 	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
1569*5e7646d2SAndroid Build Coastguard Worker         }
1570*5e7646d2SAndroid Build Coastguard Worker 	else if (srcattr->value_tag & IPP_TAG_CUPS_CONST)
1571*5e7646d2SAndroid Build Coastguard Worker 	{
1572*5e7646d2SAndroid Build Coastguard Worker 	 /*
1573*5e7646d2SAndroid Build Coastguard Worker 	  * Otherwise do a normal reference counted copy...
1574*5e7646d2SAndroid Build Coastguard Worker 	  */
1575*5e7646d2SAndroid Build Coastguard Worker 
1576*5e7646d2SAndroid Build Coastguard Worker 	  for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
1577*5e7646d2SAndroid Build Coastguard Worker 	  {
1578*5e7646d2SAndroid Build Coastguard Worker 	    if (srcval == srcattr->values)
1579*5e7646d2SAndroid Build Coastguard Worker               dstval->string.language = _cupsStrAlloc(srcval->string.language);
1580*5e7646d2SAndroid Build Coastguard Worker 	    else
1581*5e7646d2SAndroid Build Coastguard Worker               dstval->string.language = dstattr->values[0].string.language;
1582*5e7646d2SAndroid Build Coastguard Worker 
1583*5e7646d2SAndroid Build Coastguard Worker 	    dstval->string.text = _cupsStrAlloc(srcval->string.text);
1584*5e7646d2SAndroid Build Coastguard Worker           }
1585*5e7646d2SAndroid Build Coastguard Worker         }
1586*5e7646d2SAndroid Build Coastguard Worker         break;
1587*5e7646d2SAndroid Build Coastguard Worker 
1588*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BEGIN_COLLECTION :
1589*5e7646d2SAndroid Build Coastguard Worker         if ((dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name, srcattr->num_values, NULL)) == NULL)
1590*5e7646d2SAndroid Build Coastguard Worker           break;
1591*5e7646d2SAndroid Build Coastguard Worker 
1592*5e7646d2SAndroid Build Coastguard Worker         for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
1593*5e7646d2SAndroid Build Coastguard Worker 	{
1594*5e7646d2SAndroid Build Coastguard Worker 	  dstval->collection = srcval->collection;
1595*5e7646d2SAndroid Build Coastguard Worker 	  srcval->collection->use ++;
1596*5e7646d2SAndroid Build Coastguard Worker 	}
1597*5e7646d2SAndroid Build Coastguard Worker         break;
1598*5e7646d2SAndroid Build Coastguard Worker 
1599*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_STRING :
1600*5e7646d2SAndroid Build Coastguard Worker     default :
1601*5e7646d2SAndroid Build Coastguard Worker         if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) == NULL)
1602*5e7646d2SAndroid Build Coastguard Worker           break;
1603*5e7646d2SAndroid Build Coastguard Worker 
1604*5e7646d2SAndroid Build Coastguard Worker         for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
1605*5e7646d2SAndroid Build Coastguard Worker 	{
1606*5e7646d2SAndroid Build Coastguard Worker 	  dstval->unknown.length = srcval->unknown.length;
1607*5e7646d2SAndroid Build Coastguard Worker 
1608*5e7646d2SAndroid Build Coastguard Worker 	  if (dstval->unknown.length > 0)
1609*5e7646d2SAndroid Build Coastguard Worker 	  {
1610*5e7646d2SAndroid Build Coastguard Worker 	    if ((dstval->unknown.data = malloc((size_t)dstval->unknown.length)) == NULL)
1611*5e7646d2SAndroid Build Coastguard Worker 	      dstval->unknown.length = 0;
1612*5e7646d2SAndroid Build Coastguard Worker 	    else
1613*5e7646d2SAndroid Build Coastguard Worker 	      memcpy(dstval->unknown.data, srcval->unknown.data, (size_t)dstval->unknown.length);
1614*5e7646d2SAndroid Build Coastguard Worker 	  }
1615*5e7646d2SAndroid Build Coastguard Worker 	}
1616*5e7646d2SAndroid Build Coastguard Worker         break; /* anti-compiler-warning-code */
1617*5e7646d2SAndroid Build Coastguard Worker   }
1618*5e7646d2SAndroid Build Coastguard Worker 
1619*5e7646d2SAndroid Build Coastguard Worker   return (dstattr);
1620*5e7646d2SAndroid Build Coastguard Worker }
1621*5e7646d2SAndroid Build Coastguard Worker 
1622*5e7646d2SAndroid Build Coastguard Worker 
1623*5e7646d2SAndroid Build Coastguard Worker /*
1624*5e7646d2SAndroid Build Coastguard Worker  * 'ippCopyAttributes()' - Copy attributes from one IPP message to another.
1625*5e7646d2SAndroid Build Coastguard Worker  *
1626*5e7646d2SAndroid Build Coastguard Worker  * Zero or more attributes are copied from the source IPP message, @code src@, to the
1627*5e7646d2SAndroid Build Coastguard Worker  * destination IPP message, @code dst@. When @code quickcopy@ is non-zero, a "shallow"
1628*5e7646d2SAndroid Build Coastguard Worker  * reference copy of the attribute is created - this should only be done as long as the
1629*5e7646d2SAndroid Build Coastguard Worker  * original source IPP message will not be freed for the life of the destination.
1630*5e7646d2SAndroid Build Coastguard Worker  *
1631*5e7646d2SAndroid Build Coastguard Worker  * The @code cb@ and @code context@ parameters provide a generic way to "filter" the
1632*5e7646d2SAndroid Build Coastguard Worker  * attributes that are copied - the function must return 1 to copy the attribute or
1633*5e7646d2SAndroid Build Coastguard Worker  * 0 to skip it. The function may also choose to do a partial copy of the source attribute
1634*5e7646d2SAndroid Build Coastguard Worker  * itself.
1635*5e7646d2SAndroid Build Coastguard Worker  *
1636*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
1637*5e7646d2SAndroid Build Coastguard Worker  */
1638*5e7646d2SAndroid Build Coastguard Worker 
1639*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on error */
ippCopyAttributes(ipp_t * dst,ipp_t * src,int quickcopy,ipp_copycb_t cb,void * context)1640*5e7646d2SAndroid Build Coastguard Worker ippCopyAttributes(
1641*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *dst,			/* I - Destination IPP message */
1642*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *src,			/* I - Source IPP message */
1643*5e7646d2SAndroid Build Coastguard Worker     int          quickcopy,		/* I - 1 for a referenced copy, 0 for normal */
1644*5e7646d2SAndroid Build Coastguard Worker     ipp_copycb_t cb,			/* I - Copy callback or @code NULL@ for none */
1645*5e7646d2SAndroid Build Coastguard Worker     void         *context)		/* I - Context pointer */
1646*5e7646d2SAndroid Build Coastguard Worker {
1647*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*srcattr;	/* Source attribute */
1648*5e7646d2SAndroid Build Coastguard Worker 
1649*5e7646d2SAndroid Build Coastguard Worker 
1650*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippCopyAttributes(dst=%p, src=%p, quickcopy=%d, cb=%p, context=%p)", (void *)dst, (void *)src, quickcopy, (void *)cb, context));
1651*5e7646d2SAndroid Build Coastguard Worker 
1652*5e7646d2SAndroid Build Coastguard Worker  /*
1653*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1654*5e7646d2SAndroid Build Coastguard Worker   */
1655*5e7646d2SAndroid Build Coastguard Worker 
1656*5e7646d2SAndroid Build Coastguard Worker   if (!dst || !src)
1657*5e7646d2SAndroid Build Coastguard Worker     return (0);
1658*5e7646d2SAndroid Build Coastguard Worker 
1659*5e7646d2SAndroid Build Coastguard Worker  /*
1660*5e7646d2SAndroid Build Coastguard Worker   * Loop through source attributes and copy as needed...
1661*5e7646d2SAndroid Build Coastguard Worker   */
1662*5e7646d2SAndroid Build Coastguard Worker 
1663*5e7646d2SAndroid Build Coastguard Worker   for (srcattr = src->attrs; srcattr; srcattr = srcattr->next)
1664*5e7646d2SAndroid Build Coastguard Worker     if (!cb || (*cb)(context, dst, srcattr))
1665*5e7646d2SAndroid Build Coastguard Worker       if (!ippCopyAttribute(dst, srcattr, quickcopy))
1666*5e7646d2SAndroid Build Coastguard Worker         return (0);
1667*5e7646d2SAndroid Build Coastguard Worker 
1668*5e7646d2SAndroid Build Coastguard Worker   return (1);
1669*5e7646d2SAndroid Build Coastguard Worker }
1670*5e7646d2SAndroid Build Coastguard Worker 
1671*5e7646d2SAndroid Build Coastguard Worker 
1672*5e7646d2SAndroid Build Coastguard Worker /*
1673*5e7646d2SAndroid Build Coastguard Worker  * 'ippDateToTime()' - Convert from RFC 2579 Date/Time format to time in
1674*5e7646d2SAndroid Build Coastguard Worker  *                     seconds.
1675*5e7646d2SAndroid Build Coastguard Worker  */
1676*5e7646d2SAndroid Build Coastguard Worker 
1677*5e7646d2SAndroid Build Coastguard Worker time_t					/* O - UNIX time value */
ippDateToTime(const ipp_uchar_t * date)1678*5e7646d2SAndroid Build Coastguard Worker ippDateToTime(const ipp_uchar_t *date)	/* I - RFC 2579 date info */
1679*5e7646d2SAndroid Build Coastguard Worker {
1680*5e7646d2SAndroid Build Coastguard Worker   struct tm	unixdate;		/* UNIX date/time info */
1681*5e7646d2SAndroid Build Coastguard Worker   time_t	t;			/* Computed time */
1682*5e7646d2SAndroid Build Coastguard Worker 
1683*5e7646d2SAndroid Build Coastguard Worker 
1684*5e7646d2SAndroid Build Coastguard Worker   if (!date)
1685*5e7646d2SAndroid Build Coastguard Worker     return (0);
1686*5e7646d2SAndroid Build Coastguard Worker 
1687*5e7646d2SAndroid Build Coastguard Worker   memset(&unixdate, 0, sizeof(unixdate));
1688*5e7646d2SAndroid Build Coastguard Worker 
1689*5e7646d2SAndroid Build Coastguard Worker  /*
1690*5e7646d2SAndroid Build Coastguard Worker   * RFC-2579 date/time format is:
1691*5e7646d2SAndroid Build Coastguard Worker   *
1692*5e7646d2SAndroid Build Coastguard Worker   *    Byte(s)  Description
1693*5e7646d2SAndroid Build Coastguard Worker   *    -------  -----------
1694*5e7646d2SAndroid Build Coastguard Worker   *    0-1      Year (0 to 65535)
1695*5e7646d2SAndroid Build Coastguard Worker   *    2        Month (1 to 12)
1696*5e7646d2SAndroid Build Coastguard Worker   *    3        Day (1 to 31)
1697*5e7646d2SAndroid Build Coastguard Worker   *    4        Hours (0 to 23)
1698*5e7646d2SAndroid Build Coastguard Worker   *    5        Minutes (0 to 59)
1699*5e7646d2SAndroid Build Coastguard Worker   *    6        Seconds (0 to 60, 60 = "leap second")
1700*5e7646d2SAndroid Build Coastguard Worker   *    7        Deciseconds (0 to 9)
1701*5e7646d2SAndroid Build Coastguard Worker   *    8        +/- UTC
1702*5e7646d2SAndroid Build Coastguard Worker   *    9        UTC hours (0 to 11)
1703*5e7646d2SAndroid Build Coastguard Worker   *    10       UTC minutes (0 to 59)
1704*5e7646d2SAndroid Build Coastguard Worker   */
1705*5e7646d2SAndroid Build Coastguard Worker 
1706*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900;
1707*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_mon  = date[2] - 1;
1708*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_mday = date[3];
1709*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_hour = date[4];
1710*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_min  = date[5];
1711*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_sec  = date[6];
1712*5e7646d2SAndroid Build Coastguard Worker 
1713*5e7646d2SAndroid Build Coastguard Worker   t = mktime(&unixdate);
1714*5e7646d2SAndroid Build Coastguard Worker 
1715*5e7646d2SAndroid Build Coastguard Worker   if (date[8] == '-')
1716*5e7646d2SAndroid Build Coastguard Worker     t += date[9] * 3600 + date[10] * 60;
1717*5e7646d2SAndroid Build Coastguard Worker   else
1718*5e7646d2SAndroid Build Coastguard Worker     t -= date[9] * 3600 + date[10] * 60;
1719*5e7646d2SAndroid Build Coastguard Worker 
1720*5e7646d2SAndroid Build Coastguard Worker   return (t);
1721*5e7646d2SAndroid Build Coastguard Worker }
1722*5e7646d2SAndroid Build Coastguard Worker 
1723*5e7646d2SAndroid Build Coastguard Worker 
1724*5e7646d2SAndroid Build Coastguard Worker /*
1725*5e7646d2SAndroid Build Coastguard Worker  * 'ippDelete()' - Delete an IPP message.
1726*5e7646d2SAndroid Build Coastguard Worker  */
1727*5e7646d2SAndroid Build Coastguard Worker 
1728*5e7646d2SAndroid Build Coastguard Worker void
ippDelete(ipp_t * ipp)1729*5e7646d2SAndroid Build Coastguard Worker ippDelete(ipp_t *ipp)			/* I - IPP message */
1730*5e7646d2SAndroid Build Coastguard Worker {
1731*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr,		/* Current attribute */
1732*5e7646d2SAndroid Build Coastguard Worker 			*next;		/* Next attribute */
1733*5e7646d2SAndroid Build Coastguard Worker 
1734*5e7646d2SAndroid Build Coastguard Worker 
1735*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippDelete(ipp=%p)", (void *)ipp));
1736*5e7646d2SAndroid Build Coastguard Worker 
1737*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
1738*5e7646d2SAndroid Build Coastguard Worker     return;
1739*5e7646d2SAndroid Build Coastguard Worker 
1740*5e7646d2SAndroid Build Coastguard Worker   ipp->use --;
1741*5e7646d2SAndroid Build Coastguard Worker   if (ipp->use > 0)
1742*5e7646d2SAndroid Build Coastguard Worker   {
1743*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_retain: %p IPP message (use=%d)", (void *)ipp, ipp->use));
1744*5e7646d2SAndroid Build Coastguard Worker     return;
1745*5e7646d2SAndroid Build Coastguard Worker   }
1746*5e7646d2SAndroid Build Coastguard Worker 
1747*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4debug_free: %p IPP message", (void *)ipp));
1748*5e7646d2SAndroid Build Coastguard Worker 
1749*5e7646d2SAndroid Build Coastguard Worker   for (attr = ipp->attrs; attr != NULL; attr = next)
1750*5e7646d2SAndroid Build Coastguard Worker   {
1751*5e7646d2SAndroid Build Coastguard Worker     next = attr->next;
1752*5e7646d2SAndroid Build Coastguard Worker 
1753*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_free: %p %s %s%s (%d values)", (void *)attr, attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), attr->num_values));
1754*5e7646d2SAndroid Build Coastguard Worker 
1755*5e7646d2SAndroid Build Coastguard Worker     ipp_free_values(attr, 0, attr->num_values);
1756*5e7646d2SAndroid Build Coastguard Worker 
1757*5e7646d2SAndroid Build Coastguard Worker     if (attr->name)
1758*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFree(attr->name);
1759*5e7646d2SAndroid Build Coastguard Worker 
1760*5e7646d2SAndroid Build Coastguard Worker     free(attr);
1761*5e7646d2SAndroid Build Coastguard Worker   }
1762*5e7646d2SAndroid Build Coastguard Worker 
1763*5e7646d2SAndroid Build Coastguard Worker   free(ipp);
1764*5e7646d2SAndroid Build Coastguard Worker }
1765*5e7646d2SAndroid Build Coastguard Worker 
1766*5e7646d2SAndroid Build Coastguard Worker 
1767*5e7646d2SAndroid Build Coastguard Worker /*
1768*5e7646d2SAndroid Build Coastguard Worker  * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
1769*5e7646d2SAndroid Build Coastguard Worker  *
1770*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
1771*5e7646d2SAndroid Build Coastguard Worker  */
1772*5e7646d2SAndroid Build Coastguard Worker 
1773*5e7646d2SAndroid Build Coastguard Worker void
ippDeleteAttribute(ipp_t * ipp,ipp_attribute_t * attr)1774*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(
1775*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I - IPP message */
1776*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr)		/* I - Attribute to delete */
1777*5e7646d2SAndroid Build Coastguard Worker {
1778*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*current,	/* Current attribute */
1779*5e7646d2SAndroid Build Coastguard Worker 			*prev;		/* Previous attribute */
1780*5e7646d2SAndroid Build Coastguard Worker 
1781*5e7646d2SAndroid Build Coastguard Worker 
1782*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", (void *)ipp, (void *)attr, attr ? attr->name : "(null)"));
1783*5e7646d2SAndroid Build Coastguard Worker 
1784*5e7646d2SAndroid Build Coastguard Worker  /*
1785*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1786*5e7646d2SAndroid Build Coastguard Worker   */
1787*5e7646d2SAndroid Build Coastguard Worker 
1788*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
1789*5e7646d2SAndroid Build Coastguard Worker     return;
1790*5e7646d2SAndroid Build Coastguard Worker 
1791*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4debug_free: %p %s %s%s (%d values)", (void *)attr, attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), attr->num_values));
1792*5e7646d2SAndroid Build Coastguard Worker 
1793*5e7646d2SAndroid Build Coastguard Worker  /*
1794*5e7646d2SAndroid Build Coastguard Worker   * Find the attribute in the list...
1795*5e7646d2SAndroid Build Coastguard Worker   */
1796*5e7646d2SAndroid Build Coastguard Worker 
1797*5e7646d2SAndroid Build Coastguard Worker   if (ipp)
1798*5e7646d2SAndroid Build Coastguard Worker   {
1799*5e7646d2SAndroid Build Coastguard Worker     for (current = ipp->attrs, prev = NULL;
1800*5e7646d2SAndroid Build Coastguard Worker 	 current;
1801*5e7646d2SAndroid Build Coastguard Worker 	 prev = current, current = current->next)
1802*5e7646d2SAndroid Build Coastguard Worker       if (current == attr)
1803*5e7646d2SAndroid Build Coastguard Worker       {
1804*5e7646d2SAndroid Build Coastguard Worker        /*
1805*5e7646d2SAndroid Build Coastguard Worker 	* Found it, remove the attribute from the list...
1806*5e7646d2SAndroid Build Coastguard Worker 	*/
1807*5e7646d2SAndroid Build Coastguard Worker 
1808*5e7646d2SAndroid Build Coastguard Worker 	if (prev)
1809*5e7646d2SAndroid Build Coastguard Worker 	  prev->next = current->next;
1810*5e7646d2SAndroid Build Coastguard Worker 	else
1811*5e7646d2SAndroid Build Coastguard Worker 	  ipp->attrs = current->next;
1812*5e7646d2SAndroid Build Coastguard Worker 
1813*5e7646d2SAndroid Build Coastguard Worker 	if (current == ipp->last)
1814*5e7646d2SAndroid Build Coastguard Worker 	  ipp->last = prev;
1815*5e7646d2SAndroid Build Coastguard Worker 
1816*5e7646d2SAndroid Build Coastguard Worker         break;
1817*5e7646d2SAndroid Build Coastguard Worker       }
1818*5e7646d2SAndroid Build Coastguard Worker 
1819*5e7646d2SAndroid Build Coastguard Worker     if (!current)
1820*5e7646d2SAndroid Build Coastguard Worker       return;
1821*5e7646d2SAndroid Build Coastguard Worker   }
1822*5e7646d2SAndroid Build Coastguard Worker 
1823*5e7646d2SAndroid Build Coastguard Worker  /*
1824*5e7646d2SAndroid Build Coastguard Worker   * Free memory used by the attribute...
1825*5e7646d2SAndroid Build Coastguard Worker   */
1826*5e7646d2SAndroid Build Coastguard Worker 
1827*5e7646d2SAndroid Build Coastguard Worker   ipp_free_values(attr, 0, attr->num_values);
1828*5e7646d2SAndroid Build Coastguard Worker 
1829*5e7646d2SAndroid Build Coastguard Worker   if (attr->name)
1830*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(attr->name);
1831*5e7646d2SAndroid Build Coastguard Worker 
1832*5e7646d2SAndroid Build Coastguard Worker   free(attr);
1833*5e7646d2SAndroid Build Coastguard Worker }
1834*5e7646d2SAndroid Build Coastguard Worker 
1835*5e7646d2SAndroid Build Coastguard Worker 
1836*5e7646d2SAndroid Build Coastguard Worker /*
1837*5e7646d2SAndroid Build Coastguard Worker  * 'ippDeleteValues()' - Delete values in an attribute.
1838*5e7646d2SAndroid Build Coastguard Worker  *
1839*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies the first value to delete, starting at
1840*5e7646d2SAndroid Build Coastguard Worker  * 0. It must be less than the number of values returned by @link ippGetCount@.
1841*5e7646d2SAndroid Build Coastguard Worker  *
1842*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
1843*5e7646d2SAndroid Build Coastguard Worker  *
1844*5e7646d2SAndroid Build Coastguard Worker  * Deleting all values in an attribute deletes the attribute.
1845*5e7646d2SAndroid Build Coastguard Worker  *
1846*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
1847*5e7646d2SAndroid Build Coastguard Worker  */
1848*5e7646d2SAndroid Build Coastguard Worker 
1849*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippDeleteValues(ipp_t * ipp,ipp_attribute_t ** attr,int element,int count)1850*5e7646d2SAndroid Build Coastguard Worker ippDeleteValues(
1851*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I  - IPP message */
1852*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - Attribute */
1853*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I  - Index of first value to delete (0-based) */
1854*5e7646d2SAndroid Build Coastguard Worker     int             count)		/* I  - Number of values to delete */
1855*5e7646d2SAndroid Build Coastguard Worker {
1856*5e7646d2SAndroid Build Coastguard Worker  /*
1857*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1858*5e7646d2SAndroid Build Coastguard Worker   */
1859*5e7646d2SAndroid Build Coastguard Worker 
1860*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr ||
1861*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= (*attr)->num_values || count <= 0 ||
1862*5e7646d2SAndroid Build Coastguard Worker       (element + count) >= (*attr)->num_values)
1863*5e7646d2SAndroid Build Coastguard Worker     return (0);
1864*5e7646d2SAndroid Build Coastguard Worker 
1865*5e7646d2SAndroid Build Coastguard Worker  /*
1866*5e7646d2SAndroid Build Coastguard Worker   * If we are deleting all values, just delete the attribute entirely.
1867*5e7646d2SAndroid Build Coastguard Worker   */
1868*5e7646d2SAndroid Build Coastguard Worker 
1869*5e7646d2SAndroid Build Coastguard Worker   if (count == (*attr)->num_values)
1870*5e7646d2SAndroid Build Coastguard Worker   {
1871*5e7646d2SAndroid Build Coastguard Worker     ippDeleteAttribute(ipp, *attr);
1872*5e7646d2SAndroid Build Coastguard Worker     *attr = NULL;
1873*5e7646d2SAndroid Build Coastguard Worker     return (1);
1874*5e7646d2SAndroid Build Coastguard Worker   }
1875*5e7646d2SAndroid Build Coastguard Worker 
1876*5e7646d2SAndroid Build Coastguard Worker  /*
1877*5e7646d2SAndroid Build Coastguard Worker   * Otherwise free the values in question and return.
1878*5e7646d2SAndroid Build Coastguard Worker   */
1879*5e7646d2SAndroid Build Coastguard Worker 
1880*5e7646d2SAndroid Build Coastguard Worker   ipp_free_values(*attr, element, count);
1881*5e7646d2SAndroid Build Coastguard Worker 
1882*5e7646d2SAndroid Build Coastguard Worker   return (1);
1883*5e7646d2SAndroid Build Coastguard Worker }
1884*5e7646d2SAndroid Build Coastguard Worker 
1885*5e7646d2SAndroid Build Coastguard Worker 
1886*5e7646d2SAndroid Build Coastguard Worker /*
1887*5e7646d2SAndroid Build Coastguard Worker  * 'ippFindAttribute()' - Find a named attribute in a request.
1888*5e7646d2SAndroid Build Coastguard Worker  *
1889*5e7646d2SAndroid Build Coastguard Worker  * Starting with CUPS 2.0, the attribute name can contain a hierarchical list
1890*5e7646d2SAndroid Build Coastguard Worker  * of attribute and member names separated by slashes, for example
1891*5e7646d2SAndroid Build Coastguard Worker  * "media-col/media-size".
1892*5e7646d2SAndroid Build Coastguard Worker  */
1893*5e7646d2SAndroid Build Coastguard Worker 
1894*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - Matching attribute */
ippFindAttribute(ipp_t * ipp,const char * name,ipp_tag_t type)1895*5e7646d2SAndroid Build Coastguard Worker ippFindAttribute(ipp_t      *ipp,	/* I - IPP message */
1896*5e7646d2SAndroid Build Coastguard Worker                  const char *name,	/* I - Name of attribute */
1897*5e7646d2SAndroid Build Coastguard Worker 		 ipp_tag_t  type)	/* I - Type of attribute */
1898*5e7646d2SAndroid Build Coastguard Worker {
1899*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", (void *)ipp, name, type, ippTagString(type)));
1900*5e7646d2SAndroid Build Coastguard Worker 
1901*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name)
1902*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1903*5e7646d2SAndroid Build Coastguard Worker 
1904*5e7646d2SAndroid Build Coastguard Worker  /*
1905*5e7646d2SAndroid Build Coastguard Worker   * Reset the current pointer...
1906*5e7646d2SAndroid Build Coastguard Worker   */
1907*5e7646d2SAndroid Build Coastguard Worker 
1908*5e7646d2SAndroid Build Coastguard Worker   ipp->current = NULL;
1909*5e7646d2SAndroid Build Coastguard Worker   ipp->atend   = 0;
1910*5e7646d2SAndroid Build Coastguard Worker 
1911*5e7646d2SAndroid Build Coastguard Worker  /*
1912*5e7646d2SAndroid Build Coastguard Worker   * Search for the attribute...
1913*5e7646d2SAndroid Build Coastguard Worker   */
1914*5e7646d2SAndroid Build Coastguard Worker 
1915*5e7646d2SAndroid Build Coastguard Worker   return (ippFindNextAttribute(ipp, name, type));
1916*5e7646d2SAndroid Build Coastguard Worker }
1917*5e7646d2SAndroid Build Coastguard Worker 
1918*5e7646d2SAndroid Build Coastguard Worker 
1919*5e7646d2SAndroid Build Coastguard Worker /*
1920*5e7646d2SAndroid Build Coastguard Worker  * 'ippFindNextAttribute()' - Find the next named attribute in a request.
1921*5e7646d2SAndroid Build Coastguard Worker  *
1922*5e7646d2SAndroid Build Coastguard Worker  * Starting with CUPS 2.0, the attribute name can contain a hierarchical list
1923*5e7646d2SAndroid Build Coastguard Worker  * of attribute and member names separated by slashes, for example
1924*5e7646d2SAndroid Build Coastguard Worker  * "media-col/media-size".
1925*5e7646d2SAndroid Build Coastguard Worker  */
1926*5e7646d2SAndroid Build Coastguard Worker 
1927*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - Matching attribute */
ippFindNextAttribute(ipp_t * ipp,const char * name,ipp_tag_t type)1928*5e7646d2SAndroid Build Coastguard Worker ippFindNextAttribute(ipp_t      *ipp,	/* I - IPP message */
1929*5e7646d2SAndroid Build Coastguard Worker                      const char *name,	/* I - Name of attribute */
1930*5e7646d2SAndroid Build Coastguard Worker 		     ipp_tag_t  type)	/* I - Type of attribute */
1931*5e7646d2SAndroid Build Coastguard Worker {
1932*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr,		/* Current atttribute */
1933*5e7646d2SAndroid Build Coastguard Worker 			*childattr;	/* Child attribute */
1934*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		value_tag;	/* Value tag */
1935*5e7646d2SAndroid Build Coastguard Worker   char			parent[1024],	/* Parent attribute name */
1936*5e7646d2SAndroid Build Coastguard Worker 			*child = NULL;	/* Child attribute name */
1937*5e7646d2SAndroid Build Coastguard Worker 
1938*5e7646d2SAndroid Build Coastguard Worker 
1939*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", (void *)ipp, name, type, ippTagString(type)));
1940*5e7646d2SAndroid Build Coastguard Worker 
1941*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !name)
1942*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1943*5e7646d2SAndroid Build Coastguard Worker 
1944*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3ippFindNextAttribute: atend=%d", ipp->atend));
1945*5e7646d2SAndroid Build Coastguard Worker 
1946*5e7646d2SAndroid Build Coastguard Worker   if (ipp->atend)
1947*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1948*5e7646d2SAndroid Build Coastguard Worker 
1949*5e7646d2SAndroid Build Coastguard Worker   if (strchr(name, '/'))
1950*5e7646d2SAndroid Build Coastguard Worker   {
1951*5e7646d2SAndroid Build Coastguard Worker    /*
1952*5e7646d2SAndroid Build Coastguard Worker     * Search for child attribute...
1953*5e7646d2SAndroid Build Coastguard Worker     */
1954*5e7646d2SAndroid Build Coastguard Worker 
1955*5e7646d2SAndroid Build Coastguard Worker     strlcpy(parent, name, sizeof(parent));
1956*5e7646d2SAndroid Build Coastguard Worker     if ((child = strchr(parent, '/')) == NULL)
1957*5e7646d2SAndroid Build Coastguard Worker     {
1958*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("3ippFindNextAttribute: Attribute name too long.");
1959*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
1960*5e7646d2SAndroid Build Coastguard Worker     }
1961*5e7646d2SAndroid Build Coastguard Worker 
1962*5e7646d2SAndroid Build Coastguard Worker     *child++ = '\0';
1963*5e7646d2SAndroid Build Coastguard Worker 
1964*5e7646d2SAndroid Build Coastguard Worker     if (ipp->current && ipp->current->name && ipp->current->value_tag == IPP_TAG_BEGIN_COLLECTION && !strcmp(parent, ipp->current->name))
1965*5e7646d2SAndroid Build Coastguard Worker     {
1966*5e7646d2SAndroid Build Coastguard Worker       while (ipp->curindex < ipp->current->num_values)
1967*5e7646d2SAndroid Build Coastguard Worker       {
1968*5e7646d2SAndroid Build Coastguard Worker         if ((childattr = ippFindNextAttribute(ipp->current->values[ipp->curindex].collection, child, type)) != NULL)
1969*5e7646d2SAndroid Build Coastguard Worker           return (childattr);
1970*5e7646d2SAndroid Build Coastguard Worker 
1971*5e7646d2SAndroid Build Coastguard Worker         ipp->curindex ++;
1972*5e7646d2SAndroid Build Coastguard Worker         if (ipp->curindex < ipp->current->num_values && ipp->current->values[ipp->curindex].collection)
1973*5e7646d2SAndroid Build Coastguard Worker           ipp->current->values[ipp->curindex].collection->current = NULL;
1974*5e7646d2SAndroid Build Coastguard Worker       }
1975*5e7646d2SAndroid Build Coastguard Worker 
1976*5e7646d2SAndroid Build Coastguard Worker       ipp->prev     = ipp->current;
1977*5e7646d2SAndroid Build Coastguard Worker       ipp->current  = ipp->current->next;
1978*5e7646d2SAndroid Build Coastguard Worker       ipp->curindex = 0;
1979*5e7646d2SAndroid Build Coastguard Worker 
1980*5e7646d2SAndroid Build Coastguard Worker       if (!ipp->current)
1981*5e7646d2SAndroid Build Coastguard Worker       {
1982*5e7646d2SAndroid Build Coastguard Worker         ipp->atend = 1;
1983*5e7646d2SAndroid Build Coastguard Worker         return (NULL);
1984*5e7646d2SAndroid Build Coastguard Worker       }
1985*5e7646d2SAndroid Build Coastguard Worker     }
1986*5e7646d2SAndroid Build Coastguard Worker 
1987*5e7646d2SAndroid Build Coastguard Worker     if (!ipp->current)
1988*5e7646d2SAndroid Build Coastguard Worker     {
1989*5e7646d2SAndroid Build Coastguard Worker       ipp->prev     = NULL;
1990*5e7646d2SAndroid Build Coastguard Worker       ipp->current  = ipp->attrs;
1991*5e7646d2SAndroid Build Coastguard Worker       ipp->curindex = 0;
1992*5e7646d2SAndroid Build Coastguard Worker     }
1993*5e7646d2SAndroid Build Coastguard Worker 
1994*5e7646d2SAndroid Build Coastguard Worker     name = parent;
1995*5e7646d2SAndroid Build Coastguard Worker     attr = ipp->current;
1996*5e7646d2SAndroid Build Coastguard Worker   }
1997*5e7646d2SAndroid Build Coastguard Worker   else if (ipp->current)
1998*5e7646d2SAndroid Build Coastguard Worker   {
1999*5e7646d2SAndroid Build Coastguard Worker     ipp->prev = ipp->current;
2000*5e7646d2SAndroid Build Coastguard Worker     attr      = ipp->current->next;
2001*5e7646d2SAndroid Build Coastguard Worker   }
2002*5e7646d2SAndroid Build Coastguard Worker   else
2003*5e7646d2SAndroid Build Coastguard Worker   {
2004*5e7646d2SAndroid Build Coastguard Worker     ipp->prev = NULL;
2005*5e7646d2SAndroid Build Coastguard Worker     attr      = ipp->attrs;
2006*5e7646d2SAndroid Build Coastguard Worker   }
2007*5e7646d2SAndroid Build Coastguard Worker 
2008*5e7646d2SAndroid Build Coastguard Worker   for (; attr != NULL; ipp->prev = attr, attr = attr->next)
2009*5e7646d2SAndroid Build Coastguard Worker   {
2010*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", (void *)attr, attr->name));
2011*5e7646d2SAndroid Build Coastguard Worker 
2012*5e7646d2SAndroid Build Coastguard Worker     value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_CUPS_MASK);
2013*5e7646d2SAndroid Build Coastguard Worker 
2014*5e7646d2SAndroid Build Coastguard Worker     if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 &&
2015*5e7646d2SAndroid Build Coastguard Worker         (value_tag == type || type == IPP_TAG_ZERO || name == parent ||
2016*5e7646d2SAndroid Build Coastguard Worker 	 (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) ||
2017*5e7646d2SAndroid Build Coastguard Worker 	 (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
2018*5e7646d2SAndroid Build Coastguard Worker     {
2019*5e7646d2SAndroid Build Coastguard Worker       ipp->current = attr;
2020*5e7646d2SAndroid Build Coastguard Worker 
2021*5e7646d2SAndroid Build Coastguard Worker       if (name == parent && attr->value_tag == IPP_TAG_BEGIN_COLLECTION)
2022*5e7646d2SAndroid Build Coastguard Worker       {
2023*5e7646d2SAndroid Build Coastguard Worker         int i;				/* Looping var */
2024*5e7646d2SAndroid Build Coastguard Worker 
2025*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
2026*5e7646d2SAndroid Build Coastguard Worker         {
2027*5e7646d2SAndroid Build Coastguard Worker 	  if ((childattr = ippFindAttribute(attr->values[i].collection, child, type)) != NULL)
2028*5e7646d2SAndroid Build Coastguard Worker 	  {
2029*5e7646d2SAndroid Build Coastguard Worker 	    attr->values[0].collection->curindex = i;
2030*5e7646d2SAndroid Build Coastguard Worker 	    return (childattr);
2031*5e7646d2SAndroid Build Coastguard Worker 	  }
2032*5e7646d2SAndroid Build Coastguard Worker         }
2033*5e7646d2SAndroid Build Coastguard Worker       }
2034*5e7646d2SAndroid Build Coastguard Worker       else
2035*5e7646d2SAndroid Build Coastguard Worker         return (attr);
2036*5e7646d2SAndroid Build Coastguard Worker     }
2037*5e7646d2SAndroid Build Coastguard Worker   }
2038*5e7646d2SAndroid Build Coastguard Worker 
2039*5e7646d2SAndroid Build Coastguard Worker   ipp->current = NULL;
2040*5e7646d2SAndroid Build Coastguard Worker   ipp->prev    = NULL;
2041*5e7646d2SAndroid Build Coastguard Worker   ipp->atend   = 1;
2042*5e7646d2SAndroid Build Coastguard Worker 
2043*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2044*5e7646d2SAndroid Build Coastguard Worker }
2045*5e7646d2SAndroid Build Coastguard Worker 
2046*5e7646d2SAndroid Build Coastguard Worker 
2047*5e7646d2SAndroid Build Coastguard Worker /*
2048*5e7646d2SAndroid Build Coastguard Worker  * 'ippFirstAttribute()' - Return the first attribute in the message.
2049*5e7646d2SAndroid Build Coastguard Worker  *
2050*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2051*5e7646d2SAndroid Build Coastguard Worker  */
2052*5e7646d2SAndroid Build Coastguard Worker 
2053*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - First attribute or @code NULL@ if none */
ippFirstAttribute(ipp_t * ipp)2054*5e7646d2SAndroid Build Coastguard Worker ippFirstAttribute(ipp_t *ipp)		/* I - IPP message */
2055*5e7646d2SAndroid Build Coastguard Worker {
2056*5e7646d2SAndroid Build Coastguard Worker  /*
2057*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2058*5e7646d2SAndroid Build Coastguard Worker   */
2059*5e7646d2SAndroid Build Coastguard Worker 
2060*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2061*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2062*5e7646d2SAndroid Build Coastguard Worker 
2063*5e7646d2SAndroid Build Coastguard Worker  /*
2064*5e7646d2SAndroid Build Coastguard Worker   * Return the first attribute...
2065*5e7646d2SAndroid Build Coastguard Worker   */
2066*5e7646d2SAndroid Build Coastguard Worker 
2067*5e7646d2SAndroid Build Coastguard Worker   return (ipp->current = ipp->attrs);
2068*5e7646d2SAndroid Build Coastguard Worker }
2069*5e7646d2SAndroid Build Coastguard Worker 
2070*5e7646d2SAndroid Build Coastguard Worker 
2071*5e7646d2SAndroid Build Coastguard Worker /*
2072*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetBoolean()' - Get a boolean value for an attribute.
2073*5e7646d2SAndroid Build Coastguard Worker  *
2074*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2075*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2076*5e7646d2SAndroid Build Coastguard Worker  *
2077*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2078*5e7646d2SAndroid Build Coastguard Worker  */
2079*5e7646d2SAndroid Build Coastguard Worker 
2080*5e7646d2SAndroid Build Coastguard Worker int					/* O - Boolean value or 0 on error */
ippGetBoolean(ipp_attribute_t * attr,int element)2081*5e7646d2SAndroid Build Coastguard Worker ippGetBoolean(ipp_attribute_t *attr,	/* I - IPP attribute */
2082*5e7646d2SAndroid Build Coastguard Worker               int             element)	/* I - Value number (0-based) */
2083*5e7646d2SAndroid Build Coastguard Worker {
2084*5e7646d2SAndroid Build Coastguard Worker  /*
2085*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2086*5e7646d2SAndroid Build Coastguard Worker   */
2087*5e7646d2SAndroid Build Coastguard Worker 
2088*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_BOOLEAN ||
2089*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2090*5e7646d2SAndroid Build Coastguard Worker     return (0);
2091*5e7646d2SAndroid Build Coastguard Worker 
2092*5e7646d2SAndroid Build Coastguard Worker  /*
2093*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2094*5e7646d2SAndroid Build Coastguard Worker   */
2095*5e7646d2SAndroid Build Coastguard Worker 
2096*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].boolean);
2097*5e7646d2SAndroid Build Coastguard Worker }
2098*5e7646d2SAndroid Build Coastguard Worker 
2099*5e7646d2SAndroid Build Coastguard Worker 
2100*5e7646d2SAndroid Build Coastguard Worker /*
2101*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetCollection()' - Get a collection value for an attribute.
2102*5e7646d2SAndroid Build Coastguard Worker  *
2103*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2104*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2105*5e7646d2SAndroid Build Coastguard Worker  *
2106*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2107*5e7646d2SAndroid Build Coastguard Worker  */
2108*5e7646d2SAndroid Build Coastguard Worker 
2109*5e7646d2SAndroid Build Coastguard Worker ipp_t *					/* O - Collection value or @code NULL@ on error */
ippGetCollection(ipp_attribute_t * attr,int element)2110*5e7646d2SAndroid Build Coastguard Worker ippGetCollection(
2111*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - IPP attribute */
2112*5e7646d2SAndroid Build Coastguard Worker     int             element)		/* I - Value number (0-based) */
2113*5e7646d2SAndroid Build Coastguard Worker {
2114*5e7646d2SAndroid Build Coastguard Worker  /*
2115*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2116*5e7646d2SAndroid Build Coastguard Worker   */
2117*5e7646d2SAndroid Build Coastguard Worker 
2118*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_BEGIN_COLLECTION ||
2119*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2120*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2121*5e7646d2SAndroid Build Coastguard Worker 
2122*5e7646d2SAndroid Build Coastguard Worker  /*
2123*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2124*5e7646d2SAndroid Build Coastguard Worker   */
2125*5e7646d2SAndroid Build Coastguard Worker 
2126*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].collection);
2127*5e7646d2SAndroid Build Coastguard Worker }
2128*5e7646d2SAndroid Build Coastguard Worker 
2129*5e7646d2SAndroid Build Coastguard Worker 
2130*5e7646d2SAndroid Build Coastguard Worker /*
2131*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetCount()' - Get the number of values in an attribute.
2132*5e7646d2SAndroid Build Coastguard Worker  *
2133*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2134*5e7646d2SAndroid Build Coastguard Worker  */
2135*5e7646d2SAndroid Build Coastguard Worker 
2136*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of values or 0 on error */
ippGetCount(ipp_attribute_t * attr)2137*5e7646d2SAndroid Build Coastguard Worker ippGetCount(ipp_attribute_t *attr)	/* I - IPP attribute */
2138*5e7646d2SAndroid Build Coastguard Worker {
2139*5e7646d2SAndroid Build Coastguard Worker  /*
2140*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2141*5e7646d2SAndroid Build Coastguard Worker   */
2142*5e7646d2SAndroid Build Coastguard Worker 
2143*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
2144*5e7646d2SAndroid Build Coastguard Worker     return (0);
2145*5e7646d2SAndroid Build Coastguard Worker 
2146*5e7646d2SAndroid Build Coastguard Worker  /*
2147*5e7646d2SAndroid Build Coastguard Worker   * Return the number of values...
2148*5e7646d2SAndroid Build Coastguard Worker   */
2149*5e7646d2SAndroid Build Coastguard Worker 
2150*5e7646d2SAndroid Build Coastguard Worker   return (attr->num_values);
2151*5e7646d2SAndroid Build Coastguard Worker }
2152*5e7646d2SAndroid Build Coastguard Worker 
2153*5e7646d2SAndroid Build Coastguard Worker 
2154*5e7646d2SAndroid Build Coastguard Worker /*
2155*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetDate()' - Get a dateTime value for an attribute.
2156*5e7646d2SAndroid Build Coastguard Worker  *
2157*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2158*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2159*5e7646d2SAndroid Build Coastguard Worker  *
2160*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2161*5e7646d2SAndroid Build Coastguard Worker  */
2162*5e7646d2SAndroid Build Coastguard Worker 
2163*5e7646d2SAndroid Build Coastguard Worker const ipp_uchar_t *			/* O - dateTime value or @code NULL@ */
ippGetDate(ipp_attribute_t * attr,int element)2164*5e7646d2SAndroid Build Coastguard Worker ippGetDate(ipp_attribute_t *attr,	/* I - IPP attribute */
2165*5e7646d2SAndroid Build Coastguard Worker            int             element)	/* I - Value number (0-based) */
2166*5e7646d2SAndroid Build Coastguard Worker {
2167*5e7646d2SAndroid Build Coastguard Worker  /*
2168*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2169*5e7646d2SAndroid Build Coastguard Worker   */
2170*5e7646d2SAndroid Build Coastguard Worker 
2171*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_DATE ||
2172*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2173*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2174*5e7646d2SAndroid Build Coastguard Worker 
2175*5e7646d2SAndroid Build Coastguard Worker  /*
2176*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2177*5e7646d2SAndroid Build Coastguard Worker   */
2178*5e7646d2SAndroid Build Coastguard Worker 
2179*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].date);
2180*5e7646d2SAndroid Build Coastguard Worker }
2181*5e7646d2SAndroid Build Coastguard Worker 
2182*5e7646d2SAndroid Build Coastguard Worker 
2183*5e7646d2SAndroid Build Coastguard Worker /*
2184*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetGroupTag()' - Get the group associated with an attribute.
2185*5e7646d2SAndroid Build Coastguard Worker  *
2186*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2187*5e7646d2SAndroid Build Coastguard Worker  */
2188*5e7646d2SAndroid Build Coastguard Worker 
2189*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t				/* O - Group tag or @code IPP_TAG_ZERO@ on error */
ippGetGroupTag(ipp_attribute_t * attr)2190*5e7646d2SAndroid Build Coastguard Worker ippGetGroupTag(ipp_attribute_t *attr)	/* I - IPP attribute */
2191*5e7646d2SAndroid Build Coastguard Worker {
2192*5e7646d2SAndroid Build Coastguard Worker  /*
2193*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2194*5e7646d2SAndroid Build Coastguard Worker   */
2195*5e7646d2SAndroid Build Coastguard Worker 
2196*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
2197*5e7646d2SAndroid Build Coastguard Worker     return (IPP_TAG_ZERO);
2198*5e7646d2SAndroid Build Coastguard Worker 
2199*5e7646d2SAndroid Build Coastguard Worker  /*
2200*5e7646d2SAndroid Build Coastguard Worker   * Return the group...
2201*5e7646d2SAndroid Build Coastguard Worker   */
2202*5e7646d2SAndroid Build Coastguard Worker 
2203*5e7646d2SAndroid Build Coastguard Worker   return (attr->group_tag);
2204*5e7646d2SAndroid Build Coastguard Worker }
2205*5e7646d2SAndroid Build Coastguard Worker 
2206*5e7646d2SAndroid Build Coastguard Worker 
2207*5e7646d2SAndroid Build Coastguard Worker /*
2208*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetInteger()' - Get the integer/enum value for an attribute.
2209*5e7646d2SAndroid Build Coastguard Worker  *
2210*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2211*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2212*5e7646d2SAndroid Build Coastguard Worker  *
2213*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2214*5e7646d2SAndroid Build Coastguard Worker  */
2215*5e7646d2SAndroid Build Coastguard Worker 
2216*5e7646d2SAndroid Build Coastguard Worker int					/* O - Value or 0 on error */
ippGetInteger(ipp_attribute_t * attr,int element)2217*5e7646d2SAndroid Build Coastguard Worker ippGetInteger(ipp_attribute_t *attr,	/* I - IPP attribute */
2218*5e7646d2SAndroid Build Coastguard Worker               int             element)	/* I - Value number (0-based) */
2219*5e7646d2SAndroid Build Coastguard Worker {
2220*5e7646d2SAndroid Build Coastguard Worker  /*
2221*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2222*5e7646d2SAndroid Build Coastguard Worker   */
2223*5e7646d2SAndroid Build Coastguard Worker 
2224*5e7646d2SAndroid Build Coastguard Worker   if (!attr || (attr->value_tag != IPP_TAG_INTEGER && attr->value_tag != IPP_TAG_ENUM) ||
2225*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2226*5e7646d2SAndroid Build Coastguard Worker     return (0);
2227*5e7646d2SAndroid Build Coastguard Worker 
2228*5e7646d2SAndroid Build Coastguard Worker  /*
2229*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2230*5e7646d2SAndroid Build Coastguard Worker   */
2231*5e7646d2SAndroid Build Coastguard Worker 
2232*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].integer);
2233*5e7646d2SAndroid Build Coastguard Worker }
2234*5e7646d2SAndroid Build Coastguard Worker 
2235*5e7646d2SAndroid Build Coastguard Worker 
2236*5e7646d2SAndroid Build Coastguard Worker /*
2237*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetName()' - Get the attribute name.
2238*5e7646d2SAndroid Build Coastguard Worker  *
2239*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2240*5e7646d2SAndroid Build Coastguard Worker  */
2241*5e7646d2SAndroid Build Coastguard Worker 
2242*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - Attribute name or @code NULL@ for separators */
ippGetName(ipp_attribute_t * attr)2243*5e7646d2SAndroid Build Coastguard Worker ippGetName(ipp_attribute_t *attr)	/* I - IPP attribute */
2244*5e7646d2SAndroid Build Coastguard Worker {
2245*5e7646d2SAndroid Build Coastguard Worker  /*
2246*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2247*5e7646d2SAndroid Build Coastguard Worker   */
2248*5e7646d2SAndroid Build Coastguard Worker 
2249*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
2250*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2251*5e7646d2SAndroid Build Coastguard Worker 
2252*5e7646d2SAndroid Build Coastguard Worker  /*
2253*5e7646d2SAndroid Build Coastguard Worker   * Return the name...
2254*5e7646d2SAndroid Build Coastguard Worker   */
2255*5e7646d2SAndroid Build Coastguard Worker 
2256*5e7646d2SAndroid Build Coastguard Worker   return (attr->name);
2257*5e7646d2SAndroid Build Coastguard Worker }
2258*5e7646d2SAndroid Build Coastguard Worker 
2259*5e7646d2SAndroid Build Coastguard Worker 
2260*5e7646d2SAndroid Build Coastguard Worker /*
2261*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetOctetString()' - Get an octetString value from an IPP attribute.
2262*5e7646d2SAndroid Build Coastguard Worker  *
2263*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2264*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2265*5e7646d2SAndroid Build Coastguard Worker  *
2266*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
2267*5e7646d2SAndroid Build Coastguard Worker  */
2268*5e7646d2SAndroid Build Coastguard Worker 
2269*5e7646d2SAndroid Build Coastguard Worker void *					/* O - Pointer to octetString data */
ippGetOctetString(ipp_attribute_t * attr,int element,int * datalen)2270*5e7646d2SAndroid Build Coastguard Worker ippGetOctetString(
2271*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - IPP attribute */
2272*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I - Value number (0-based) */
2273*5e7646d2SAndroid Build Coastguard Worker     int             *datalen)		/* O - Length of octetString data */
2274*5e7646d2SAndroid Build Coastguard Worker {
2275*5e7646d2SAndroid Build Coastguard Worker  /*
2276*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2277*5e7646d2SAndroid Build Coastguard Worker   */
2278*5e7646d2SAndroid Build Coastguard Worker 
2279*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_STRING ||
2280*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2281*5e7646d2SAndroid Build Coastguard Worker   {
2282*5e7646d2SAndroid Build Coastguard Worker     if (datalen)
2283*5e7646d2SAndroid Build Coastguard Worker       *datalen = 0;
2284*5e7646d2SAndroid Build Coastguard Worker 
2285*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2286*5e7646d2SAndroid Build Coastguard Worker   }
2287*5e7646d2SAndroid Build Coastguard Worker 
2288*5e7646d2SAndroid Build Coastguard Worker  /*
2289*5e7646d2SAndroid Build Coastguard Worker   * Return the values...
2290*5e7646d2SAndroid Build Coastguard Worker   */
2291*5e7646d2SAndroid Build Coastguard Worker 
2292*5e7646d2SAndroid Build Coastguard Worker   if (datalen)
2293*5e7646d2SAndroid Build Coastguard Worker     *datalen = attr->values[element].unknown.length;
2294*5e7646d2SAndroid Build Coastguard Worker 
2295*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].unknown.data);
2296*5e7646d2SAndroid Build Coastguard Worker }
2297*5e7646d2SAndroid Build Coastguard Worker 
2298*5e7646d2SAndroid Build Coastguard Worker 
2299*5e7646d2SAndroid Build Coastguard Worker /*
2300*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetOperation()' - Get the operation ID in an IPP message.
2301*5e7646d2SAndroid Build Coastguard Worker  *
2302*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2303*5e7646d2SAndroid Build Coastguard Worker  */
2304*5e7646d2SAndroid Build Coastguard Worker 
2305*5e7646d2SAndroid Build Coastguard Worker ipp_op_t				/* O - Operation ID or 0 on error */
ippGetOperation(ipp_t * ipp)2306*5e7646d2SAndroid Build Coastguard Worker ippGetOperation(ipp_t *ipp)		/* I - IPP request message */
2307*5e7646d2SAndroid Build Coastguard Worker {
2308*5e7646d2SAndroid Build Coastguard Worker  /*
2309*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2310*5e7646d2SAndroid Build Coastguard Worker   */
2311*5e7646d2SAndroid Build Coastguard Worker 
2312*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2313*5e7646d2SAndroid Build Coastguard Worker     return ((ipp_op_t)0);
2314*5e7646d2SAndroid Build Coastguard Worker 
2315*5e7646d2SAndroid Build Coastguard Worker  /*
2316*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2317*5e7646d2SAndroid Build Coastguard Worker   */
2318*5e7646d2SAndroid Build Coastguard Worker 
2319*5e7646d2SAndroid Build Coastguard Worker   return (ipp->request.op.operation_id);
2320*5e7646d2SAndroid Build Coastguard Worker }
2321*5e7646d2SAndroid Build Coastguard Worker 
2322*5e7646d2SAndroid Build Coastguard Worker 
2323*5e7646d2SAndroid Build Coastguard Worker /*
2324*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetRange()' - Get a rangeOfInteger value from an attribute.
2325*5e7646d2SAndroid Build Coastguard Worker  *
2326*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2327*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2328*5e7646d2SAndroid Build Coastguard Worker  *
2329*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2330*5e7646d2SAndroid Build Coastguard Worker  */
2331*5e7646d2SAndroid Build Coastguard Worker 
2332*5e7646d2SAndroid Build Coastguard Worker int					/* O - Lower value of range or 0 */
ippGetRange(ipp_attribute_t * attr,int element,int * uppervalue)2333*5e7646d2SAndroid Build Coastguard Worker ippGetRange(ipp_attribute_t *attr,	/* I - IPP attribute */
2334*5e7646d2SAndroid Build Coastguard Worker 	    int             element,	/* I - Value number (0-based) */
2335*5e7646d2SAndroid Build Coastguard Worker 	    int             *uppervalue)/* O - Upper value of range */
2336*5e7646d2SAndroid Build Coastguard Worker {
2337*5e7646d2SAndroid Build Coastguard Worker  /*
2338*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2339*5e7646d2SAndroid Build Coastguard Worker   */
2340*5e7646d2SAndroid Build Coastguard Worker 
2341*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_RANGE ||
2342*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2343*5e7646d2SAndroid Build Coastguard Worker   {
2344*5e7646d2SAndroid Build Coastguard Worker     if (uppervalue)
2345*5e7646d2SAndroid Build Coastguard Worker       *uppervalue = 0;
2346*5e7646d2SAndroid Build Coastguard Worker 
2347*5e7646d2SAndroid Build Coastguard Worker     return (0);
2348*5e7646d2SAndroid Build Coastguard Worker   }
2349*5e7646d2SAndroid Build Coastguard Worker 
2350*5e7646d2SAndroid Build Coastguard Worker  /*
2351*5e7646d2SAndroid Build Coastguard Worker   * Return the values...
2352*5e7646d2SAndroid Build Coastguard Worker   */
2353*5e7646d2SAndroid Build Coastguard Worker 
2354*5e7646d2SAndroid Build Coastguard Worker   if (uppervalue)
2355*5e7646d2SAndroid Build Coastguard Worker     *uppervalue = attr->values[element].range.upper;
2356*5e7646d2SAndroid Build Coastguard Worker 
2357*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].range.lower);
2358*5e7646d2SAndroid Build Coastguard Worker }
2359*5e7646d2SAndroid Build Coastguard Worker 
2360*5e7646d2SAndroid Build Coastguard Worker 
2361*5e7646d2SAndroid Build Coastguard Worker /*
2362*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetRequestId()' - Get the request ID from an IPP message.
2363*5e7646d2SAndroid Build Coastguard Worker  *
2364*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2365*5e7646d2SAndroid Build Coastguard Worker  */
2366*5e7646d2SAndroid Build Coastguard Worker 
2367*5e7646d2SAndroid Build Coastguard Worker int					/* O - Request ID or 0 on error */
ippGetRequestId(ipp_t * ipp)2368*5e7646d2SAndroid Build Coastguard Worker ippGetRequestId(ipp_t *ipp)		/* I - IPP message */
2369*5e7646d2SAndroid Build Coastguard Worker {
2370*5e7646d2SAndroid Build Coastguard Worker  /*
2371*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2372*5e7646d2SAndroid Build Coastguard Worker   */
2373*5e7646d2SAndroid Build Coastguard Worker 
2374*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2375*5e7646d2SAndroid Build Coastguard Worker     return (0);
2376*5e7646d2SAndroid Build Coastguard Worker 
2377*5e7646d2SAndroid Build Coastguard Worker  /*
2378*5e7646d2SAndroid Build Coastguard Worker   * Return the request ID...
2379*5e7646d2SAndroid Build Coastguard Worker   */
2380*5e7646d2SAndroid Build Coastguard Worker 
2381*5e7646d2SAndroid Build Coastguard Worker   return (ipp->request.any.request_id);
2382*5e7646d2SAndroid Build Coastguard Worker }
2383*5e7646d2SAndroid Build Coastguard Worker 
2384*5e7646d2SAndroid Build Coastguard Worker 
2385*5e7646d2SAndroid Build Coastguard Worker /*
2386*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetResolution()' - Get a resolution value for an attribute.
2387*5e7646d2SAndroid Build Coastguard Worker  *
2388*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2389*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2390*5e7646d2SAndroid Build Coastguard Worker  *
2391*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2392*5e7646d2SAndroid Build Coastguard Worker  */
2393*5e7646d2SAndroid Build Coastguard Worker 
2394*5e7646d2SAndroid Build Coastguard Worker int					/* O - Horizontal/cross feed resolution or 0 */
ippGetResolution(ipp_attribute_t * attr,int element,int * yres,ipp_res_t * units)2395*5e7646d2SAndroid Build Coastguard Worker ippGetResolution(
2396*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - IPP attribute */
2397*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I - Value number (0-based) */
2398*5e7646d2SAndroid Build Coastguard Worker     int             *yres,		/* O - Vertical/feed resolution */
2399*5e7646d2SAndroid Build Coastguard Worker     ipp_res_t       *units)		/* O - Units for resolution */
2400*5e7646d2SAndroid Build Coastguard Worker {
2401*5e7646d2SAndroid Build Coastguard Worker  /*
2402*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2403*5e7646d2SAndroid Build Coastguard Worker   */
2404*5e7646d2SAndroid Build Coastguard Worker 
2405*5e7646d2SAndroid Build Coastguard Worker   if (!attr || attr->value_tag != IPP_TAG_RESOLUTION ||
2406*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element >= attr->num_values)
2407*5e7646d2SAndroid Build Coastguard Worker   {
2408*5e7646d2SAndroid Build Coastguard Worker     if (yres)
2409*5e7646d2SAndroid Build Coastguard Worker       *yres = 0;
2410*5e7646d2SAndroid Build Coastguard Worker 
2411*5e7646d2SAndroid Build Coastguard Worker     if (units)
2412*5e7646d2SAndroid Build Coastguard Worker       *units = (ipp_res_t)0;
2413*5e7646d2SAndroid Build Coastguard Worker 
2414*5e7646d2SAndroid Build Coastguard Worker     return (0);
2415*5e7646d2SAndroid Build Coastguard Worker   }
2416*5e7646d2SAndroid Build Coastguard Worker 
2417*5e7646d2SAndroid Build Coastguard Worker  /*
2418*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2419*5e7646d2SAndroid Build Coastguard Worker   */
2420*5e7646d2SAndroid Build Coastguard Worker 
2421*5e7646d2SAndroid Build Coastguard Worker   if (yres)
2422*5e7646d2SAndroid Build Coastguard Worker     *yres = attr->values[element].resolution.yres;
2423*5e7646d2SAndroid Build Coastguard Worker 
2424*5e7646d2SAndroid Build Coastguard Worker   if (units)
2425*5e7646d2SAndroid Build Coastguard Worker     *units = attr->values[element].resolution.units;
2426*5e7646d2SAndroid Build Coastguard Worker 
2427*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].resolution.xres);
2428*5e7646d2SAndroid Build Coastguard Worker }
2429*5e7646d2SAndroid Build Coastguard Worker 
2430*5e7646d2SAndroid Build Coastguard Worker 
2431*5e7646d2SAndroid Build Coastguard Worker /*
2432*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetState()' - Get the IPP message state.
2433*5e7646d2SAndroid Build Coastguard Worker  *
2434*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2435*5e7646d2SAndroid Build Coastguard Worker  */
2436*5e7646d2SAndroid Build Coastguard Worker 
2437*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - IPP message state value */
ippGetState(ipp_t * ipp)2438*5e7646d2SAndroid Build Coastguard Worker ippGetState(ipp_t *ipp)			/* I - IPP message */
2439*5e7646d2SAndroid Build Coastguard Worker {
2440*5e7646d2SAndroid Build Coastguard Worker  /*
2441*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2442*5e7646d2SAndroid Build Coastguard Worker   */
2443*5e7646d2SAndroid Build Coastguard Worker 
2444*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2445*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_IDLE);
2446*5e7646d2SAndroid Build Coastguard Worker 
2447*5e7646d2SAndroid Build Coastguard Worker  /*
2448*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2449*5e7646d2SAndroid Build Coastguard Worker   */
2450*5e7646d2SAndroid Build Coastguard Worker 
2451*5e7646d2SAndroid Build Coastguard Worker   return (ipp->state);
2452*5e7646d2SAndroid Build Coastguard Worker }
2453*5e7646d2SAndroid Build Coastguard Worker 
2454*5e7646d2SAndroid Build Coastguard Worker 
2455*5e7646d2SAndroid Build Coastguard Worker /*
2456*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetStatusCode()' - Get the status code from an IPP response or event message.
2457*5e7646d2SAndroid Build Coastguard Worker  *
2458*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2459*5e7646d2SAndroid Build Coastguard Worker  */
2460*5e7646d2SAndroid Build Coastguard Worker 
2461*5e7646d2SAndroid Build Coastguard Worker ipp_status_t				/* O - Status code in IPP message */
ippGetStatusCode(ipp_t * ipp)2462*5e7646d2SAndroid Build Coastguard Worker ippGetStatusCode(ipp_t *ipp)		/* I - IPP response or event message */
2463*5e7646d2SAndroid Build Coastguard Worker {
2464*5e7646d2SAndroid Build Coastguard Worker  /*
2465*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2466*5e7646d2SAndroid Build Coastguard Worker   */
2467*5e7646d2SAndroid Build Coastguard Worker 
2468*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2469*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATUS_ERROR_INTERNAL);
2470*5e7646d2SAndroid Build Coastguard Worker 
2471*5e7646d2SAndroid Build Coastguard Worker  /*
2472*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2473*5e7646d2SAndroid Build Coastguard Worker   */
2474*5e7646d2SAndroid Build Coastguard Worker 
2475*5e7646d2SAndroid Build Coastguard Worker   return (ipp->request.status.status_code);
2476*5e7646d2SAndroid Build Coastguard Worker }
2477*5e7646d2SAndroid Build Coastguard Worker 
2478*5e7646d2SAndroid Build Coastguard Worker 
2479*5e7646d2SAndroid Build Coastguard Worker /*
2480*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetString()' - Get the string and optionally the language code for an attribute.
2481*5e7646d2SAndroid Build Coastguard Worker  *
2482*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to get from 0 to
2483*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@ - 1.
2484*5e7646d2SAndroid Build Coastguard Worker  *
2485*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2486*5e7646d2SAndroid Build Coastguard Worker  */
2487*5e7646d2SAndroid Build Coastguard Worker 
2488*5e7646d2SAndroid Build Coastguard Worker const char *
ippGetString(ipp_attribute_t * attr,int element,const char ** language)2489*5e7646d2SAndroid Build Coastguard Worker ippGetString(ipp_attribute_t *attr,	/* I - IPP attribute */
2490*5e7646d2SAndroid Build Coastguard Worker              int             element,	/* I - Value number (0-based) */
2491*5e7646d2SAndroid Build Coastguard Worker 	     const char      **language)/* O - Language code (@code NULL@ for don't care) */
2492*5e7646d2SAndroid Build Coastguard Worker {
2493*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	tag;			/* Value tag */
2494*5e7646d2SAndroid Build Coastguard Worker 
2495*5e7646d2SAndroid Build Coastguard Worker 
2496*5e7646d2SAndroid Build Coastguard Worker  /*
2497*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2498*5e7646d2SAndroid Build Coastguard Worker   */
2499*5e7646d2SAndroid Build Coastguard Worker 
2500*5e7646d2SAndroid Build Coastguard Worker   tag = ippGetValueTag(attr);
2501*5e7646d2SAndroid Build Coastguard Worker 
2502*5e7646d2SAndroid Build Coastguard Worker   if (!attr || element < 0 || element >= attr->num_values || (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG && (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE)))
2503*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2504*5e7646d2SAndroid Build Coastguard Worker 
2505*5e7646d2SAndroid Build Coastguard Worker  /*
2506*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2507*5e7646d2SAndroid Build Coastguard Worker   */
2508*5e7646d2SAndroid Build Coastguard Worker 
2509*5e7646d2SAndroid Build Coastguard Worker   if (language)
2510*5e7646d2SAndroid Build Coastguard Worker     *language = attr->values[element].string.language;
2511*5e7646d2SAndroid Build Coastguard Worker 
2512*5e7646d2SAndroid Build Coastguard Worker   return (attr->values[element].string.text);
2513*5e7646d2SAndroid Build Coastguard Worker }
2514*5e7646d2SAndroid Build Coastguard Worker 
2515*5e7646d2SAndroid Build Coastguard Worker 
2516*5e7646d2SAndroid Build Coastguard Worker /*
2517*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetValueTag()' - Get the value tag for an attribute.
2518*5e7646d2SAndroid Build Coastguard Worker  *
2519*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2520*5e7646d2SAndroid Build Coastguard Worker  */
2521*5e7646d2SAndroid Build Coastguard Worker 
2522*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t				/* O - Value tag or @code IPP_TAG_ZERO@ on error */
ippGetValueTag(ipp_attribute_t * attr)2523*5e7646d2SAndroid Build Coastguard Worker ippGetValueTag(ipp_attribute_t *attr)	/* I - IPP attribute */
2524*5e7646d2SAndroid Build Coastguard Worker {
2525*5e7646d2SAndroid Build Coastguard Worker  /*
2526*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2527*5e7646d2SAndroid Build Coastguard Worker   */
2528*5e7646d2SAndroid Build Coastguard Worker 
2529*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
2530*5e7646d2SAndroid Build Coastguard Worker     return (IPP_TAG_ZERO);
2531*5e7646d2SAndroid Build Coastguard Worker 
2532*5e7646d2SAndroid Build Coastguard Worker  /*
2533*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2534*5e7646d2SAndroid Build Coastguard Worker   */
2535*5e7646d2SAndroid Build Coastguard Worker 
2536*5e7646d2SAndroid Build Coastguard Worker   return (attr->value_tag & IPP_TAG_CUPS_MASK);
2537*5e7646d2SAndroid Build Coastguard Worker }
2538*5e7646d2SAndroid Build Coastguard Worker 
2539*5e7646d2SAndroid Build Coastguard Worker 
2540*5e7646d2SAndroid Build Coastguard Worker /*
2541*5e7646d2SAndroid Build Coastguard Worker  * 'ippGetVersion()' - Get the major and minor version number from an IPP message.
2542*5e7646d2SAndroid Build Coastguard Worker  *
2543*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2544*5e7646d2SAndroid Build Coastguard Worker  */
2545*5e7646d2SAndroid Build Coastguard Worker 
2546*5e7646d2SAndroid Build Coastguard Worker int					/* O - Major version number or 0 on error */
ippGetVersion(ipp_t * ipp,int * minor)2547*5e7646d2SAndroid Build Coastguard Worker ippGetVersion(ipp_t *ipp,		/* I - IPP message */
2548*5e7646d2SAndroid Build Coastguard Worker               int   *minor)		/* O - Minor version number or @code NULL@ for don't care */
2549*5e7646d2SAndroid Build Coastguard Worker {
2550*5e7646d2SAndroid Build Coastguard Worker  /*
2551*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2552*5e7646d2SAndroid Build Coastguard Worker   */
2553*5e7646d2SAndroid Build Coastguard Worker 
2554*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
2555*5e7646d2SAndroid Build Coastguard Worker   {
2556*5e7646d2SAndroid Build Coastguard Worker     if (minor)
2557*5e7646d2SAndroid Build Coastguard Worker       *minor = 0;
2558*5e7646d2SAndroid Build Coastguard Worker 
2559*5e7646d2SAndroid Build Coastguard Worker     return (0);
2560*5e7646d2SAndroid Build Coastguard Worker   }
2561*5e7646d2SAndroid Build Coastguard Worker 
2562*5e7646d2SAndroid Build Coastguard Worker  /*
2563*5e7646d2SAndroid Build Coastguard Worker   * Return the value...
2564*5e7646d2SAndroid Build Coastguard Worker   */
2565*5e7646d2SAndroid Build Coastguard Worker 
2566*5e7646d2SAndroid Build Coastguard Worker   if (minor)
2567*5e7646d2SAndroid Build Coastguard Worker     *minor = ipp->request.any.version[1];
2568*5e7646d2SAndroid Build Coastguard Worker 
2569*5e7646d2SAndroid Build Coastguard Worker   return (ipp->request.any.version[0]);
2570*5e7646d2SAndroid Build Coastguard Worker }
2571*5e7646d2SAndroid Build Coastguard Worker 
2572*5e7646d2SAndroid Build Coastguard Worker 
2573*5e7646d2SAndroid Build Coastguard Worker /*
2574*5e7646d2SAndroid Build Coastguard Worker  * 'ippLength()' - Compute the length of an IPP message.
2575*5e7646d2SAndroid Build Coastguard Worker  */
2576*5e7646d2SAndroid Build Coastguard Worker 
2577*5e7646d2SAndroid Build Coastguard Worker size_t					/* O - Size of IPP message */
ippLength(ipp_t * ipp)2578*5e7646d2SAndroid Build Coastguard Worker ippLength(ipp_t *ipp)			/* I - IPP message */
2579*5e7646d2SAndroid Build Coastguard Worker {
2580*5e7646d2SAndroid Build Coastguard Worker   return (ipp_length(ipp, 0));
2581*5e7646d2SAndroid Build Coastguard Worker }
2582*5e7646d2SAndroid Build Coastguard Worker 
2583*5e7646d2SAndroid Build Coastguard Worker 
2584*5e7646d2SAndroid Build Coastguard Worker /*
2585*5e7646d2SAndroid Build Coastguard Worker  * 'ippNextAttribute()' - Return the next attribute in the message.
2586*5e7646d2SAndroid Build Coastguard Worker  *
2587*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
2588*5e7646d2SAndroid Build Coastguard Worker  */
2589*5e7646d2SAndroid Build Coastguard Worker 
2590*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *			/* O - Next attribute or @code NULL@ if none */
ippNextAttribute(ipp_t * ipp)2591*5e7646d2SAndroid Build Coastguard Worker ippNextAttribute(ipp_t *ipp)		/* I - IPP message */
2592*5e7646d2SAndroid Build Coastguard Worker {
2593*5e7646d2SAndroid Build Coastguard Worker  /*
2594*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2595*5e7646d2SAndroid Build Coastguard Worker   */
2596*5e7646d2SAndroid Build Coastguard Worker 
2597*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !ipp->current)
2598*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2599*5e7646d2SAndroid Build Coastguard Worker 
2600*5e7646d2SAndroid Build Coastguard Worker  /*
2601*5e7646d2SAndroid Build Coastguard Worker   * Return the next attribute...
2602*5e7646d2SAndroid Build Coastguard Worker   */
2603*5e7646d2SAndroid Build Coastguard Worker 
2604*5e7646d2SAndroid Build Coastguard Worker   return (ipp->current = ipp->current->next);
2605*5e7646d2SAndroid Build Coastguard Worker }
2606*5e7646d2SAndroid Build Coastguard Worker 
2607*5e7646d2SAndroid Build Coastguard Worker 
2608*5e7646d2SAndroid Build Coastguard Worker /*
2609*5e7646d2SAndroid Build Coastguard Worker  * 'ippNew()' - Allocate a new IPP message.
2610*5e7646d2SAndroid Build Coastguard Worker  */
2611*5e7646d2SAndroid Build Coastguard Worker 
2612*5e7646d2SAndroid Build Coastguard Worker ipp_t *					/* O - New IPP message */
ippNew(void)2613*5e7646d2SAndroid Build Coastguard Worker ippNew(void)
2614*5e7646d2SAndroid Build Coastguard Worker {
2615*5e7646d2SAndroid Build Coastguard Worker   ipp_t			*temp;		/* New IPP message */
2616*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t	*cg = _cupsGlobals();
2617*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
2618*5e7646d2SAndroid Build Coastguard Worker 
2619*5e7646d2SAndroid Build Coastguard Worker 
2620*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("ippNew()");
2621*5e7646d2SAndroid Build Coastguard Worker 
2622*5e7646d2SAndroid Build Coastguard Worker   if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL)
2623*5e7646d2SAndroid Build Coastguard Worker   {
2624*5e7646d2SAndroid Build Coastguard Worker    /*
2625*5e7646d2SAndroid Build Coastguard Worker     * Set default version - usually 2.0...
2626*5e7646d2SAndroid Build Coastguard Worker     */
2627*5e7646d2SAndroid Build Coastguard Worker 
2628*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_alloc: %p IPP message", (void *)temp));
2629*5e7646d2SAndroid Build Coastguard Worker 
2630*5e7646d2SAndroid Build Coastguard Worker     if (cg->server_version == 0)
2631*5e7646d2SAndroid Build Coastguard Worker       _cupsSetDefaults();
2632*5e7646d2SAndroid Build Coastguard Worker 
2633*5e7646d2SAndroid Build Coastguard Worker     temp->request.any.version[0] = (ipp_uchar_t)(cg->server_version / 10);
2634*5e7646d2SAndroid Build Coastguard Worker     temp->request.any.version[1] = (ipp_uchar_t)(cg->server_version % 10);
2635*5e7646d2SAndroid Build Coastguard Worker     temp->use                    = 1;
2636*5e7646d2SAndroid Build Coastguard Worker   }
2637*5e7646d2SAndroid Build Coastguard Worker 
2638*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1ippNew: Returning %p", (void *)temp));
2639*5e7646d2SAndroid Build Coastguard Worker 
2640*5e7646d2SAndroid Build Coastguard Worker   return (temp);
2641*5e7646d2SAndroid Build Coastguard Worker }
2642*5e7646d2SAndroid Build Coastguard Worker 
2643*5e7646d2SAndroid Build Coastguard Worker 
2644*5e7646d2SAndroid Build Coastguard Worker /*
2645*5e7646d2SAndroid Build Coastguard Worker  *  'ippNewRequest()' - Allocate a new IPP request message.
2646*5e7646d2SAndroid Build Coastguard Worker  *
2647*5e7646d2SAndroid Build Coastguard Worker  * The new request message is initialized with the "attributes-charset" and
2648*5e7646d2SAndroid Build Coastguard Worker  * "attributes-natural-language" attributes added. The
2649*5e7646d2SAndroid Build Coastguard Worker  * "attributes-natural-language" value is derived from the current locale.
2650*5e7646d2SAndroid Build Coastguard Worker  *
2651*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
2652*5e7646d2SAndroid Build Coastguard Worker  */
2653*5e7646d2SAndroid Build Coastguard Worker 
2654*5e7646d2SAndroid Build Coastguard Worker ipp_t *					/* O - IPP request message */
ippNewRequest(ipp_op_t op)2655*5e7646d2SAndroid Build Coastguard Worker ippNewRequest(ipp_op_t op)		/* I - Operation code */
2656*5e7646d2SAndroid Build Coastguard Worker {
2657*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* IPP request message */
2658*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t	*language;		/* Current language localization */
2659*5e7646d2SAndroid Build Coastguard Worker   static int	request_id = 0;		/* Current request ID */
2660*5e7646d2SAndroid Build Coastguard Worker   static _cups_mutex_t request_mutex = _CUPS_MUTEX_INITIALIZER;
2661*5e7646d2SAndroid Build Coastguard Worker 					/* Mutex for request ID */
2662*5e7646d2SAndroid Build Coastguard Worker 
2663*5e7646d2SAndroid Build Coastguard Worker 
2664*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op)));
2665*5e7646d2SAndroid Build Coastguard Worker 
2666*5e7646d2SAndroid Build Coastguard Worker  /*
2667*5e7646d2SAndroid Build Coastguard Worker   * Create a new IPP message...
2668*5e7646d2SAndroid Build Coastguard Worker   */
2669*5e7646d2SAndroid Build Coastguard Worker 
2670*5e7646d2SAndroid Build Coastguard Worker   if ((request = ippNew()) == NULL)
2671*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2672*5e7646d2SAndroid Build Coastguard Worker 
2673*5e7646d2SAndroid Build Coastguard Worker  /*
2674*5e7646d2SAndroid Build Coastguard Worker   * Set the operation and request ID...
2675*5e7646d2SAndroid Build Coastguard Worker   */
2676*5e7646d2SAndroid Build Coastguard Worker 
2677*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&request_mutex);
2678*5e7646d2SAndroid Build Coastguard Worker 
2679*5e7646d2SAndroid Build Coastguard Worker   request->request.op.operation_id = op;
2680*5e7646d2SAndroid Build Coastguard Worker   request->request.op.request_id   = ++request_id;
2681*5e7646d2SAndroid Build Coastguard Worker 
2682*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&request_mutex);
2683*5e7646d2SAndroid Build Coastguard Worker 
2684*5e7646d2SAndroid Build Coastguard Worker  /*
2685*5e7646d2SAndroid Build Coastguard Worker   * Use UTF-8 as the character set...
2686*5e7646d2SAndroid Build Coastguard Worker   */
2687*5e7646d2SAndroid Build Coastguard Worker 
2688*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
2689*5e7646d2SAndroid Build Coastguard Worker                "attributes-charset", NULL, "utf-8");
2690*5e7646d2SAndroid Build Coastguard Worker 
2691*5e7646d2SAndroid Build Coastguard Worker  /*
2692*5e7646d2SAndroid Build Coastguard Worker   * Get the language from the current locale...
2693*5e7646d2SAndroid Build Coastguard Worker   */
2694*5e7646d2SAndroid Build Coastguard Worker 
2695*5e7646d2SAndroid Build Coastguard Worker   language = cupsLangDefault();
2696*5e7646d2SAndroid Build Coastguard Worker 
2697*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
2698*5e7646d2SAndroid Build Coastguard Worker                "attributes-natural-language", NULL, language->language);
2699*5e7646d2SAndroid Build Coastguard Worker 
2700*5e7646d2SAndroid Build Coastguard Worker  /*
2701*5e7646d2SAndroid Build Coastguard Worker   * Return the new request...
2702*5e7646d2SAndroid Build Coastguard Worker   */
2703*5e7646d2SAndroid Build Coastguard Worker 
2704*5e7646d2SAndroid Build Coastguard Worker   return (request);
2705*5e7646d2SAndroid Build Coastguard Worker }
2706*5e7646d2SAndroid Build Coastguard Worker 
2707*5e7646d2SAndroid Build Coastguard Worker 
2708*5e7646d2SAndroid Build Coastguard Worker /*
2709*5e7646d2SAndroid Build Coastguard Worker  * 'ippNewResponse()' - Allocate a new IPP response message.
2710*5e7646d2SAndroid Build Coastguard Worker  *
2711*5e7646d2SAndroid Build Coastguard Worker  * The new response message is initialized with the same "version-number",
2712*5e7646d2SAndroid Build Coastguard Worker  * "request-id", "attributes-charset", and "attributes-natural-language" as the
2713*5e7646d2SAndroid Build Coastguard Worker  * provided request message.  If the "attributes-charset" or
2714*5e7646d2SAndroid Build Coastguard Worker  * "attributes-natural-language" attributes are missing from the request,
2715*5e7646d2SAndroid Build Coastguard Worker  * 'utf-8' and a value derived from the current locale are substituted,
2716*5e7646d2SAndroid Build Coastguard Worker  * respectively.
2717*5e7646d2SAndroid Build Coastguard Worker  *
2718*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
2719*5e7646d2SAndroid Build Coastguard Worker  */
2720*5e7646d2SAndroid Build Coastguard Worker 
2721*5e7646d2SAndroid Build Coastguard Worker ipp_t *					/* O - IPP response message */
ippNewResponse(ipp_t * request)2722*5e7646d2SAndroid Build Coastguard Worker ippNewResponse(ipp_t *request)		/* I - IPP request message */
2723*5e7646d2SAndroid Build Coastguard Worker {
2724*5e7646d2SAndroid Build Coastguard Worker   ipp_t			*response;	/* IPP response message */
2725*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
2726*5e7646d2SAndroid Build Coastguard Worker 
2727*5e7646d2SAndroid Build Coastguard Worker 
2728*5e7646d2SAndroid Build Coastguard Worker  /*
2729*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2730*5e7646d2SAndroid Build Coastguard Worker   */
2731*5e7646d2SAndroid Build Coastguard Worker 
2732*5e7646d2SAndroid Build Coastguard Worker   if (!request)
2733*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2734*5e7646d2SAndroid Build Coastguard Worker 
2735*5e7646d2SAndroid Build Coastguard Worker  /*
2736*5e7646d2SAndroid Build Coastguard Worker   * Create a new IPP message...
2737*5e7646d2SAndroid Build Coastguard Worker   */
2738*5e7646d2SAndroid Build Coastguard Worker 
2739*5e7646d2SAndroid Build Coastguard Worker   if ((response = ippNew()) == NULL)
2740*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2741*5e7646d2SAndroid Build Coastguard Worker 
2742*5e7646d2SAndroid Build Coastguard Worker  /*
2743*5e7646d2SAndroid Build Coastguard Worker   * Copy the request values over to the response...
2744*5e7646d2SAndroid Build Coastguard Worker   */
2745*5e7646d2SAndroid Build Coastguard Worker 
2746*5e7646d2SAndroid Build Coastguard Worker   response->request.status.version[0] = request->request.op.version[0];
2747*5e7646d2SAndroid Build Coastguard Worker   response->request.status.version[1] = request->request.op.version[1];
2748*5e7646d2SAndroid Build Coastguard Worker   response->request.status.request_id = request->request.op.request_id;
2749*5e7646d2SAndroid Build Coastguard Worker 
2750*5e7646d2SAndroid Build Coastguard Worker  /*
2751*5e7646d2SAndroid Build Coastguard Worker   * The first attribute MUST be attributes-charset...
2752*5e7646d2SAndroid Build Coastguard Worker   */
2753*5e7646d2SAndroid Build Coastguard Worker 
2754*5e7646d2SAndroid Build Coastguard Worker   attr = request->attrs;
2755*5e7646d2SAndroid Build Coastguard Worker 
2756*5e7646d2SAndroid Build Coastguard Worker   if (attr && attr->name && !strcmp(attr->name, "attributes-charset") &&
2757*5e7646d2SAndroid Build Coastguard Worker       attr->group_tag == IPP_TAG_OPERATION &&
2758*5e7646d2SAndroid Build Coastguard Worker       attr->value_tag == IPP_TAG_CHARSET &&
2759*5e7646d2SAndroid Build Coastguard Worker       attr->num_values == 1)
2760*5e7646d2SAndroid Build Coastguard Worker   {
2761*5e7646d2SAndroid Build Coastguard Worker    /*
2762*5e7646d2SAndroid Build Coastguard Worker     * Copy charset from request...
2763*5e7646d2SAndroid Build Coastguard Worker     */
2764*5e7646d2SAndroid Build Coastguard Worker 
2765*5e7646d2SAndroid Build Coastguard Worker     ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
2766*5e7646d2SAndroid Build Coastguard Worker 		 "attributes-charset", NULL, attr->values[0].string.text);
2767*5e7646d2SAndroid Build Coastguard Worker   }
2768*5e7646d2SAndroid Build Coastguard Worker   else
2769*5e7646d2SAndroid Build Coastguard Worker   {
2770*5e7646d2SAndroid Build Coastguard Worker    /*
2771*5e7646d2SAndroid Build Coastguard Worker     * Use "utf-8" as the default...
2772*5e7646d2SAndroid Build Coastguard Worker     */
2773*5e7646d2SAndroid Build Coastguard Worker 
2774*5e7646d2SAndroid Build Coastguard Worker     ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
2775*5e7646d2SAndroid Build Coastguard Worker 		 "attributes-charset", NULL, "utf-8");
2776*5e7646d2SAndroid Build Coastguard Worker   }
2777*5e7646d2SAndroid Build Coastguard Worker 
2778*5e7646d2SAndroid Build Coastguard Worker  /*
2779*5e7646d2SAndroid Build Coastguard Worker   * Then attributes-natural-language...
2780*5e7646d2SAndroid Build Coastguard Worker   */
2781*5e7646d2SAndroid Build Coastguard Worker 
2782*5e7646d2SAndroid Build Coastguard Worker   if (attr)
2783*5e7646d2SAndroid Build Coastguard Worker     attr = attr->next;
2784*5e7646d2SAndroid Build Coastguard Worker 
2785*5e7646d2SAndroid Build Coastguard Worker   if (attr && attr->name &&
2786*5e7646d2SAndroid Build Coastguard Worker       !strcmp(attr->name, "attributes-natural-language") &&
2787*5e7646d2SAndroid Build Coastguard Worker       attr->group_tag == IPP_TAG_OPERATION &&
2788*5e7646d2SAndroid Build Coastguard Worker       attr->value_tag == IPP_TAG_LANGUAGE &&
2789*5e7646d2SAndroid Build Coastguard Worker       attr->num_values == 1)
2790*5e7646d2SAndroid Build Coastguard Worker   {
2791*5e7646d2SAndroid Build Coastguard Worker    /*
2792*5e7646d2SAndroid Build Coastguard Worker     * Copy language from request...
2793*5e7646d2SAndroid Build Coastguard Worker     */
2794*5e7646d2SAndroid Build Coastguard Worker 
2795*5e7646d2SAndroid Build Coastguard Worker     ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
2796*5e7646d2SAndroid Build Coastguard Worker 		 "attributes-natural-language", NULL,
2797*5e7646d2SAndroid Build Coastguard Worker 		 attr->values[0].string.text);
2798*5e7646d2SAndroid Build Coastguard Worker   }
2799*5e7646d2SAndroid Build Coastguard Worker   else
2800*5e7646d2SAndroid Build Coastguard Worker   {
2801*5e7646d2SAndroid Build Coastguard Worker    /*
2802*5e7646d2SAndroid Build Coastguard Worker     * Use the language from the current locale...
2803*5e7646d2SAndroid Build Coastguard Worker     */
2804*5e7646d2SAndroid Build Coastguard Worker 
2805*5e7646d2SAndroid Build Coastguard Worker     cups_lang_t *language = cupsLangDefault();
2806*5e7646d2SAndroid Build Coastguard Worker 					/* Current locale */
2807*5e7646d2SAndroid Build Coastguard Worker 
2808*5e7646d2SAndroid Build Coastguard Worker     ippAddString(response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
2809*5e7646d2SAndroid Build Coastguard Worker 		 "attributes-natural-language", NULL, language->language);
2810*5e7646d2SAndroid Build Coastguard Worker   }
2811*5e7646d2SAndroid Build Coastguard Worker 
2812*5e7646d2SAndroid Build Coastguard Worker   return (response);
2813*5e7646d2SAndroid Build Coastguard Worker }
2814*5e7646d2SAndroid Build Coastguard Worker 
2815*5e7646d2SAndroid Build Coastguard Worker 
2816*5e7646d2SAndroid Build Coastguard Worker /*
2817*5e7646d2SAndroid Build Coastguard Worker  * 'ippRead()' - Read data for an IPP message from a HTTP connection.
2818*5e7646d2SAndroid Build Coastguard Worker  */
2819*5e7646d2SAndroid Build Coastguard Worker 
2820*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippRead(http_t * http,ipp_t * ipp)2821*5e7646d2SAndroid Build Coastguard Worker ippRead(http_t *http,			/* I - HTTP connection */
2822*5e7646d2SAndroid Build Coastguard Worker         ipp_t  *ipp)			/* I - IPP data */
2823*5e7646d2SAndroid Build Coastguard Worker {
2824*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT, (void *)http, (void *)ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
2825*5e7646d2SAndroid Build Coastguard Worker 
2826*5e7646d2SAndroid Build Coastguard Worker   if (!http)
2827*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
2828*5e7646d2SAndroid Build Coastguard Worker 
2829*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state, http->used));
2830*5e7646d2SAndroid Build Coastguard Worker 
2831*5e7646d2SAndroid Build Coastguard Worker   return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
2832*5e7646d2SAndroid Build Coastguard Worker                     ipp));
2833*5e7646d2SAndroid Build Coastguard Worker }
2834*5e7646d2SAndroid Build Coastguard Worker 
2835*5e7646d2SAndroid Build Coastguard Worker 
2836*5e7646d2SAndroid Build Coastguard Worker /*
2837*5e7646d2SAndroid Build Coastguard Worker  * 'ippReadFile()' - Read data for an IPP message from a file.
2838*5e7646d2SAndroid Build Coastguard Worker  *
2839*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
2840*5e7646d2SAndroid Build Coastguard Worker  */
2841*5e7646d2SAndroid Build Coastguard Worker 
2842*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippReadFile(int fd,ipp_t * ipp)2843*5e7646d2SAndroid Build Coastguard Worker ippReadFile(int   fd,			/* I - HTTP data */
2844*5e7646d2SAndroid Build Coastguard Worker             ipp_t *ipp)			/* I - IPP data */
2845*5e7646d2SAndroid Build Coastguard Worker {
2846*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, (void *)ipp));
2847*5e7646d2SAndroid Build Coastguard Worker 
2848*5e7646d2SAndroid Build Coastguard Worker   return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
2849*5e7646d2SAndroid Build Coastguard Worker }
2850*5e7646d2SAndroid Build Coastguard Worker 
2851*5e7646d2SAndroid Build Coastguard Worker 
2852*5e7646d2SAndroid Build Coastguard Worker /*
2853*5e7646d2SAndroid Build Coastguard Worker  * 'ippReadIO()' - Read data for an IPP message.
2854*5e7646d2SAndroid Build Coastguard Worker  *
2855*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
2856*5e7646d2SAndroid Build Coastguard Worker  */
2857*5e7646d2SAndroid Build Coastguard Worker 
2858*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippReadIO(void * src,ipp_iocb_t cb,int blocking,ipp_t * parent,ipp_t * ipp)2859*5e7646d2SAndroid Build Coastguard Worker ippReadIO(void       *src,		/* I - Data source */
2860*5e7646d2SAndroid Build Coastguard Worker           ipp_iocb_t cb,		/* I - Read callback function */
2861*5e7646d2SAndroid Build Coastguard Worker 	  int        blocking,		/* I - Use blocking IO? */
2862*5e7646d2SAndroid Build Coastguard Worker 	  ipp_t      *parent,		/* I - Parent request, if any */
2863*5e7646d2SAndroid Build Coastguard Worker           ipp_t      *ipp)		/* I - IPP data */
2864*5e7646d2SAndroid Build Coastguard Worker {
2865*5e7646d2SAndroid Build Coastguard Worker   int			n;		/* Length of data */
2866*5e7646d2SAndroid Build Coastguard Worker   unsigned char		*buffer,	/* Data buffer */
2867*5e7646d2SAndroid Build Coastguard Worker 			string[IPP_MAX_TEXT],
2868*5e7646d2SAndroid Build Coastguard Worker 					/* Small string buffer */
2869*5e7646d2SAndroid Build Coastguard Worker 			*bufptr,	/* Pointer into buffer */
2870*5e7646d2SAndroid Build Coastguard Worker 			*bufend;	/* End of buffer */
2871*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr = NULL;	/* Current attribute */
2872*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		tag;		/* Current tag */
2873*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		value_tag;	/* Current value tag */
2874*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
2875*5e7646d2SAndroid Build Coastguard Worker 
2876*5e7646d2SAndroid Build Coastguard Worker 
2877*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", (void *)src, (void *)cb, blocking, (void *)parent, (void *)ipp));
2878*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp ? ipp->state : IPP_STATE_ERROR));
2879*5e7646d2SAndroid Build Coastguard Worker 
2880*5e7646d2SAndroid Build Coastguard Worker   if (!src || !ipp)
2881*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
2882*5e7646d2SAndroid Build Coastguard Worker 
2883*5e7646d2SAndroid Build Coastguard Worker   if ((buffer = (unsigned char *)_cupsBufferGet(IPP_BUF_SIZE)) == NULL)
2884*5e7646d2SAndroid Build Coastguard Worker   {
2885*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1ippReadIO: Unable to get read buffer.");
2886*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
2887*5e7646d2SAndroid Build Coastguard Worker   }
2888*5e7646d2SAndroid Build Coastguard Worker 
2889*5e7646d2SAndroid Build Coastguard Worker   switch (ipp->state)
2890*5e7646d2SAndroid Build Coastguard Worker   {
2891*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_IDLE :
2892*5e7646d2SAndroid Build Coastguard Worker         ipp->state ++; /* Avoid common problem... */
2893*5e7646d2SAndroid Build Coastguard Worker 
2894*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_HEADER :
2895*5e7646d2SAndroid Build Coastguard Worker         if (parent == NULL)
2896*5e7646d2SAndroid Build Coastguard Worker 	{
2897*5e7646d2SAndroid Build Coastguard Worker 	 /*
2898*5e7646d2SAndroid Build Coastguard Worker           * Get the request header...
2899*5e7646d2SAndroid Build Coastguard Worker 	  */
2900*5e7646d2SAndroid Build Coastguard Worker 
2901*5e7646d2SAndroid Build Coastguard Worker           if ((*cb)(src, buffer, 8) < 8)
2902*5e7646d2SAndroid Build Coastguard Worker 	  {
2903*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippReadIO: Unable to read header.");
2904*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
2905*5e7646d2SAndroid Build Coastguard Worker 	  }
2906*5e7646d2SAndroid Build Coastguard Worker 
2907*5e7646d2SAndroid Build Coastguard Worker 	 /*
2908*5e7646d2SAndroid Build Coastguard Worker           * Then copy the request header over...
2909*5e7646d2SAndroid Build Coastguard Worker 	  */
2910*5e7646d2SAndroid Build Coastguard Worker 
2911*5e7646d2SAndroid Build Coastguard Worker           ipp->request.any.version[0]  = buffer[0];
2912*5e7646d2SAndroid Build Coastguard Worker           ipp->request.any.version[1]  = buffer[1];
2913*5e7646d2SAndroid Build Coastguard Worker           ipp->request.any.op_status   = (buffer[2] << 8) | buffer[3];
2914*5e7646d2SAndroid Build Coastguard Worker           ipp->request.any.request_id  = (((((buffer[4] << 8) | buffer[5]) << 8) |
2915*5e7646d2SAndroid Build Coastguard Worker 	                        	 buffer[6]) << 8) | buffer[7];
2916*5e7646d2SAndroid Build Coastguard Worker 
2917*5e7646d2SAndroid Build Coastguard Worker           DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1]));
2918*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippReadIO: op_status=%04x",
2919*5e7646d2SAndroid Build Coastguard Worker 	                ipp->request.any.op_status));
2920*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippReadIO: request_id=%d",
2921*5e7646d2SAndroid Build Coastguard Worker 	                ipp->request.any.request_id));
2922*5e7646d2SAndroid Build Coastguard Worker         }
2923*5e7646d2SAndroid Build Coastguard Worker 
2924*5e7646d2SAndroid Build Coastguard Worker         ipp->state   = IPP_STATE_ATTRIBUTE;
2925*5e7646d2SAndroid Build Coastguard Worker 	ipp->current = NULL;
2926*5e7646d2SAndroid Build Coastguard Worker 	ipp->curtag  = IPP_TAG_ZERO;
2927*5e7646d2SAndroid Build Coastguard Worker 	ipp->prev    = ipp->last;
2928*5e7646d2SAndroid Build Coastguard Worker 
2929*5e7646d2SAndroid Build Coastguard Worker        /*
2930*5e7646d2SAndroid Build Coastguard Worker         * If blocking is disabled, stop here...
2931*5e7646d2SAndroid Build Coastguard Worker 	*/
2932*5e7646d2SAndroid Build Coastguard Worker 
2933*5e7646d2SAndroid Build Coastguard Worker         if (!blocking)
2934*5e7646d2SAndroid Build Coastguard Worker 	  break;
2935*5e7646d2SAndroid Build Coastguard Worker 
2936*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_ATTRIBUTE :
2937*5e7646d2SAndroid Build Coastguard Worker         for (;;)
2938*5e7646d2SAndroid Build Coastguard Worker 	{
2939*5e7646d2SAndroid Build Coastguard Worker 	  if ((*cb)(src, buffer, 1) < 1)
2940*5e7646d2SAndroid Build Coastguard Worker 	  {
2941*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippReadIO: Callback returned EOF/error");
2942*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
2943*5e7646d2SAndroid Build Coastguard Worker 	  }
2944*5e7646d2SAndroid Build Coastguard Worker 
2945*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p", (void *)ipp->current, (void *)ipp->prev));
2946*5e7646d2SAndroid Build Coastguard Worker 
2947*5e7646d2SAndroid Build Coastguard Worker 	 /*
2948*5e7646d2SAndroid Build Coastguard Worker 	  * Read this attribute...
2949*5e7646d2SAndroid Build Coastguard Worker 	  */
2950*5e7646d2SAndroid Build Coastguard Worker 
2951*5e7646d2SAndroid Build Coastguard Worker           tag = (ipp_tag_t)buffer[0];
2952*5e7646d2SAndroid Build Coastguard Worker           if (tag == IPP_TAG_EXTENSION)
2953*5e7646d2SAndroid Build Coastguard Worker           {
2954*5e7646d2SAndroid Build Coastguard Worker            /*
2955*5e7646d2SAndroid Build Coastguard Worker             * Read 32-bit "extension" tag...
2956*5e7646d2SAndroid Build Coastguard Worker             */
2957*5e7646d2SAndroid Build Coastguard Worker 
2958*5e7646d2SAndroid Build Coastguard Worker 	    if ((*cb)(src, buffer, 4) < 4)
2959*5e7646d2SAndroid Build Coastguard Worker 	    {
2960*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: Callback returned EOF/error");
2961*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
2962*5e7646d2SAndroid Build Coastguard Worker 	    }
2963*5e7646d2SAndroid Build Coastguard Worker 
2964*5e7646d2SAndroid Build Coastguard Worker 	    tag = (ipp_tag_t)((((((buffer[0] << 8) | buffer[1]) << 8) |
2965*5e7646d2SAndroid Build Coastguard Worker 	                        buffer[2]) << 8) | buffer[3]);
2966*5e7646d2SAndroid Build Coastguard Worker 
2967*5e7646d2SAndroid Build Coastguard Worker             if (tag & IPP_TAG_CUPS_CONST)
2968*5e7646d2SAndroid Build Coastguard Worker             {
2969*5e7646d2SAndroid Build Coastguard Worker              /*
2970*5e7646d2SAndroid Build Coastguard Worker               * Fail if the high bit is set in the tag...
2971*5e7646d2SAndroid Build Coastguard Worker               */
2972*5e7646d2SAndroid Build Coastguard Worker 
2973*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP extension tag larger than 0x7FFFFFFF."), 1);
2974*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("1ippReadIO: bad tag 0x%x.", tag));
2975*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
2976*5e7646d2SAndroid Build Coastguard Worker             }
2977*5e7646d2SAndroid Build Coastguard Worker           }
2978*5e7646d2SAndroid Build Coastguard Worker 
2979*5e7646d2SAndroid Build Coastguard Worker 	  if (tag == IPP_TAG_END)
2980*5e7646d2SAndroid Build Coastguard Worker 	  {
2981*5e7646d2SAndroid Build Coastguard Worker 	   /*
2982*5e7646d2SAndroid Build Coastguard Worker 	    * No more attributes left...
2983*5e7646d2SAndroid Build Coastguard Worker 	    */
2984*5e7646d2SAndroid Build Coastguard Worker 
2985*5e7646d2SAndroid Build Coastguard Worker             DEBUG_puts("2ippReadIO: IPP_TAG_END.");
2986*5e7646d2SAndroid Build Coastguard Worker 
2987*5e7646d2SAndroid Build Coastguard Worker 	    ipp->state = IPP_STATE_DATA;
2988*5e7646d2SAndroid Build Coastguard Worker 	    break;
2989*5e7646d2SAndroid Build Coastguard Worker 	  }
2990*5e7646d2SAndroid Build Coastguard Worker 	  else if (tag == IPP_TAG_ZERO || (tag == IPP_TAG_OPERATION && ipp->curtag != IPP_TAG_ZERO))
2991*5e7646d2SAndroid Build Coastguard Worker 	  {
2992*5e7646d2SAndroid Build Coastguard Worker 	    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid group tag."), 1);
2993*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("1ippReadIO: bad tag 0x%02x.", tag));
2994*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
2995*5e7646d2SAndroid Build Coastguard Worker 	  }
2996*5e7646d2SAndroid Build Coastguard Worker           else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
2997*5e7646d2SAndroid Build Coastguard Worker 	  {
2998*5e7646d2SAndroid Build Coastguard Worker 	   /*
2999*5e7646d2SAndroid Build Coastguard Worker 	    * Group tag...  Set the current group and continue...
3000*5e7646d2SAndroid Build Coastguard Worker 	    */
3001*5e7646d2SAndroid Build Coastguard Worker 
3002*5e7646d2SAndroid Build Coastguard Worker             if (parent)
3003*5e7646d2SAndroid Build Coastguard Worker             {
3004*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid group tag."), 1);
3005*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("1ippReadIO: bad tag 0x%02x.", tag));
3006*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3007*5e7646d2SAndroid Build Coastguard Worker             }
3008*5e7646d2SAndroid Build Coastguard Worker             else if (ipp->curtag == tag)
3009*5e7646d2SAndroid Build Coastguard Worker 	      ipp->prev = ippAddSeparator(ipp);
3010*5e7646d2SAndroid Build Coastguard Worker             else if (ipp->current)
3011*5e7646d2SAndroid Build Coastguard Worker 	      ipp->prev = ipp->current;
3012*5e7646d2SAndroid Build Coastguard Worker 
3013*5e7646d2SAndroid Build Coastguard Worker 	    ipp->curtag  = tag;
3014*5e7646d2SAndroid Build Coastguard Worker 	    ipp->current = NULL;
3015*5e7646d2SAndroid Build Coastguard Worker 	    attr         = NULL;
3016*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag, ippTagString(tag), (void *)ipp->prev));
3017*5e7646d2SAndroid Build Coastguard Worker 	    continue;
3018*5e7646d2SAndroid Build Coastguard Worker 	  }
3019*5e7646d2SAndroid Build Coastguard Worker 
3020*5e7646d2SAndroid Build Coastguard Worker           DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag,
3021*5e7646d2SAndroid Build Coastguard Worker 	                ippTagString(tag)));
3022*5e7646d2SAndroid Build Coastguard Worker 
3023*5e7646d2SAndroid Build Coastguard Worker          /*
3024*5e7646d2SAndroid Build Coastguard Worker 	  * Get the name...
3025*5e7646d2SAndroid Build Coastguard Worker 	  */
3026*5e7646d2SAndroid Build Coastguard Worker 
3027*5e7646d2SAndroid Build Coastguard Worker           if ((*cb)(src, buffer, 2) < 2)
3028*5e7646d2SAndroid Build Coastguard Worker 	  {
3029*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippReadIO: unable to read name length.");
3030*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
3031*5e7646d2SAndroid Build Coastguard Worker 	  }
3032*5e7646d2SAndroid Build Coastguard Worker 
3033*5e7646d2SAndroid Build Coastguard Worker           n = (buffer[0] << 8) | buffer[1];
3034*5e7646d2SAndroid Build Coastguard Worker 
3035*5e7646d2SAndroid Build Coastguard Worker           if (n >= IPP_BUF_SIZE)
3036*5e7646d2SAndroid Build Coastguard Worker 	  {
3037*5e7646d2SAndroid Build Coastguard Worker 	    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP name larger than 32767 bytes."), 1);
3038*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("1ippReadIO: bad name length %d.", n));
3039*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
3040*5e7646d2SAndroid Build Coastguard Worker 	  }
3041*5e7646d2SAndroid Build Coastguard Worker 
3042*5e7646d2SAndroid Build Coastguard Worker           DEBUG_printf(("2ippReadIO: name length=%d", n));
3043*5e7646d2SAndroid Build Coastguard Worker 
3044*5e7646d2SAndroid Build Coastguard Worker           if (n && parent)
3045*5e7646d2SAndroid Build Coastguard Worker           {
3046*5e7646d2SAndroid Build Coastguard Worker             _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid named IPP attribute in collection."), 1);
3047*5e7646d2SAndroid Build Coastguard Worker             DEBUG_puts("1ippReadIO: bad attribute name in collection.");
3048*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
3049*5e7646d2SAndroid Build Coastguard Worker           }
3050*5e7646d2SAndroid Build Coastguard Worker           else if (n == 0 && tag != IPP_TAG_MEMBERNAME && tag != IPP_TAG_END_COLLECTION)
3051*5e7646d2SAndroid Build Coastguard Worker 	  {
3052*5e7646d2SAndroid Build Coastguard Worker 	   /*
3053*5e7646d2SAndroid Build Coastguard Worker 	    * More values for current attribute...
3054*5e7646d2SAndroid Build Coastguard Worker 	    */
3055*5e7646d2SAndroid Build Coastguard Worker 
3056*5e7646d2SAndroid Build Coastguard Worker             if (ipp->current == NULL)
3057*5e7646d2SAndroid Build Coastguard Worker 	    {
3058*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP attribute has no name."), 1);
3059*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: Attribute without name and no current.");
3060*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3061*5e7646d2SAndroid Build Coastguard Worker 	    }
3062*5e7646d2SAndroid Build Coastguard Worker 
3063*5e7646d2SAndroid Build Coastguard Worker             attr      = ipp->current;
3064*5e7646d2SAndroid Build Coastguard Worker 	    value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_CUPS_MASK);
3065*5e7646d2SAndroid Build Coastguard Worker 
3066*5e7646d2SAndroid Build Coastguard Worker 	   /*
3067*5e7646d2SAndroid Build Coastguard Worker 	    * Make sure we aren't adding a new value of a different
3068*5e7646d2SAndroid Build Coastguard Worker 	    * type...
3069*5e7646d2SAndroid Build Coastguard Worker 	    */
3070*5e7646d2SAndroid Build Coastguard Worker 
3071*5e7646d2SAndroid Build Coastguard Worker 	    if (value_tag == IPP_TAG_ZERO)
3072*5e7646d2SAndroid Build Coastguard Worker 	    {
3073*5e7646d2SAndroid Build Coastguard Worker 	     /*
3074*5e7646d2SAndroid Build Coastguard Worker 	      * Setting the value of a collection member...
3075*5e7646d2SAndroid Build Coastguard Worker 	      */
3076*5e7646d2SAndroid Build Coastguard Worker 
3077*5e7646d2SAndroid Build Coastguard Worker 	      attr->value_tag = tag;
3078*5e7646d2SAndroid Build Coastguard Worker 	    }
3079*5e7646d2SAndroid Build Coastguard Worker 	    else if (value_tag == IPP_TAG_TEXTLANG ||
3080*5e7646d2SAndroid Build Coastguard Worker 	             value_tag == IPP_TAG_NAMELANG ||
3081*5e7646d2SAndroid Build Coastguard Worker 		     (value_tag >= IPP_TAG_TEXT &&
3082*5e7646d2SAndroid Build Coastguard Worker 		      value_tag <= IPP_TAG_MIMETYPE))
3083*5e7646d2SAndroid Build Coastguard Worker             {
3084*5e7646d2SAndroid Build Coastguard Worker 	     /*
3085*5e7646d2SAndroid Build Coastguard Worker 	      * String values can sometimes come across in different
3086*5e7646d2SAndroid Build Coastguard Worker 	      * forms; accept sets of differing values...
3087*5e7646d2SAndroid Build Coastguard Worker 	      */
3088*5e7646d2SAndroid Build Coastguard Worker 
3089*5e7646d2SAndroid Build Coastguard Worker 	      if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG &&
3090*5e7646d2SAndroid Build Coastguard Worker 	          (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) &&
3091*5e7646d2SAndroid Build Coastguard Worker 		  tag != IPP_TAG_NOVALUE)
3092*5e7646d2SAndroid Build Coastguard Worker 	      {
3093*5e7646d2SAndroid Build Coastguard Worker 		_cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3094*5e7646d2SAndroid Build Coastguard Worker 		              _("IPP 1setOf attribute with incompatible value "
3095*5e7646d2SAndroid Build Coastguard Worker 		                "tags."), 1);
3096*5e7646d2SAndroid Build Coastguard Worker 		DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
3097*5e7646d2SAndroid Build Coastguard Worker 			      value_tag, ippTagString(value_tag), tag,
3098*5e7646d2SAndroid Build Coastguard Worker 			      ippTagString(tag)));
3099*5e7646d2SAndroid Build Coastguard Worker 		goto rollback;
3100*5e7646d2SAndroid Build Coastguard Worker 	      }
3101*5e7646d2SAndroid Build Coastguard Worker 
3102*5e7646d2SAndroid Build Coastguard Worker               if (value_tag != tag)
3103*5e7646d2SAndroid Build Coastguard Worker               {
3104*5e7646d2SAndroid Build Coastguard Worker                 DEBUG_printf(("1ippReadIO: Converting %s attribute from %s to %s.",
3105*5e7646d2SAndroid Build Coastguard Worker                               attr->name, ippTagString(value_tag), ippTagString(tag)));
3106*5e7646d2SAndroid Build Coastguard Worker 		ippSetValueTag(ipp, &attr, tag);
3107*5e7646d2SAndroid Build Coastguard Worker 	      }
3108*5e7646d2SAndroid Build Coastguard Worker             }
3109*5e7646d2SAndroid Build Coastguard Worker 	    else if (value_tag == IPP_TAG_INTEGER ||
3110*5e7646d2SAndroid Build Coastguard Worker 	             value_tag == IPP_TAG_RANGE)
3111*5e7646d2SAndroid Build Coastguard Worker             {
3112*5e7646d2SAndroid Build Coastguard Worker 	     /*
3113*5e7646d2SAndroid Build Coastguard Worker 	      * Integer and rangeOfInteger values can sometimes be mixed; accept
3114*5e7646d2SAndroid Build Coastguard Worker 	      * sets of differing values...
3115*5e7646d2SAndroid Build Coastguard Worker 	      */
3116*5e7646d2SAndroid Build Coastguard Worker 
3117*5e7646d2SAndroid Build Coastguard Worker 	      if (tag != IPP_TAG_INTEGER && tag != IPP_TAG_RANGE)
3118*5e7646d2SAndroid Build Coastguard Worker 	      {
3119*5e7646d2SAndroid Build Coastguard Worker 		_cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3120*5e7646d2SAndroid Build Coastguard Worker 		              _("IPP 1setOf attribute with incompatible value "
3121*5e7646d2SAndroid Build Coastguard Worker 		                "tags."), 1);
3122*5e7646d2SAndroid Build Coastguard Worker 		DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
3123*5e7646d2SAndroid Build Coastguard Worker 			      value_tag, ippTagString(value_tag), tag,
3124*5e7646d2SAndroid Build Coastguard Worker 			      ippTagString(tag)));
3125*5e7646d2SAndroid Build Coastguard Worker 		goto rollback;
3126*5e7646d2SAndroid Build Coastguard Worker 	      }
3127*5e7646d2SAndroid Build Coastguard Worker 
3128*5e7646d2SAndroid Build Coastguard Worker               if (value_tag == IPP_TAG_INTEGER && tag == IPP_TAG_RANGE)
3129*5e7646d2SAndroid Build Coastguard Worker               {
3130*5e7646d2SAndroid Build Coastguard Worker                /*
3131*5e7646d2SAndroid Build Coastguard Worker                 * Convert integer values to rangeOfInteger values...
3132*5e7646d2SAndroid Build Coastguard Worker                 */
3133*5e7646d2SAndroid Build Coastguard Worker 
3134*5e7646d2SAndroid Build Coastguard Worker 		DEBUG_printf(("1ippReadIO: Converting %s attribute to "
3135*5e7646d2SAndroid Build Coastguard Worker 		              "rangeOfInteger.", attr->name));
3136*5e7646d2SAndroid Build Coastguard Worker                 ippSetValueTag(ipp, &attr, IPP_TAG_RANGE);
3137*5e7646d2SAndroid Build Coastguard Worker               }
3138*5e7646d2SAndroid Build Coastguard Worker             }
3139*5e7646d2SAndroid Build Coastguard Worker 	    else if (value_tag != tag)
3140*5e7646d2SAndroid Build Coastguard Worker 	    {
3141*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3142*5e7646d2SAndroid Build Coastguard Worker 			    _("IPP 1setOf attribute with incompatible value "
3143*5e7646d2SAndroid Build Coastguard Worker 			      "tags."), 1);
3144*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
3145*5e7646d2SAndroid Build Coastguard Worker 	                    value_tag, ippTagString(value_tag), tag,
3146*5e7646d2SAndroid Build Coastguard Worker 			    ippTagString(tag)));
3147*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3148*5e7646d2SAndroid Build Coastguard Worker             }
3149*5e7646d2SAndroid Build Coastguard Worker 
3150*5e7646d2SAndroid Build Coastguard Worker            /*
3151*5e7646d2SAndroid Build Coastguard Worker 	    * Finally, reallocate the attribute array as needed...
3152*5e7646d2SAndroid Build Coastguard Worker 	    */
3153*5e7646d2SAndroid Build Coastguard Worker 
3154*5e7646d2SAndroid Build Coastguard Worker 	    if ((value = ipp_set_value(ipp, &attr, attr->num_values)) == NULL)
3155*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3156*5e7646d2SAndroid Build Coastguard Worker 	  }
3157*5e7646d2SAndroid Build Coastguard Worker 	  else if (tag == IPP_TAG_MEMBERNAME)
3158*5e7646d2SAndroid Build Coastguard Worker 	  {
3159*5e7646d2SAndroid Build Coastguard Worker 	   /*
3160*5e7646d2SAndroid Build Coastguard Worker 	    * Name must be length 0!
3161*5e7646d2SAndroid Build Coastguard Worker 	    */
3162*5e7646d2SAndroid Build Coastguard Worker 
3163*5e7646d2SAndroid Build Coastguard Worker 	    if (n)
3164*5e7646d2SAndroid Build Coastguard Worker 	    {
3165*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP member name is not empty."), 1);
3166*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: member name not empty.");
3167*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3168*5e7646d2SAndroid Build Coastguard Worker 	    }
3169*5e7646d2SAndroid Build Coastguard Worker 	    else if (!parent)
3170*5e7646d2SAndroid Build Coastguard Worker 	    {
3171*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP member attribute outside of collection."), 1);
3172*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: member attribute outside of collection.");
3173*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3174*5e7646d2SAndroid Build Coastguard Worker 	    }
3175*5e7646d2SAndroid Build Coastguard Worker 
3176*5e7646d2SAndroid Build Coastguard Worker             if (ipp->current)
3177*5e7646d2SAndroid Build Coastguard Worker 	      ipp->prev = ipp->current;
3178*5e7646d2SAndroid Build Coastguard Worker 
3179*5e7646d2SAndroid Build Coastguard Worker 	    attr = ipp->current = ipp_add_attr(ipp, NULL, ipp->curtag, IPP_TAG_ZERO, 1);
3180*5e7646d2SAndroid Build Coastguard Worker 	    if (!attr)
3181*5e7646d2SAndroid Build Coastguard Worker 	    {
3182*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetHTTPError(HTTP_STATUS_ERROR);
3183*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: unable to allocate attribute.");
3184*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3185*5e7646d2SAndroid Build Coastguard Worker 	    }
3186*5e7646d2SAndroid Build Coastguard Worker 
3187*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, ipp->prev=%p", (void *)ipp->current, (void *)ipp->prev));
3188*5e7646d2SAndroid Build Coastguard Worker 
3189*5e7646d2SAndroid Build Coastguard Worker 	    value = attr->values;
3190*5e7646d2SAndroid Build Coastguard Worker 	  }
3191*5e7646d2SAndroid Build Coastguard Worker 	  else if (tag != IPP_TAG_END_COLLECTION)
3192*5e7646d2SAndroid Build Coastguard Worker 	  {
3193*5e7646d2SAndroid Build Coastguard Worker 	   /*
3194*5e7646d2SAndroid Build Coastguard Worker 	    * New attribute; read the name and add it...
3195*5e7646d2SAndroid Build Coastguard Worker 	    */
3196*5e7646d2SAndroid Build Coastguard Worker 
3197*5e7646d2SAndroid Build Coastguard Worker 	    if ((*cb)(src, buffer, (size_t)n) < n)
3198*5e7646d2SAndroid Build Coastguard Worker 	    {
3199*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: unable to read name.");
3200*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3201*5e7646d2SAndroid Build Coastguard Worker 	    }
3202*5e7646d2SAndroid Build Coastguard Worker 
3203*5e7646d2SAndroid Build Coastguard Worker 	    buffer[n] = '\0';
3204*5e7646d2SAndroid Build Coastguard Worker 
3205*5e7646d2SAndroid Build Coastguard Worker             if (ipp->current)
3206*5e7646d2SAndroid Build Coastguard Worker 	      ipp->prev = ipp->current;
3207*5e7646d2SAndroid Build Coastguard Worker 
3208*5e7646d2SAndroid Build Coastguard Worker 	    if ((attr = ipp->current = ipp_add_attr(ipp, (char *)buffer, ipp->curtag, tag,
3209*5e7646d2SAndroid Build Coastguard Worker 	                                            1)) == NULL)
3210*5e7646d2SAndroid Build Coastguard Worker 	    {
3211*5e7646d2SAndroid Build Coastguard Worker 	      _cupsSetHTTPError(HTTP_STATUS_ERROR);
3212*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippReadIO: unable to allocate attribute.");
3213*5e7646d2SAndroid Build Coastguard Worker 	      goto rollback;
3214*5e7646d2SAndroid Build Coastguard Worker 	    }
3215*5e7646d2SAndroid Build Coastguard Worker 
3216*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, ipp->prev=%p", buffer, (void *)ipp->current, (void *)ipp->prev));
3217*5e7646d2SAndroid Build Coastguard Worker 
3218*5e7646d2SAndroid Build Coastguard Worker 	    value = attr->values;
3219*5e7646d2SAndroid Build Coastguard Worker 	  }
3220*5e7646d2SAndroid Build Coastguard Worker 	  else
3221*5e7646d2SAndroid Build Coastguard Worker 	  {
3222*5e7646d2SAndroid Build Coastguard Worker 	    attr  = NULL;
3223*5e7646d2SAndroid Build Coastguard Worker 	    value = NULL;
3224*5e7646d2SAndroid Build Coastguard Worker 	  }
3225*5e7646d2SAndroid Build Coastguard Worker 
3226*5e7646d2SAndroid Build Coastguard Worker 	  if ((*cb)(src, buffer, 2) < 2)
3227*5e7646d2SAndroid Build Coastguard Worker 	  {
3228*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippReadIO: unable to read value length.");
3229*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
3230*5e7646d2SAndroid Build Coastguard Worker 	  }
3231*5e7646d2SAndroid Build Coastguard Worker 
3232*5e7646d2SAndroid Build Coastguard Worker 	  n = (buffer[0] << 8) | buffer[1];
3233*5e7646d2SAndroid Build Coastguard Worker           DEBUG_printf(("2ippReadIO: value length=%d", n));
3234*5e7646d2SAndroid Build Coastguard Worker 
3235*5e7646d2SAndroid Build Coastguard Worker 	  if (n >= IPP_BUF_SIZE)
3236*5e7646d2SAndroid Build Coastguard Worker 	  {
3237*5e7646d2SAndroid Build Coastguard Worker 	    _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3238*5e7646d2SAndroid Build Coastguard Worker 			  _("IPP value larger than 32767 bytes."), 1);
3239*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("1ippReadIO: bad value length %d.", n));
3240*5e7646d2SAndroid Build Coastguard Worker 	    goto rollback;
3241*5e7646d2SAndroid Build Coastguard Worker 	  }
3242*5e7646d2SAndroid Build Coastguard Worker 
3243*5e7646d2SAndroid Build Coastguard Worker 	  switch (tag)
3244*5e7646d2SAndroid Build Coastguard Worker 	  {
3245*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_INTEGER :
3246*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ENUM :
3247*5e7646d2SAndroid Build Coastguard Worker 		if (n != 4)
3248*5e7646d2SAndroid Build Coastguard Worker 		{
3249*5e7646d2SAndroid Build Coastguard Worker 		  if (tag == IPP_TAG_INTEGER)
3250*5e7646d2SAndroid Build Coastguard Worker 		    _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3251*5e7646d2SAndroid Build Coastguard Worker 				  _("IPP integer value not 4 bytes."), 1);
3252*5e7646d2SAndroid Build Coastguard Worker 		  else
3253*5e7646d2SAndroid Build Coastguard Worker 		    _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3254*5e7646d2SAndroid Build Coastguard Worker 				  _("IPP enum value not 4 bytes."), 1);
3255*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad integer value length %d.", n));
3256*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3257*5e7646d2SAndroid Build Coastguard Worker 		}
3258*5e7646d2SAndroid Build Coastguard Worker 
3259*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, buffer, 4) < 4)
3260*5e7646d2SAndroid Build Coastguard Worker 		{
3261*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read integer value.");
3262*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3263*5e7646d2SAndroid Build Coastguard Worker 		}
3264*5e7646d2SAndroid Build Coastguard Worker 
3265*5e7646d2SAndroid Build Coastguard Worker 		n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
3266*5e7646d2SAndroid Build Coastguard Worker 		    buffer[3];
3267*5e7646d2SAndroid Build Coastguard Worker 
3268*5e7646d2SAndroid Build Coastguard Worker                 if (attr->value_tag == IPP_TAG_RANGE)
3269*5e7646d2SAndroid Build Coastguard Worker                   value->range.lower = value->range.upper = n;
3270*5e7646d2SAndroid Build Coastguard Worker                 else
3271*5e7646d2SAndroid Build Coastguard Worker 		  value->integer = n;
3272*5e7646d2SAndroid Build Coastguard Worker 	        break;
3273*5e7646d2SAndroid Build Coastguard Worker 
3274*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_BOOLEAN :
3275*5e7646d2SAndroid Build Coastguard Worker 		if (n != 1)
3276*5e7646d2SAndroid Build Coastguard Worker 		{
3277*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP boolean value not 1 byte."),
3278*5e7646d2SAndroid Build Coastguard Worker 		                1);
3279*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad boolean value length %d.", n));
3280*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3281*5e7646d2SAndroid Build Coastguard Worker 		}
3282*5e7646d2SAndroid Build Coastguard Worker 
3283*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, buffer, 1) < 1)
3284*5e7646d2SAndroid Build Coastguard Worker 		{
3285*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read boolean value.");
3286*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3287*5e7646d2SAndroid Build Coastguard Worker 		}
3288*5e7646d2SAndroid Build Coastguard Worker 
3289*5e7646d2SAndroid Build Coastguard Worker                 value->boolean = (char)buffer[0];
3290*5e7646d2SAndroid Build Coastguard Worker 	        break;
3291*5e7646d2SAndroid Build Coastguard Worker 
3292*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_UNSUPPORTED_VALUE :
3293*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DEFAULT :
3294*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_UNKNOWN :
3295*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NOVALUE :
3296*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NOTSETTABLE :
3297*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DELETEATTR :
3298*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ADMINDEFINE :
3299*5e7646d2SAndroid Build Coastguard Worker 	       /*
3300*5e7646d2SAndroid Build Coastguard Worker 	        * These value types are not supposed to have values, however
3301*5e7646d2SAndroid Build Coastguard Worker 		* some vendors (Brother) do not implement IPP correctly and so
3302*5e7646d2SAndroid Build Coastguard Worker 		* we need to map non-empty values to text...
3303*5e7646d2SAndroid Build Coastguard Worker 		*/
3304*5e7646d2SAndroid Build Coastguard Worker 
3305*5e7646d2SAndroid Build Coastguard Worker 	        if (attr->value_tag == tag)
3306*5e7646d2SAndroid Build Coastguard Worker 		{
3307*5e7646d2SAndroid Build Coastguard Worker 		  if (n == 0)
3308*5e7646d2SAndroid Build Coastguard Worker 		    break;
3309*5e7646d2SAndroid Build Coastguard Worker 
3310*5e7646d2SAndroid Build Coastguard Worker 		  attr->value_tag = IPP_TAG_TEXT;
3311*5e7646d2SAndroid Build Coastguard Worker 		}
3312*5e7646d2SAndroid Build Coastguard Worker 
3313*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXT :
3314*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAME :
3315*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_RESERVED_STRING :
3316*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_KEYWORD :
3317*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URI :
3318*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URISCHEME :
3319*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_CHARSET :
3320*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_LANGUAGE :
3321*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_MIMETYPE :
3322*5e7646d2SAndroid Build Coastguard Worker 	        if (n > 0)
3323*5e7646d2SAndroid Build Coastguard Worker 	        {
3324*5e7646d2SAndroid Build Coastguard Worker 		  if ((*cb)(src, buffer, (size_t)n) < n)
3325*5e7646d2SAndroid Build Coastguard Worker 		  {
3326*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_puts("1ippReadIO: unable to read string value.");
3327*5e7646d2SAndroid Build Coastguard Worker 		    goto rollback;
3328*5e7646d2SAndroid Build Coastguard Worker 		  }
3329*5e7646d2SAndroid Build Coastguard Worker 		}
3330*5e7646d2SAndroid Build Coastguard Worker 
3331*5e7646d2SAndroid Build Coastguard Worker 		buffer[n] = '\0';
3332*5e7646d2SAndroid Build Coastguard Worker 		value->string.text = _cupsStrAlloc((char *)buffer);
3333*5e7646d2SAndroid Build Coastguard Worker 		DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text));
3334*5e7646d2SAndroid Build Coastguard Worker 	        break;
3335*5e7646d2SAndroid Build Coastguard Worker 
3336*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DATE :
3337*5e7646d2SAndroid Build Coastguard Worker 		if (n != 11)
3338*5e7646d2SAndroid Build Coastguard Worker 		{
3339*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("IPP date value not 11 bytes."), 1);
3340*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad date value length %d.", n));
3341*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3342*5e7646d2SAndroid Build Coastguard Worker 		}
3343*5e7646d2SAndroid Build Coastguard Worker 
3344*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, value->date, 11) < 11)
3345*5e7646d2SAndroid Build Coastguard Worker 		{
3346*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read date value.");
3347*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3348*5e7646d2SAndroid Build Coastguard Worker 		}
3349*5e7646d2SAndroid Build Coastguard Worker 	        break;
3350*5e7646d2SAndroid Build Coastguard Worker 
3351*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_RESOLUTION :
3352*5e7646d2SAndroid Build Coastguard Worker 		if (n != 9)
3353*5e7646d2SAndroid Build Coastguard Worker 		{
3354*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3355*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP resolution value not 9 bytes."), 1);
3356*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad resolution value length %d.", n));
3357*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3358*5e7646d2SAndroid Build Coastguard Worker 		}
3359*5e7646d2SAndroid Build Coastguard Worker 
3360*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, buffer, 9) < 9)
3361*5e7646d2SAndroid Build Coastguard Worker 		{
3362*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read resolution value.");
3363*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3364*5e7646d2SAndroid Build Coastguard Worker 		}
3365*5e7646d2SAndroid Build Coastguard Worker 
3366*5e7646d2SAndroid Build Coastguard Worker                 value->resolution.xres =
3367*5e7646d2SAndroid Build Coastguard Worker 		    (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
3368*5e7646d2SAndroid Build Coastguard Worker 		    buffer[3];
3369*5e7646d2SAndroid Build Coastguard Worker                 value->resolution.yres =
3370*5e7646d2SAndroid Build Coastguard Worker 		    (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
3371*5e7646d2SAndroid Build Coastguard Worker 		    buffer[7];
3372*5e7646d2SAndroid Build Coastguard Worker                 value->resolution.units =
3373*5e7646d2SAndroid Build Coastguard Worker 		    (ipp_res_t)buffer[8];
3374*5e7646d2SAndroid Build Coastguard Worker 	        break;
3375*5e7646d2SAndroid Build Coastguard Worker 
3376*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_RANGE :
3377*5e7646d2SAndroid Build Coastguard Worker 		if (n != 8)
3378*5e7646d2SAndroid Build Coastguard Worker 		{
3379*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3380*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP rangeOfInteger value not 8 bytes."), 1);
3381*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad rangeOfInteger value length "
3382*5e7646d2SAndroid Build Coastguard Worker 		                "%d.", n));
3383*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3384*5e7646d2SAndroid Build Coastguard Worker 		}
3385*5e7646d2SAndroid Build Coastguard Worker 
3386*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, buffer, 8) < 8)
3387*5e7646d2SAndroid Build Coastguard Worker 		{
3388*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read range value.");
3389*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3390*5e7646d2SAndroid Build Coastguard Worker 		}
3391*5e7646d2SAndroid Build Coastguard Worker 
3392*5e7646d2SAndroid Build Coastguard Worker                 value->range.lower =
3393*5e7646d2SAndroid Build Coastguard Worker 		    (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
3394*5e7646d2SAndroid Build Coastguard Worker 		    buffer[3];
3395*5e7646d2SAndroid Build Coastguard Worker                 value->range.upper =
3396*5e7646d2SAndroid Build Coastguard Worker 		    (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
3397*5e7646d2SAndroid Build Coastguard Worker 		    buffer[7];
3398*5e7646d2SAndroid Build Coastguard Worker 	        break;
3399*5e7646d2SAndroid Build Coastguard Worker 
3400*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXTLANG :
3401*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAMELANG :
3402*5e7646d2SAndroid Build Coastguard Worker 	        if (n < 4)
3403*5e7646d2SAndroid Build Coastguard Worker 		{
3404*5e7646d2SAndroid Build Coastguard Worker 		  if (tag == IPP_TAG_TEXTLANG)
3405*5e7646d2SAndroid Build Coastguard Worker 		    _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3406*5e7646d2SAndroid Build Coastguard Worker 		                  _("IPP textWithLanguage value less than "
3407*5e7646d2SAndroid Build Coastguard Worker 		                    "minimum 4 bytes."), 1);
3408*5e7646d2SAndroid Build Coastguard Worker 		  else
3409*5e7646d2SAndroid Build Coastguard Worker 		    _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3410*5e7646d2SAndroid Build Coastguard Worker 		                  _("IPP nameWithLanguage value less than "
3411*5e7646d2SAndroid Build Coastguard Worker 		                    "minimum 4 bytes."), 1);
3412*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad stringWithLanguage value "
3413*5e7646d2SAndroid Build Coastguard Worker 		                "length %d.", n));
3414*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3415*5e7646d2SAndroid Build Coastguard Worker 		}
3416*5e7646d2SAndroid Build Coastguard Worker 
3417*5e7646d2SAndroid Build Coastguard Worker 	        if ((*cb)(src, buffer, (size_t)n) < n)
3418*5e7646d2SAndroid Build Coastguard Worker 		{
3419*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read string w/language "
3420*5e7646d2SAndroid Build Coastguard Worker 		             "value.");
3421*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3422*5e7646d2SAndroid Build Coastguard Worker 		}
3423*5e7646d2SAndroid Build Coastguard Worker 
3424*5e7646d2SAndroid Build Coastguard Worker                 bufptr = buffer;
3425*5e7646d2SAndroid Build Coastguard Worker                 bufend = buffer + n;
3426*5e7646d2SAndroid Build Coastguard Worker 
3427*5e7646d2SAndroid Build Coastguard Worker 	       /*
3428*5e7646d2SAndroid Build Coastguard Worker 	        * text-with-language and name-with-language are composite
3429*5e7646d2SAndroid Build Coastguard Worker 		* values:
3430*5e7646d2SAndroid Build Coastguard Worker 		*
3431*5e7646d2SAndroid Build Coastguard Worker 		*    language-length
3432*5e7646d2SAndroid Build Coastguard Worker 		*    language
3433*5e7646d2SAndroid Build Coastguard Worker 		*    text-length
3434*5e7646d2SAndroid Build Coastguard Worker 		*    text
3435*5e7646d2SAndroid Build Coastguard Worker 		*/
3436*5e7646d2SAndroid Build Coastguard Worker 
3437*5e7646d2SAndroid Build Coastguard Worker 		n = (bufptr[0] << 8) | bufptr[1];
3438*5e7646d2SAndroid Build Coastguard Worker 
3439*5e7646d2SAndroid Build Coastguard Worker 		if ((bufptr + 2 + n + 2) > bufend || n >= (int)sizeof(string))
3440*5e7646d2SAndroid Build Coastguard Worker 		{
3441*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3442*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP language length overflows value."), 1);
3443*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad language value length %d.",
3444*5e7646d2SAndroid Build Coastguard Worker 		                n));
3445*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3446*5e7646d2SAndroid Build Coastguard Worker 		}
3447*5e7646d2SAndroid Build Coastguard Worker 		else if (n >= IPP_MAX_LANGUAGE)
3448*5e7646d2SAndroid Build Coastguard Worker 		{
3449*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3450*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP language length too large."), 1);
3451*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad language value length %d.",
3452*5e7646d2SAndroid Build Coastguard Worker 		                n));
3453*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3454*5e7646d2SAndroid Build Coastguard Worker 		}
3455*5e7646d2SAndroid Build Coastguard Worker 
3456*5e7646d2SAndroid Build Coastguard Worker 		memcpy(string, bufptr + 2, (size_t)n);
3457*5e7646d2SAndroid Build Coastguard Worker 		string[n] = '\0';
3458*5e7646d2SAndroid Build Coastguard Worker 
3459*5e7646d2SAndroid Build Coastguard Worker 		value->string.language = _cupsStrAlloc((char *)string);
3460*5e7646d2SAndroid Build Coastguard Worker 
3461*5e7646d2SAndroid Build Coastguard Worker                 bufptr += 2 + n;
3462*5e7646d2SAndroid Build Coastguard Worker 		n = (bufptr[0] << 8) | bufptr[1];
3463*5e7646d2SAndroid Build Coastguard Worker 
3464*5e7646d2SAndroid Build Coastguard Worker 		if ((bufptr + 2 + n) > bufend)
3465*5e7646d2SAndroid Build Coastguard Worker 		{
3466*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3467*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP string length overflows value."), 1);
3468*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad string value length %d.", n));
3469*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3470*5e7646d2SAndroid Build Coastguard Worker 		}
3471*5e7646d2SAndroid Build Coastguard Worker 
3472*5e7646d2SAndroid Build Coastguard Worker 		bufptr[2 + n] = '\0';
3473*5e7646d2SAndroid Build Coastguard Worker                 value->string.text = _cupsStrAlloc((char *)bufptr + 2);
3474*5e7646d2SAndroid Build Coastguard Worker 	        break;
3475*5e7646d2SAndroid Build Coastguard Worker 
3476*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_BEGIN_COLLECTION :
3477*5e7646d2SAndroid Build Coastguard Worker 	       /*
3478*5e7646d2SAndroid Build Coastguard Worker 	        * Oh, boy, here comes a collection value, so read it...
3479*5e7646d2SAndroid Build Coastguard Worker 		*/
3480*5e7646d2SAndroid Build Coastguard Worker 
3481*5e7646d2SAndroid Build Coastguard Worker                 value->collection = ippNew();
3482*5e7646d2SAndroid Build Coastguard Worker 
3483*5e7646d2SAndroid Build Coastguard Worker                 if (n > 0)
3484*5e7646d2SAndroid Build Coastguard Worker 		{
3485*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3486*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP begCollection value not 0 bytes."), 1);
3487*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: begCollection tag with value length "
3488*5e7646d2SAndroid Build Coastguard Worker 		             "> 0.");
3489*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3490*5e7646d2SAndroid Build Coastguard Worker 		}
3491*5e7646d2SAndroid Build Coastguard Worker 
3492*5e7646d2SAndroid Build Coastguard Worker 		if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_STATE_ERROR)
3493*5e7646d2SAndroid Build Coastguard Worker 		{
3494*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read collection value.");
3495*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3496*5e7646d2SAndroid Build Coastguard Worker 		}
3497*5e7646d2SAndroid Build Coastguard Worker                 break;
3498*5e7646d2SAndroid Build Coastguard Worker 
3499*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_END_COLLECTION :
3500*5e7646d2SAndroid Build Coastguard Worker                 if (n > 0)
3501*5e7646d2SAndroid Build Coastguard Worker 		{
3502*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3503*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP endCollection value not 0 bytes."), 1);
3504*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: endCollection tag with value length "
3505*5e7646d2SAndroid Build Coastguard Worker 		             "> 0.");
3506*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3507*5e7646d2SAndroid Build Coastguard Worker 		}
3508*5e7646d2SAndroid Build Coastguard Worker 
3509*5e7646d2SAndroid Build Coastguard Worker 		_cupsBufferRelease((char *)buffer);
3510*5e7646d2SAndroid Build Coastguard Worker 
3511*5e7646d2SAndroid Build Coastguard Worker 	        DEBUG_puts("1ippReadIO: endCollection tag...");
3512*5e7646d2SAndroid Build Coastguard Worker 		return (ipp->state = IPP_STATE_DATA);
3513*5e7646d2SAndroid Build Coastguard Worker 
3514*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_MEMBERNAME :
3515*5e7646d2SAndroid Build Coastguard Worker 	       /*
3516*5e7646d2SAndroid Build Coastguard Worker 	        * The value the name of the member in the collection, which
3517*5e7646d2SAndroid Build Coastguard Worker 		* we need to carry over...
3518*5e7646d2SAndroid Build Coastguard Worker 		*/
3519*5e7646d2SAndroid Build Coastguard Worker 
3520*5e7646d2SAndroid Build Coastguard Worker                 if (!attr)
3521*5e7646d2SAndroid Build Coastguard Worker                 {
3522*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3523*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP memberName with no attribute."), 1);
3524*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Member name without attribute.");
3525*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3526*5e7646d2SAndroid Build Coastguard Worker                 }
3527*5e7646d2SAndroid Build Coastguard Worker 		else if (n == 0)
3528*5e7646d2SAndroid Build Coastguard Worker 		{
3529*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3530*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP memberName value is empty."), 1);
3531*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Empty member name value.");
3532*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3533*5e7646d2SAndroid Build Coastguard Worker 		}
3534*5e7646d2SAndroid Build Coastguard Worker 		else if ((*cb)(src, buffer, (size_t)n) < n)
3535*5e7646d2SAndroid Build Coastguard Worker 		{
3536*5e7646d2SAndroid Build Coastguard Worker 	          DEBUG_puts("1ippReadIO: Unable to read member name value.");
3537*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3538*5e7646d2SAndroid Build Coastguard Worker 		}
3539*5e7646d2SAndroid Build Coastguard Worker 
3540*5e7646d2SAndroid Build Coastguard Worker 		buffer[n] = '\0';
3541*5e7646d2SAndroid Build Coastguard Worker 		attr->name = _cupsStrAlloc((char *)buffer);
3542*5e7646d2SAndroid Build Coastguard Worker 
3543*5e7646d2SAndroid Build Coastguard Worker                /*
3544*5e7646d2SAndroid Build Coastguard Worker 	        * Since collection members are encoded differently than
3545*5e7646d2SAndroid Build Coastguard Worker 		* regular attributes, make sure we don't start with an
3546*5e7646d2SAndroid Build Coastguard Worker 		* empty value...
3547*5e7646d2SAndroid Build Coastguard Worker 		*/
3548*5e7646d2SAndroid Build Coastguard Worker 
3549*5e7646d2SAndroid Build Coastguard Worker                 attr->num_values --;
3550*5e7646d2SAndroid Build Coastguard Worker 
3551*5e7646d2SAndroid Build Coastguard Worker 		DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name));
3552*5e7646d2SAndroid Build Coastguard Worker 		break;
3553*5e7646d2SAndroid Build Coastguard Worker 
3554*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_STRING :
3555*5e7646d2SAndroid Build Coastguard Worker             default : /* Other unsupported values */
3556*5e7646d2SAndroid Build Coastguard Worker                 if (tag == IPP_TAG_STRING && n > IPP_MAX_LENGTH)
3557*5e7646d2SAndroid Build Coastguard Worker 		{
3558*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
3559*5e7646d2SAndroid Build Coastguard Worker 		                _("IPP octetString length too large."), 1);
3560*5e7646d2SAndroid Build Coastguard Worker 		  DEBUG_printf(("1ippReadIO: bad octetString value length %d.",
3561*5e7646d2SAndroid Build Coastguard Worker 		                n));
3562*5e7646d2SAndroid Build Coastguard Worker 		  goto rollback;
3563*5e7646d2SAndroid Build Coastguard Worker 		}
3564*5e7646d2SAndroid Build Coastguard Worker 
3565*5e7646d2SAndroid Build Coastguard Worker                 value->unknown.length = n;
3566*5e7646d2SAndroid Build Coastguard Worker 
3567*5e7646d2SAndroid Build Coastguard Worker 	        if (n > 0)
3568*5e7646d2SAndroid Build Coastguard Worker 		{
3569*5e7646d2SAndroid Build Coastguard Worker 		  if ((value->unknown.data = malloc((size_t)n)) == NULL)
3570*5e7646d2SAndroid Build Coastguard Worker 		  {
3571*5e7646d2SAndroid Build Coastguard Worker 		    _cupsSetHTTPError(HTTP_STATUS_ERROR);
3572*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_puts("1ippReadIO: Unable to allocate value");
3573*5e7646d2SAndroid Build Coastguard Worker 		    goto rollback;
3574*5e7646d2SAndroid Build Coastguard Worker 		  }
3575*5e7646d2SAndroid Build Coastguard Worker 
3576*5e7646d2SAndroid Build Coastguard Worker 	          if ((*cb)(src, value->unknown.data, (size_t)n) < n)
3577*5e7646d2SAndroid Build Coastguard Worker 		  {
3578*5e7646d2SAndroid Build Coastguard Worker 	            DEBUG_puts("1ippReadIO: Unable to read unsupported value.");
3579*5e7646d2SAndroid Build Coastguard Worker 		    goto rollback;
3580*5e7646d2SAndroid Build Coastguard Worker 		  }
3581*5e7646d2SAndroid Build Coastguard Worker 		}
3582*5e7646d2SAndroid Build Coastguard Worker 		else
3583*5e7646d2SAndroid Build Coastguard Worker 		  value->unknown.data = NULL;
3584*5e7646d2SAndroid Build Coastguard Worker 	        break;
3585*5e7646d2SAndroid Build Coastguard Worker 	  }
3586*5e7646d2SAndroid Build Coastguard Worker 
3587*5e7646d2SAndroid Build Coastguard Worker 	 /*
3588*5e7646d2SAndroid Build Coastguard Worker           * If blocking is disabled, stop here...
3589*5e7646d2SAndroid Build Coastguard Worker 	  */
3590*5e7646d2SAndroid Build Coastguard Worker 
3591*5e7646d2SAndroid Build Coastguard Worker           if (!blocking)
3592*5e7646d2SAndroid Build Coastguard Worker 	    break;
3593*5e7646d2SAndroid Build Coastguard Worker 	}
3594*5e7646d2SAndroid Build Coastguard Worker         break;
3595*5e7646d2SAndroid Build Coastguard Worker 
3596*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_DATA :
3597*5e7646d2SAndroid Build Coastguard Worker         break;
3598*5e7646d2SAndroid Build Coastguard Worker 
3599*5e7646d2SAndroid Build Coastguard Worker     default :
3600*5e7646d2SAndroid Build Coastguard Worker         break; /* anti-compiler-warning-code */
3601*5e7646d2SAndroid Build Coastguard Worker   }
3602*5e7646d2SAndroid Build Coastguard Worker 
3603*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp->state));
3604*5e7646d2SAndroid Build Coastguard Worker   _cupsBufferRelease((char *)buffer);
3605*5e7646d2SAndroid Build Coastguard Worker 
3606*5e7646d2SAndroid Build Coastguard Worker   return (ipp->state);
3607*5e7646d2SAndroid Build Coastguard Worker 
3608*5e7646d2SAndroid Build Coastguard Worker   // If we get here, there was an error that required us to roll back the last
3609*5e7646d2SAndroid Build Coastguard Worker   // attribute read in order to keep the IPP message valid...
3610*5e7646d2SAndroid Build Coastguard Worker   rollback:
3611*5e7646d2SAndroid Build Coastguard Worker 
3612*5e7646d2SAndroid Build Coastguard Worker   _cupsBufferRelease((char *)buffer);
3613*5e7646d2SAndroid Build Coastguard Worker 
3614*5e7646d2SAndroid Build Coastguard Worker   if (attr)
3615*5e7646d2SAndroid Build Coastguard Worker     ippDeleteAttribute(ipp, attr);
3616*5e7646d2SAndroid Build Coastguard Worker 
3617*5e7646d2SAndroid Build Coastguard Worker   return (IPP_STATE_ERROR);
3618*5e7646d2SAndroid Build Coastguard Worker }
3619*5e7646d2SAndroid Build Coastguard Worker 
3620*5e7646d2SAndroid Build Coastguard Worker 
3621*5e7646d2SAndroid Build Coastguard Worker /*
3622*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetBoolean()' - Set a boolean value in an attribute.
3623*5e7646d2SAndroid Build Coastguard Worker  *
3624*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3625*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3626*5e7646d2SAndroid Build Coastguard Worker  *
3627*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3628*5e7646d2SAndroid Build Coastguard Worker  *
3629*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
3630*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
3631*5e7646d2SAndroid Build Coastguard Worker  *
3632*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3633*5e7646d2SAndroid Build Coastguard Worker  */
3634*5e7646d2SAndroid Build Coastguard Worker 
3635*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetBoolean(ipp_t * ipp,ipp_attribute_t ** attr,int element,int boolvalue)3636*5e7646d2SAndroid Build Coastguard Worker ippSetBoolean(ipp_t           *ipp,	/* I  - IPP message */
3637*5e7646d2SAndroid Build Coastguard Worker               ipp_attribute_t **attr,	/* IO - IPP attribute */
3638*5e7646d2SAndroid Build Coastguard Worker               int             element,	/* I  - Value number (0-based) */
3639*5e7646d2SAndroid Build Coastguard Worker               int             boolvalue)/* I  - Boolean value */
3640*5e7646d2SAndroid Build Coastguard Worker {
3641*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
3642*5e7646d2SAndroid Build Coastguard Worker 
3643*5e7646d2SAndroid Build Coastguard Worker 
3644*5e7646d2SAndroid Build Coastguard Worker  /*
3645*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3646*5e7646d2SAndroid Build Coastguard Worker   */
3647*5e7646d2SAndroid Build Coastguard Worker 
3648*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BOOLEAN ||
3649*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element > (*attr)->num_values)
3650*5e7646d2SAndroid Build Coastguard Worker     return (0);
3651*5e7646d2SAndroid Build Coastguard Worker 
3652*5e7646d2SAndroid Build Coastguard Worker  /*
3653*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3654*5e7646d2SAndroid Build Coastguard Worker   */
3655*5e7646d2SAndroid Build Coastguard Worker 
3656*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
3657*5e7646d2SAndroid Build Coastguard Worker     value->boolean = (char)boolvalue;
3658*5e7646d2SAndroid Build Coastguard Worker 
3659*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
3660*5e7646d2SAndroid Build Coastguard Worker }
3661*5e7646d2SAndroid Build Coastguard Worker 
3662*5e7646d2SAndroid Build Coastguard Worker 
3663*5e7646d2SAndroid Build Coastguard Worker /*
3664*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetCollection()' - Set a collection value in an attribute.
3665*5e7646d2SAndroid Build Coastguard Worker  *
3666*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3667*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3668*5e7646d2SAndroid Build Coastguard Worker  *
3669*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3670*5e7646d2SAndroid Build Coastguard Worker  *
3671*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
3672*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
3673*5e7646d2SAndroid Build Coastguard Worker  *
3674*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3675*5e7646d2SAndroid Build Coastguard Worker  */
3676*5e7646d2SAndroid Build Coastguard Worker 
3677*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetCollection(ipp_t * ipp,ipp_attribute_t ** attr,int element,ipp_t * colvalue)3678*5e7646d2SAndroid Build Coastguard Worker ippSetCollection(
3679*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I  - IPP message */
3680*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - IPP attribute */
3681*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I  - Value number (0-based) */
3682*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *colvalue)		/* I  - Collection value */
3683*5e7646d2SAndroid Build Coastguard Worker {
3684*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
3685*5e7646d2SAndroid Build Coastguard Worker 
3686*5e7646d2SAndroid Build Coastguard Worker 
3687*5e7646d2SAndroid Build Coastguard Worker  /*
3688*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3689*5e7646d2SAndroid Build Coastguard Worker   */
3690*5e7646d2SAndroid Build Coastguard Worker 
3691*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BEGIN_COLLECTION ||
3692*5e7646d2SAndroid Build Coastguard Worker       element < 0 || element > (*attr)->num_values || !colvalue)
3693*5e7646d2SAndroid Build Coastguard Worker     return (0);
3694*5e7646d2SAndroid Build Coastguard Worker 
3695*5e7646d2SAndroid Build Coastguard Worker  /*
3696*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3697*5e7646d2SAndroid Build Coastguard Worker   */
3698*5e7646d2SAndroid Build Coastguard Worker 
3699*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
3700*5e7646d2SAndroid Build Coastguard Worker   {
3701*5e7646d2SAndroid Build Coastguard Worker     if (value->collection)
3702*5e7646d2SAndroid Build Coastguard Worker       ippDelete(value->collection);
3703*5e7646d2SAndroid Build Coastguard Worker 
3704*5e7646d2SAndroid Build Coastguard Worker     value->collection = colvalue;
3705*5e7646d2SAndroid Build Coastguard Worker     colvalue->use ++;
3706*5e7646d2SAndroid Build Coastguard Worker   }
3707*5e7646d2SAndroid Build Coastguard Worker 
3708*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
3709*5e7646d2SAndroid Build Coastguard Worker }
3710*5e7646d2SAndroid Build Coastguard Worker 
3711*5e7646d2SAndroid Build Coastguard Worker 
3712*5e7646d2SAndroid Build Coastguard Worker /*
3713*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetDate()' - Set a dateTime value in an attribute.
3714*5e7646d2SAndroid Build Coastguard Worker  *
3715*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3716*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3717*5e7646d2SAndroid Build Coastguard Worker  *
3718*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3719*5e7646d2SAndroid Build Coastguard Worker  *
3720*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
3721*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
3722*5e7646d2SAndroid Build Coastguard Worker  *
3723*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3724*5e7646d2SAndroid Build Coastguard Worker  */
3725*5e7646d2SAndroid Build Coastguard Worker 
3726*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetDate(ipp_t * ipp,ipp_attribute_t ** attr,int element,const ipp_uchar_t * datevalue)3727*5e7646d2SAndroid Build Coastguard Worker ippSetDate(ipp_t             *ipp,	/* I  - IPP message */
3728*5e7646d2SAndroid Build Coastguard Worker            ipp_attribute_t   **attr,	/* IO - IPP attribute */
3729*5e7646d2SAndroid Build Coastguard Worker            int               element,	/* I  - Value number (0-based) */
3730*5e7646d2SAndroid Build Coastguard Worker            const ipp_uchar_t *datevalue)/* I  - dateTime value */
3731*5e7646d2SAndroid Build Coastguard Worker {
3732*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
3733*5e7646d2SAndroid Build Coastguard Worker 
3734*5e7646d2SAndroid Build Coastguard Worker 
3735*5e7646d2SAndroid Build Coastguard Worker  /*
3736*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3737*5e7646d2SAndroid Build Coastguard Worker   */
3738*5e7646d2SAndroid Build Coastguard Worker 
3739*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || ((*attr)->value_tag != IPP_TAG_DATE && (*attr)->value_tag != IPP_TAG_NOVALUE && (*attr)->value_tag != IPP_TAG_UNKNOWN) || element < 0 || element > (*attr)->num_values || !datevalue)
3740*5e7646d2SAndroid Build Coastguard Worker     return (0);
3741*5e7646d2SAndroid Build Coastguard Worker 
3742*5e7646d2SAndroid Build Coastguard Worker  /*
3743*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3744*5e7646d2SAndroid Build Coastguard Worker   */
3745*5e7646d2SAndroid Build Coastguard Worker 
3746*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
3747*5e7646d2SAndroid Build Coastguard Worker     memcpy(value->date, datevalue, sizeof(value->date));
3748*5e7646d2SAndroid Build Coastguard Worker 
3749*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
3750*5e7646d2SAndroid Build Coastguard Worker }
3751*5e7646d2SAndroid Build Coastguard Worker 
3752*5e7646d2SAndroid Build Coastguard Worker 
3753*5e7646d2SAndroid Build Coastguard Worker /*
3754*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetGroupTag()' - Set the group tag of an attribute.
3755*5e7646d2SAndroid Build Coastguard Worker  *
3756*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3757*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3758*5e7646d2SAndroid Build Coastguard Worker  *
3759*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3760*5e7646d2SAndroid Build Coastguard Worker  *
3761*5e7646d2SAndroid Build Coastguard Worker  * The @code group@ parameter specifies the IPP attribute group tag: none
3762*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
3763*5e7646d2SAndroid Build Coastguard Worker  * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
3764*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
3765*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
3766*5e7646d2SAndroid Build Coastguard Worker  *
3767*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3768*5e7646d2SAndroid Build Coastguard Worker  */
3769*5e7646d2SAndroid Build Coastguard Worker 
3770*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetGroupTag(ipp_t * ipp,ipp_attribute_t ** attr,ipp_tag_t group_tag)3771*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(
3772*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I  - IPP message */
3773*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - Attribute */
3774*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t       group_tag)		/* I  - Group tag */
3775*5e7646d2SAndroid Build Coastguard Worker {
3776*5e7646d2SAndroid Build Coastguard Worker  /*
3777*5e7646d2SAndroid Build Coastguard Worker   * Range check input - group tag must be 0x01 to 0x0F, per RFC 8011...
3778*5e7646d2SAndroid Build Coastguard Worker   */
3779*5e7646d2SAndroid Build Coastguard Worker 
3780*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr ||
3781*5e7646d2SAndroid Build Coastguard Worker       group_tag < IPP_TAG_ZERO || group_tag == IPP_TAG_END ||
3782*5e7646d2SAndroid Build Coastguard Worker       group_tag >= IPP_TAG_UNSUPPORTED_VALUE)
3783*5e7646d2SAndroid Build Coastguard Worker     return (0);
3784*5e7646d2SAndroid Build Coastguard Worker 
3785*5e7646d2SAndroid Build Coastguard Worker  /*
3786*5e7646d2SAndroid Build Coastguard Worker   * Set the group tag and return...
3787*5e7646d2SAndroid Build Coastguard Worker   */
3788*5e7646d2SAndroid Build Coastguard Worker 
3789*5e7646d2SAndroid Build Coastguard Worker   (*attr)->group_tag = group_tag;
3790*5e7646d2SAndroid Build Coastguard Worker 
3791*5e7646d2SAndroid Build Coastguard Worker   return (1);
3792*5e7646d2SAndroid Build Coastguard Worker }
3793*5e7646d2SAndroid Build Coastguard Worker 
3794*5e7646d2SAndroid Build Coastguard Worker 
3795*5e7646d2SAndroid Build Coastguard Worker /*
3796*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetInteger()' - Set an integer or enum value in an attribute.
3797*5e7646d2SAndroid Build Coastguard Worker  *
3798*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3799*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3800*5e7646d2SAndroid Build Coastguard Worker  *
3801*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3802*5e7646d2SAndroid Build Coastguard Worker  *
3803*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
3804*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
3805*5e7646d2SAndroid Build Coastguard Worker  *
3806*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3807*5e7646d2SAndroid Build Coastguard Worker  */
3808*5e7646d2SAndroid Build Coastguard Worker 
3809*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetInteger(ipp_t * ipp,ipp_attribute_t ** attr,int element,int intvalue)3810*5e7646d2SAndroid Build Coastguard Worker ippSetInteger(ipp_t           *ipp,	/* I  - IPP message */
3811*5e7646d2SAndroid Build Coastguard Worker               ipp_attribute_t **attr,	/* IO - IPP attribute */
3812*5e7646d2SAndroid Build Coastguard Worker               int             element,	/* I  - Value number (0-based) */
3813*5e7646d2SAndroid Build Coastguard Worker               int             intvalue)	/* I  - Integer/enum value */
3814*5e7646d2SAndroid Build Coastguard Worker {
3815*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
3816*5e7646d2SAndroid Build Coastguard Worker 
3817*5e7646d2SAndroid Build Coastguard Worker 
3818*5e7646d2SAndroid Build Coastguard Worker  /*
3819*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3820*5e7646d2SAndroid Build Coastguard Worker   */
3821*5e7646d2SAndroid Build Coastguard Worker 
3822*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || ((*attr)->value_tag != IPP_TAG_INTEGER && (*attr)->value_tag != IPP_TAG_ENUM && (*attr)->value_tag != IPP_TAG_NOVALUE && (*attr)->value_tag != IPP_TAG_UNKNOWN) || element < 0 || element > (*attr)->num_values)
3823*5e7646d2SAndroid Build Coastguard Worker     return (0);
3824*5e7646d2SAndroid Build Coastguard Worker 
3825*5e7646d2SAndroid Build Coastguard Worker  /*
3826*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3827*5e7646d2SAndroid Build Coastguard Worker   */
3828*5e7646d2SAndroid Build Coastguard Worker 
3829*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
3830*5e7646d2SAndroid Build Coastguard Worker   {
3831*5e7646d2SAndroid Build Coastguard Worker     if ((*attr)->value_tag != IPP_TAG_ENUM)
3832*5e7646d2SAndroid Build Coastguard Worker       (*attr)->value_tag = IPP_TAG_INTEGER;
3833*5e7646d2SAndroid Build Coastguard Worker 
3834*5e7646d2SAndroid Build Coastguard Worker     value->integer = intvalue;
3835*5e7646d2SAndroid Build Coastguard Worker   }
3836*5e7646d2SAndroid Build Coastguard Worker 
3837*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
3838*5e7646d2SAndroid Build Coastguard Worker }
3839*5e7646d2SAndroid Build Coastguard Worker 
3840*5e7646d2SAndroid Build Coastguard Worker 
3841*5e7646d2SAndroid Build Coastguard Worker /*
3842*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetName()' - Set the name of an attribute.
3843*5e7646d2SAndroid Build Coastguard Worker  *
3844*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3845*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3846*5e7646d2SAndroid Build Coastguard Worker  *
3847*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3848*5e7646d2SAndroid Build Coastguard Worker  *
3849*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3850*5e7646d2SAndroid Build Coastguard Worker  */
3851*5e7646d2SAndroid Build Coastguard Worker 
3852*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetName(ipp_t * ipp,ipp_attribute_t ** attr,const char * name)3853*5e7646d2SAndroid Build Coastguard Worker ippSetName(ipp_t           *ipp,	/* I  - IPP message */
3854*5e7646d2SAndroid Build Coastguard Worker 	   ipp_attribute_t **attr,	/* IO - IPP attribute */
3855*5e7646d2SAndroid Build Coastguard Worker 	   const char      *name)	/* I  - Attribute name */
3856*5e7646d2SAndroid Build Coastguard Worker {
3857*5e7646d2SAndroid Build Coastguard Worker   char	*temp;				/* Temporary name value */
3858*5e7646d2SAndroid Build Coastguard Worker 
3859*5e7646d2SAndroid Build Coastguard Worker 
3860*5e7646d2SAndroid Build Coastguard Worker  /*
3861*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3862*5e7646d2SAndroid Build Coastguard Worker   */
3863*5e7646d2SAndroid Build Coastguard Worker 
3864*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr)
3865*5e7646d2SAndroid Build Coastguard Worker     return (0);
3866*5e7646d2SAndroid Build Coastguard Worker 
3867*5e7646d2SAndroid Build Coastguard Worker  /*
3868*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3869*5e7646d2SAndroid Build Coastguard Worker   */
3870*5e7646d2SAndroid Build Coastguard Worker 
3871*5e7646d2SAndroid Build Coastguard Worker   if ((temp = _cupsStrAlloc(name)) != NULL)
3872*5e7646d2SAndroid Build Coastguard Worker   {
3873*5e7646d2SAndroid Build Coastguard Worker     if ((*attr)->name)
3874*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFree((*attr)->name);
3875*5e7646d2SAndroid Build Coastguard Worker 
3876*5e7646d2SAndroid Build Coastguard Worker     (*attr)->name = temp;
3877*5e7646d2SAndroid Build Coastguard Worker   }
3878*5e7646d2SAndroid Build Coastguard Worker 
3879*5e7646d2SAndroid Build Coastguard Worker   return (temp != NULL);
3880*5e7646d2SAndroid Build Coastguard Worker }
3881*5e7646d2SAndroid Build Coastguard Worker 
3882*5e7646d2SAndroid Build Coastguard Worker 
3883*5e7646d2SAndroid Build Coastguard Worker /*
3884*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetOctetString()' - Set an octetString value in an IPP attribute.
3885*5e7646d2SAndroid Build Coastguard Worker  *
3886*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3887*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3888*5e7646d2SAndroid Build Coastguard Worker  *
3889*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
3890*5e7646d2SAndroid Build Coastguard Worker  *
3891*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
3892*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
3893*5e7646d2SAndroid Build Coastguard Worker  *
3894*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
3895*5e7646d2SAndroid Build Coastguard Worker  */
3896*5e7646d2SAndroid Build Coastguard Worker 
3897*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetOctetString(ipp_t * ipp,ipp_attribute_t ** attr,int element,const void * data,int datalen)3898*5e7646d2SAndroid Build Coastguard Worker ippSetOctetString(
3899*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I  - IPP message */
3900*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - IPP attribute */
3901*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I  - Value number (0-based) */
3902*5e7646d2SAndroid Build Coastguard Worker     const void      *data,		/* I  - Pointer to octetString data */
3903*5e7646d2SAndroid Build Coastguard Worker     int             datalen)		/* I  - Length of octetString data */
3904*5e7646d2SAndroid Build Coastguard Worker {
3905*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
3906*5e7646d2SAndroid Build Coastguard Worker 
3907*5e7646d2SAndroid Build Coastguard Worker 
3908*5e7646d2SAndroid Build Coastguard Worker  /*
3909*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3910*5e7646d2SAndroid Build Coastguard Worker   */
3911*5e7646d2SAndroid Build Coastguard Worker 
3912*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || ((*attr)->value_tag != IPP_TAG_STRING && (*attr)->value_tag != IPP_TAG_NOVALUE && (*attr)->value_tag != IPP_TAG_UNKNOWN) || element < 0 || element > (*attr)->num_values || datalen < 0 || datalen > IPP_MAX_LENGTH)
3913*5e7646d2SAndroid Build Coastguard Worker     return (0);
3914*5e7646d2SAndroid Build Coastguard Worker 
3915*5e7646d2SAndroid Build Coastguard Worker  /*
3916*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
3917*5e7646d2SAndroid Build Coastguard Worker   */
3918*5e7646d2SAndroid Build Coastguard Worker 
3919*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
3920*5e7646d2SAndroid Build Coastguard Worker   {
3921*5e7646d2SAndroid Build Coastguard Worker     if ((int)((*attr)->value_tag) & IPP_TAG_CUPS_CONST)
3922*5e7646d2SAndroid Build Coastguard Worker     {
3923*5e7646d2SAndroid Build Coastguard Worker      /*
3924*5e7646d2SAndroid Build Coastguard Worker       * Just copy the pointer...
3925*5e7646d2SAndroid Build Coastguard Worker       */
3926*5e7646d2SAndroid Build Coastguard Worker 
3927*5e7646d2SAndroid Build Coastguard Worker       value->unknown.data   = (void *)data;
3928*5e7646d2SAndroid Build Coastguard Worker       value->unknown.length = datalen;
3929*5e7646d2SAndroid Build Coastguard Worker     }
3930*5e7646d2SAndroid Build Coastguard Worker     else
3931*5e7646d2SAndroid Build Coastguard Worker     {
3932*5e7646d2SAndroid Build Coastguard Worker      /*
3933*5e7646d2SAndroid Build Coastguard Worker       * Copy the data...
3934*5e7646d2SAndroid Build Coastguard Worker       */
3935*5e7646d2SAndroid Build Coastguard Worker 
3936*5e7646d2SAndroid Build Coastguard Worker       (*attr)->value_tag = IPP_TAG_STRING;
3937*5e7646d2SAndroid Build Coastguard Worker 
3938*5e7646d2SAndroid Build Coastguard Worker       if (value->unknown.data)
3939*5e7646d2SAndroid Build Coastguard Worker       {
3940*5e7646d2SAndroid Build Coastguard Worker        /*
3941*5e7646d2SAndroid Build Coastguard Worker 	* Free previous data...
3942*5e7646d2SAndroid Build Coastguard Worker 	*/
3943*5e7646d2SAndroid Build Coastguard Worker 
3944*5e7646d2SAndroid Build Coastguard Worker 	free(value->unknown.data);
3945*5e7646d2SAndroid Build Coastguard Worker 
3946*5e7646d2SAndroid Build Coastguard Worker 	value->unknown.data   = NULL;
3947*5e7646d2SAndroid Build Coastguard Worker         value->unknown.length = 0;
3948*5e7646d2SAndroid Build Coastguard Worker       }
3949*5e7646d2SAndroid Build Coastguard Worker 
3950*5e7646d2SAndroid Build Coastguard Worker       if (datalen > 0)
3951*5e7646d2SAndroid Build Coastguard Worker       {
3952*5e7646d2SAndroid Build Coastguard Worker 	void	*temp;			/* Temporary data pointer */
3953*5e7646d2SAndroid Build Coastguard Worker 
3954*5e7646d2SAndroid Build Coastguard Worker 	if ((temp = malloc((size_t)datalen)) != NULL)
3955*5e7646d2SAndroid Build Coastguard Worker 	{
3956*5e7646d2SAndroid Build Coastguard Worker 	  memcpy(temp, data, (size_t)datalen);
3957*5e7646d2SAndroid Build Coastguard Worker 
3958*5e7646d2SAndroid Build Coastguard Worker 	  value->unknown.data   = temp;
3959*5e7646d2SAndroid Build Coastguard Worker 	  value->unknown.length = datalen;
3960*5e7646d2SAndroid Build Coastguard Worker 	}
3961*5e7646d2SAndroid Build Coastguard Worker 	else
3962*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
3963*5e7646d2SAndroid Build Coastguard Worker       }
3964*5e7646d2SAndroid Build Coastguard Worker     }
3965*5e7646d2SAndroid Build Coastguard Worker   }
3966*5e7646d2SAndroid Build Coastguard Worker 
3967*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
3968*5e7646d2SAndroid Build Coastguard Worker }
3969*5e7646d2SAndroid Build Coastguard Worker 
3970*5e7646d2SAndroid Build Coastguard Worker 
3971*5e7646d2SAndroid Build Coastguard Worker /*
3972*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetOperation()' - Set the operation ID in an IPP request message.
3973*5e7646d2SAndroid Build Coastguard Worker  *
3974*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
3975*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
3976*5e7646d2SAndroid Build Coastguard Worker  *
3977*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
3978*5e7646d2SAndroid Build Coastguard Worker  */
3979*5e7646d2SAndroid Build Coastguard Worker 
3980*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
ippSetOperation(ipp_t * ipp,ipp_op_t op)3981*5e7646d2SAndroid Build Coastguard Worker ippSetOperation(ipp_t    *ipp,		/* I - IPP request message */
3982*5e7646d2SAndroid Build Coastguard Worker                 ipp_op_t op)		/* I - Operation ID */
3983*5e7646d2SAndroid Build Coastguard Worker {
3984*5e7646d2SAndroid Build Coastguard Worker  /*
3985*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3986*5e7646d2SAndroid Build Coastguard Worker   */
3987*5e7646d2SAndroid Build Coastguard Worker 
3988*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
3989*5e7646d2SAndroid Build Coastguard Worker     return (0);
3990*5e7646d2SAndroid Build Coastguard Worker 
3991*5e7646d2SAndroid Build Coastguard Worker  /*
3992*5e7646d2SAndroid Build Coastguard Worker   * Set the operation and return...
3993*5e7646d2SAndroid Build Coastguard Worker   */
3994*5e7646d2SAndroid Build Coastguard Worker 
3995*5e7646d2SAndroid Build Coastguard Worker   ipp->request.op.operation_id = op;
3996*5e7646d2SAndroid Build Coastguard Worker 
3997*5e7646d2SAndroid Build Coastguard Worker   return (1);
3998*5e7646d2SAndroid Build Coastguard Worker }
3999*5e7646d2SAndroid Build Coastguard Worker 
4000*5e7646d2SAndroid Build Coastguard Worker 
4001*5e7646d2SAndroid Build Coastguard Worker /*
4002*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetRange()' - Set a rangeOfInteger value in an attribute.
4003*5e7646d2SAndroid Build Coastguard Worker  *
4004*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4005*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4006*5e7646d2SAndroid Build Coastguard Worker  *
4007*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4008*5e7646d2SAndroid Build Coastguard Worker  *
4009*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
4010*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
4011*5e7646d2SAndroid Build Coastguard Worker  *
4012*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4013*5e7646d2SAndroid Build Coastguard Worker  */
4014*5e7646d2SAndroid Build Coastguard Worker 
4015*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetRange(ipp_t * ipp,ipp_attribute_t ** attr,int element,int lowervalue,int uppervalue)4016*5e7646d2SAndroid Build Coastguard Worker ippSetRange(ipp_t           *ipp,	/* I  - IPP message */
4017*5e7646d2SAndroid Build Coastguard Worker             ipp_attribute_t **attr,	/* IO - IPP attribute */
4018*5e7646d2SAndroid Build Coastguard Worker             int             element,	/* I  - Value number (0-based) */
4019*5e7646d2SAndroid Build Coastguard Worker 	    int             lowervalue,	/* I  - Lower bound for range */
4020*5e7646d2SAndroid Build Coastguard Worker 	    int             uppervalue)	/* I  - Upper bound for range */
4021*5e7646d2SAndroid Build Coastguard Worker {
4022*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
4023*5e7646d2SAndroid Build Coastguard Worker 
4024*5e7646d2SAndroid Build Coastguard Worker 
4025*5e7646d2SAndroid Build Coastguard Worker  /*
4026*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4027*5e7646d2SAndroid Build Coastguard Worker   */
4028*5e7646d2SAndroid Build Coastguard Worker 
4029*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || ((*attr)->value_tag != IPP_TAG_RANGE && (*attr)->value_tag != IPP_TAG_NOVALUE && (*attr)->value_tag != IPP_TAG_UNKNOWN) || element < 0 || element > (*attr)->num_values || lowervalue > uppervalue)
4030*5e7646d2SAndroid Build Coastguard Worker     return (0);
4031*5e7646d2SAndroid Build Coastguard Worker 
4032*5e7646d2SAndroid Build Coastguard Worker  /*
4033*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
4034*5e7646d2SAndroid Build Coastguard Worker   */
4035*5e7646d2SAndroid Build Coastguard Worker 
4036*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
4037*5e7646d2SAndroid Build Coastguard Worker   {
4038*5e7646d2SAndroid Build Coastguard Worker     (*attr)->value_tag = IPP_TAG_RANGE;
4039*5e7646d2SAndroid Build Coastguard Worker     value->range.lower = lowervalue;
4040*5e7646d2SAndroid Build Coastguard Worker     value->range.upper = uppervalue;
4041*5e7646d2SAndroid Build Coastguard Worker   }
4042*5e7646d2SAndroid Build Coastguard Worker 
4043*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
4044*5e7646d2SAndroid Build Coastguard Worker }
4045*5e7646d2SAndroid Build Coastguard Worker 
4046*5e7646d2SAndroid Build Coastguard Worker 
4047*5e7646d2SAndroid Build Coastguard Worker /*
4048*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetRequestId()' - Set the request ID in an IPP message.
4049*5e7646d2SAndroid Build Coastguard Worker  *
4050*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4051*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4052*5e7646d2SAndroid Build Coastguard Worker  *
4053*5e7646d2SAndroid Build Coastguard Worker  * The @code request_id@ parameter must be greater than 0.
4054*5e7646d2SAndroid Build Coastguard Worker  *
4055*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4056*5e7646d2SAndroid Build Coastguard Worker  */
4057*5e7646d2SAndroid Build Coastguard Worker 
4058*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
ippSetRequestId(ipp_t * ipp,int request_id)4059*5e7646d2SAndroid Build Coastguard Worker ippSetRequestId(ipp_t *ipp,		/* I - IPP message */
4060*5e7646d2SAndroid Build Coastguard Worker                 int   request_id)	/* I - Request ID */
4061*5e7646d2SAndroid Build Coastguard Worker {
4062*5e7646d2SAndroid Build Coastguard Worker  /*
4063*5e7646d2SAndroid Build Coastguard Worker   * Range check input; not checking request_id values since ipptool wants to send
4064*5e7646d2SAndroid Build Coastguard Worker   * invalid values for conformance testing and a bad request_id does not affect the
4065*5e7646d2SAndroid Build Coastguard Worker   * encoding of a message...
4066*5e7646d2SAndroid Build Coastguard Worker   */
4067*5e7646d2SAndroid Build Coastguard Worker 
4068*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
4069*5e7646d2SAndroid Build Coastguard Worker     return (0);
4070*5e7646d2SAndroid Build Coastguard Worker 
4071*5e7646d2SAndroid Build Coastguard Worker  /*
4072*5e7646d2SAndroid Build Coastguard Worker   * Set the request ID and return...
4073*5e7646d2SAndroid Build Coastguard Worker   */
4074*5e7646d2SAndroid Build Coastguard Worker 
4075*5e7646d2SAndroid Build Coastguard Worker   ipp->request.any.request_id = request_id;
4076*5e7646d2SAndroid Build Coastguard Worker 
4077*5e7646d2SAndroid Build Coastguard Worker   return (1);
4078*5e7646d2SAndroid Build Coastguard Worker }
4079*5e7646d2SAndroid Build Coastguard Worker 
4080*5e7646d2SAndroid Build Coastguard Worker 
4081*5e7646d2SAndroid Build Coastguard Worker /*
4082*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetResolution()' - Set a resolution value in an attribute.
4083*5e7646d2SAndroid Build Coastguard Worker  *
4084*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4085*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4086*5e7646d2SAndroid Build Coastguard Worker  *
4087*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4088*5e7646d2SAndroid Build Coastguard Worker  *
4089*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
4090*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
4091*5e7646d2SAndroid Build Coastguard Worker  *
4092*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4093*5e7646d2SAndroid Build Coastguard Worker  */
4094*5e7646d2SAndroid Build Coastguard Worker 
4095*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetResolution(ipp_t * ipp,ipp_attribute_t ** attr,int element,ipp_res_t unitsvalue,int xresvalue,int yresvalue)4096*5e7646d2SAndroid Build Coastguard Worker ippSetResolution(
4097*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I  - IPP message */
4098*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - IPP attribute */
4099*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I  - Value number (0-based) */
4100*5e7646d2SAndroid Build Coastguard Worker     ipp_res_t       unitsvalue,		/* I  - Resolution units */
4101*5e7646d2SAndroid Build Coastguard Worker     int             xresvalue,		/* I  - Horizontal/cross feed resolution */
4102*5e7646d2SAndroid Build Coastguard Worker     int             yresvalue)		/* I  - Vertical/feed resolution */
4103*5e7646d2SAndroid Build Coastguard Worker {
4104*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
4105*5e7646d2SAndroid Build Coastguard Worker 
4106*5e7646d2SAndroid Build Coastguard Worker 
4107*5e7646d2SAndroid Build Coastguard Worker  /*
4108*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4109*5e7646d2SAndroid Build Coastguard Worker   */
4110*5e7646d2SAndroid Build Coastguard Worker 
4111*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || ((*attr)->value_tag != IPP_TAG_RESOLUTION && (*attr)->value_tag != IPP_TAG_NOVALUE && (*attr)->value_tag != IPP_TAG_UNKNOWN) || element < 0 || element > (*attr)->num_values || xresvalue <= 0 || yresvalue <= 0 || unitsvalue < IPP_RES_PER_INCH || unitsvalue > IPP_RES_PER_CM)
4112*5e7646d2SAndroid Build Coastguard Worker     return (0);
4113*5e7646d2SAndroid Build Coastguard Worker 
4114*5e7646d2SAndroid Build Coastguard Worker  /*
4115*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
4116*5e7646d2SAndroid Build Coastguard Worker   */
4117*5e7646d2SAndroid Build Coastguard Worker 
4118*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
4119*5e7646d2SAndroid Build Coastguard Worker   {
4120*5e7646d2SAndroid Build Coastguard Worker     (*attr)->value_tag      = IPP_TAG_RESOLUTION;
4121*5e7646d2SAndroid Build Coastguard Worker     value->resolution.units = unitsvalue;
4122*5e7646d2SAndroid Build Coastguard Worker     value->resolution.xres  = xresvalue;
4123*5e7646d2SAndroid Build Coastguard Worker     value->resolution.yres  = yresvalue;
4124*5e7646d2SAndroid Build Coastguard Worker   }
4125*5e7646d2SAndroid Build Coastguard Worker 
4126*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
4127*5e7646d2SAndroid Build Coastguard Worker }
4128*5e7646d2SAndroid Build Coastguard Worker 
4129*5e7646d2SAndroid Build Coastguard Worker 
4130*5e7646d2SAndroid Build Coastguard Worker /*
4131*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetState()' - Set the current state of the IPP message.
4132*5e7646d2SAndroid Build Coastguard Worker  *
4133*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4134*5e7646d2SAndroid Build Coastguard Worker  */
4135*5e7646d2SAndroid Build Coastguard Worker 
4136*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
ippSetState(ipp_t * ipp,ipp_state_t state)4137*5e7646d2SAndroid Build Coastguard Worker ippSetState(ipp_t       *ipp,		/* I - IPP message */
4138*5e7646d2SAndroid Build Coastguard Worker             ipp_state_t state)		/* I - IPP state value */
4139*5e7646d2SAndroid Build Coastguard Worker {
4140*5e7646d2SAndroid Build Coastguard Worker  /*
4141*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4142*5e7646d2SAndroid Build Coastguard Worker   */
4143*5e7646d2SAndroid Build Coastguard Worker 
4144*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
4145*5e7646d2SAndroid Build Coastguard Worker     return (0);
4146*5e7646d2SAndroid Build Coastguard Worker 
4147*5e7646d2SAndroid Build Coastguard Worker  /*
4148*5e7646d2SAndroid Build Coastguard Worker   * Set the state and return...
4149*5e7646d2SAndroid Build Coastguard Worker   */
4150*5e7646d2SAndroid Build Coastguard Worker 
4151*5e7646d2SAndroid Build Coastguard Worker   ipp->state   = state;
4152*5e7646d2SAndroid Build Coastguard Worker   ipp->current = NULL;
4153*5e7646d2SAndroid Build Coastguard Worker 
4154*5e7646d2SAndroid Build Coastguard Worker   return (1);
4155*5e7646d2SAndroid Build Coastguard Worker }
4156*5e7646d2SAndroid Build Coastguard Worker 
4157*5e7646d2SAndroid Build Coastguard Worker 
4158*5e7646d2SAndroid Build Coastguard Worker /*
4159*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetStatusCode()' - Set the status code in an IPP response or event message.
4160*5e7646d2SAndroid Build Coastguard Worker  *
4161*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4162*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4163*5e7646d2SAndroid Build Coastguard Worker  *
4164*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4165*5e7646d2SAndroid Build Coastguard Worker  */
4166*5e7646d2SAndroid Build Coastguard Worker 
4167*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
ippSetStatusCode(ipp_t * ipp,ipp_status_t status)4168*5e7646d2SAndroid Build Coastguard Worker ippSetStatusCode(ipp_t        *ipp,	/* I - IPP response or event message */
4169*5e7646d2SAndroid Build Coastguard Worker                  ipp_status_t status)	/* I - Status code */
4170*5e7646d2SAndroid Build Coastguard Worker {
4171*5e7646d2SAndroid Build Coastguard Worker  /*
4172*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4173*5e7646d2SAndroid Build Coastguard Worker   */
4174*5e7646d2SAndroid Build Coastguard Worker 
4175*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
4176*5e7646d2SAndroid Build Coastguard Worker     return (0);
4177*5e7646d2SAndroid Build Coastguard Worker 
4178*5e7646d2SAndroid Build Coastguard Worker  /*
4179*5e7646d2SAndroid Build Coastguard Worker   * Set the status code and return...
4180*5e7646d2SAndroid Build Coastguard Worker   */
4181*5e7646d2SAndroid Build Coastguard Worker 
4182*5e7646d2SAndroid Build Coastguard Worker   ipp->request.status.status_code = status;
4183*5e7646d2SAndroid Build Coastguard Worker 
4184*5e7646d2SAndroid Build Coastguard Worker   return (1);
4185*5e7646d2SAndroid Build Coastguard Worker }
4186*5e7646d2SAndroid Build Coastguard Worker 
4187*5e7646d2SAndroid Build Coastguard Worker 
4188*5e7646d2SAndroid Build Coastguard Worker /*
4189*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetString()' - Set a string value in an attribute.
4190*5e7646d2SAndroid Build Coastguard Worker  *
4191*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4192*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4193*5e7646d2SAndroid Build Coastguard Worker  *
4194*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4195*5e7646d2SAndroid Build Coastguard Worker  *
4196*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
4197*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
4198*5e7646d2SAndroid Build Coastguard Worker  *
4199*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4200*5e7646d2SAndroid Build Coastguard Worker  */
4201*5e7646d2SAndroid Build Coastguard Worker 
4202*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetString(ipp_t * ipp,ipp_attribute_t ** attr,int element,const char * strvalue)4203*5e7646d2SAndroid Build Coastguard Worker ippSetString(ipp_t           *ipp,	/* I  - IPP message */
4204*5e7646d2SAndroid Build Coastguard Worker              ipp_attribute_t **attr,	/* IO - IPP attribute */
4205*5e7646d2SAndroid Build Coastguard Worker              int             element,	/* I  - Value number (0-based) */
4206*5e7646d2SAndroid Build Coastguard Worker 	     const char      *strvalue)	/* I  - String value */
4207*5e7646d2SAndroid Build Coastguard Worker {
4208*5e7646d2SAndroid Build Coastguard Worker   char		*temp;			/* Temporary string */
4209*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
4210*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	value_tag;		/* Value tag */
4211*5e7646d2SAndroid Build Coastguard Worker 
4212*5e7646d2SAndroid Build Coastguard Worker 
4213*5e7646d2SAndroid Build Coastguard Worker  /*
4214*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4215*5e7646d2SAndroid Build Coastguard Worker   */
4216*5e7646d2SAndroid Build Coastguard Worker 
4217*5e7646d2SAndroid Build Coastguard Worker   if (attr && *attr)
4218*5e7646d2SAndroid Build Coastguard Worker     value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK;
4219*5e7646d2SAndroid Build Coastguard Worker   else
4220*5e7646d2SAndroid Build Coastguard Worker     value_tag = IPP_TAG_ZERO;
4221*5e7646d2SAndroid Build Coastguard Worker 
4222*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && value_tag != IPP_TAG_NAMELANG && value_tag != IPP_TAG_NOVALUE && value_tag != IPP_TAG_UNKNOWN) || value_tag > IPP_TAG_MIMETYPE || element < 0 || element > (*attr)->num_values || !strvalue)
4223*5e7646d2SAndroid Build Coastguard Worker     return (0);
4224*5e7646d2SAndroid Build Coastguard Worker 
4225*5e7646d2SAndroid Build Coastguard Worker  /*
4226*5e7646d2SAndroid Build Coastguard Worker   * Set the value and return...
4227*5e7646d2SAndroid Build Coastguard Worker   */
4228*5e7646d2SAndroid Build Coastguard Worker 
4229*5e7646d2SAndroid Build Coastguard Worker   if ((value = ipp_set_value(ipp, attr, element)) != NULL)
4230*5e7646d2SAndroid Build Coastguard Worker   {
4231*5e7646d2SAndroid Build Coastguard Worker     if (value_tag == IPP_TAG_NOVALUE || value_tag == IPP_TAG_UNKNOWN)
4232*5e7646d2SAndroid Build Coastguard Worker       (*attr)->value_tag = IPP_TAG_KEYWORD;
4233*5e7646d2SAndroid Build Coastguard Worker 
4234*5e7646d2SAndroid Build Coastguard Worker     if (element > 0)
4235*5e7646d2SAndroid Build Coastguard Worker       value->string.language = (*attr)->values[0].string.language;
4236*5e7646d2SAndroid Build Coastguard Worker 
4237*5e7646d2SAndroid Build Coastguard Worker     if ((int)((*attr)->value_tag) & IPP_TAG_CUPS_CONST)
4238*5e7646d2SAndroid Build Coastguard Worker       value->string.text = (char *)strvalue;
4239*5e7646d2SAndroid Build Coastguard Worker     else if ((temp = _cupsStrAlloc(strvalue)) != NULL)
4240*5e7646d2SAndroid Build Coastguard Worker     {
4241*5e7646d2SAndroid Build Coastguard Worker       if (value->string.text)
4242*5e7646d2SAndroid Build Coastguard Worker         _cupsStrFree(value->string.text);
4243*5e7646d2SAndroid Build Coastguard Worker 
4244*5e7646d2SAndroid Build Coastguard Worker       value->string.text = temp;
4245*5e7646d2SAndroid Build Coastguard Worker     }
4246*5e7646d2SAndroid Build Coastguard Worker     else
4247*5e7646d2SAndroid Build Coastguard Worker       return (0);
4248*5e7646d2SAndroid Build Coastguard Worker   }
4249*5e7646d2SAndroid Build Coastguard Worker 
4250*5e7646d2SAndroid Build Coastguard Worker   return (value != NULL);
4251*5e7646d2SAndroid Build Coastguard Worker }
4252*5e7646d2SAndroid Build Coastguard Worker 
4253*5e7646d2SAndroid Build Coastguard Worker 
4254*5e7646d2SAndroid Build Coastguard Worker /*
4255*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetStringf()' - Set a formatted string value of an attribute.
4256*5e7646d2SAndroid Build Coastguard Worker  *
4257*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4258*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4259*5e7646d2SAndroid Build Coastguard Worker  *
4260*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4261*5e7646d2SAndroid Build Coastguard Worker  *
4262*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
4263*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
4264*5e7646d2SAndroid Build Coastguard Worker  *
4265*5e7646d2SAndroid Build Coastguard Worker  * The @code format@ parameter uses formatting characters compatible with the
4266*5e7646d2SAndroid Build Coastguard Worker  * printf family of standard functions.  Additional arguments follow it as
4267*5e7646d2SAndroid Build Coastguard Worker  * needed.  The formatted string is truncated as needed to the maximum length of
4268*5e7646d2SAndroid Build Coastguard Worker  * the corresponding value type.
4269*5e7646d2SAndroid Build Coastguard Worker  *
4270*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
4271*5e7646d2SAndroid Build Coastguard Worker  */
4272*5e7646d2SAndroid Build Coastguard Worker 
4273*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetStringf(ipp_t * ipp,ipp_attribute_t ** attr,int element,const char * format,...)4274*5e7646d2SAndroid Build Coastguard Worker ippSetStringf(ipp_t           *ipp,	/* I  - IPP message */
4275*5e7646d2SAndroid Build Coastguard Worker               ipp_attribute_t **attr,	/* IO - IPP attribute */
4276*5e7646d2SAndroid Build Coastguard Worker               int             element,	/* I  - Value number (0-based) */
4277*5e7646d2SAndroid Build Coastguard Worker 	      const char      *format,	/* I  - Printf-style format string */
4278*5e7646d2SAndroid Build Coastguard Worker 	      ...)			/* I  - Additional arguments as needed */
4279*5e7646d2SAndroid Build Coastguard Worker {
4280*5e7646d2SAndroid Build Coastguard Worker   int		ret;			/* Return value */
4281*5e7646d2SAndroid Build Coastguard Worker   va_list	ap;			/* Pointer to additional arguments */
4282*5e7646d2SAndroid Build Coastguard Worker 
4283*5e7646d2SAndroid Build Coastguard Worker 
4284*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, format);
4285*5e7646d2SAndroid Build Coastguard Worker   ret = ippSetStringfv(ipp, attr, element, format, ap);
4286*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
4287*5e7646d2SAndroid Build Coastguard Worker 
4288*5e7646d2SAndroid Build Coastguard Worker   return (ret);
4289*5e7646d2SAndroid Build Coastguard Worker }
4290*5e7646d2SAndroid Build Coastguard Worker 
4291*5e7646d2SAndroid Build Coastguard Worker 
4292*5e7646d2SAndroid Build Coastguard Worker /*
4293*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetStringf()' - Set a formatted string value of an attribute.
4294*5e7646d2SAndroid Build Coastguard Worker  *
4295*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4296*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4297*5e7646d2SAndroid Build Coastguard Worker  *
4298*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4299*5e7646d2SAndroid Build Coastguard Worker  *
4300*5e7646d2SAndroid Build Coastguard Worker  * The @code element@ parameter specifies which value to set from 0 to
4301*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCount(attr)@.
4302*5e7646d2SAndroid Build Coastguard Worker  *
4303*5e7646d2SAndroid Build Coastguard Worker  * The @code format@ parameter uses formatting characters compatible with the
4304*5e7646d2SAndroid Build Coastguard Worker  * printf family of standard functions.  Additional arguments follow it as
4305*5e7646d2SAndroid Build Coastguard Worker  * needed.  The formatted string is truncated as needed to the maximum length of
4306*5e7646d2SAndroid Build Coastguard Worker  * the corresponding value type.
4307*5e7646d2SAndroid Build Coastguard Worker  *
4308*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
4309*5e7646d2SAndroid Build Coastguard Worker  */
4310*5e7646d2SAndroid Build Coastguard Worker 
4311*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetStringfv(ipp_t * ipp,ipp_attribute_t ** attr,int element,const char * format,va_list ap)4312*5e7646d2SAndroid Build Coastguard Worker ippSetStringfv(ipp_t           *ipp,	/* I  - IPP message */
4313*5e7646d2SAndroid Build Coastguard Worker                ipp_attribute_t **attr,	/* IO - IPP attribute */
4314*5e7646d2SAndroid Build Coastguard Worker                int             element,	/* I  - Value number (0-based) */
4315*5e7646d2SAndroid Build Coastguard Worker 	       const char      *format,	/* I  - Printf-style format string */
4316*5e7646d2SAndroid Build Coastguard Worker 	       va_list         ap)	/* I  - Pointer to additional arguments */
4317*5e7646d2SAndroid Build Coastguard Worker {
4318*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	value_tag;		/* Value tag */
4319*5e7646d2SAndroid Build Coastguard Worker   char		buffer[IPP_MAX_TEXT + 4];
4320*5e7646d2SAndroid Build Coastguard Worker 					/* Formatted text string */
4321*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes,			/* Length of formatted value */
4322*5e7646d2SAndroid Build Coastguard Worker 		max_bytes;		/* Maximum number of bytes for value */
4323*5e7646d2SAndroid Build Coastguard Worker 
4324*5e7646d2SAndroid Build Coastguard Worker 
4325*5e7646d2SAndroid Build Coastguard Worker  /*
4326*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4327*5e7646d2SAndroid Build Coastguard Worker   */
4328*5e7646d2SAndroid Build Coastguard Worker 
4329*5e7646d2SAndroid Build Coastguard Worker   if (attr && *attr)
4330*5e7646d2SAndroid Build Coastguard Worker     value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK;
4331*5e7646d2SAndroid Build Coastguard Worker   else
4332*5e7646d2SAndroid Build Coastguard Worker     value_tag = IPP_TAG_ZERO;
4333*5e7646d2SAndroid Build Coastguard Worker 
4334*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr || (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && value_tag != IPP_TAG_NAMELANG && value_tag != IPP_TAG_NOVALUE && value_tag != IPP_TAG_UNKNOWN) || value_tag > IPP_TAG_MIMETYPE || !format)
4335*5e7646d2SAndroid Build Coastguard Worker     return (0);
4336*5e7646d2SAndroid Build Coastguard Worker 
4337*5e7646d2SAndroid Build Coastguard Worker  /*
4338*5e7646d2SAndroid Build Coastguard Worker   * Format the string...
4339*5e7646d2SAndroid Build Coastguard Worker   */
4340*5e7646d2SAndroid Build Coastguard Worker 
4341*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(format, "%s"))
4342*5e7646d2SAndroid Build Coastguard Worker   {
4343*5e7646d2SAndroid Build Coastguard Worker    /*
4344*5e7646d2SAndroid Build Coastguard Worker     * Optimize the simple case...
4345*5e7646d2SAndroid Build Coastguard Worker     */
4346*5e7646d2SAndroid Build Coastguard Worker 
4347*5e7646d2SAndroid Build Coastguard Worker     const char *s = va_arg(ap, char *);
4348*5e7646d2SAndroid Build Coastguard Worker 
4349*5e7646d2SAndroid Build Coastguard Worker     if (!s)
4350*5e7646d2SAndroid Build Coastguard Worker       s = "(null)";
4351*5e7646d2SAndroid Build Coastguard Worker 
4352*5e7646d2SAndroid Build Coastguard Worker     bytes = (ssize_t)strlen(s);
4353*5e7646d2SAndroid Build Coastguard Worker     strlcpy(buffer, s, sizeof(buffer));
4354*5e7646d2SAndroid Build Coastguard Worker   }
4355*5e7646d2SAndroid Build Coastguard Worker   else
4356*5e7646d2SAndroid Build Coastguard Worker   {
4357*5e7646d2SAndroid Build Coastguard Worker    /*
4358*5e7646d2SAndroid Build Coastguard Worker     * Do a full formatting of the message...
4359*5e7646d2SAndroid Build Coastguard Worker     */
4360*5e7646d2SAndroid Build Coastguard Worker 
4361*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = vsnprintf(buffer, sizeof(buffer), format, ap)) < 0)
4362*5e7646d2SAndroid Build Coastguard Worker       return (0);
4363*5e7646d2SAndroid Build Coastguard Worker   }
4364*5e7646d2SAndroid Build Coastguard Worker 
4365*5e7646d2SAndroid Build Coastguard Worker  /*
4366*5e7646d2SAndroid Build Coastguard Worker   * Limit the length of the string...
4367*5e7646d2SAndroid Build Coastguard Worker   */
4368*5e7646d2SAndroid Build Coastguard Worker 
4369*5e7646d2SAndroid Build Coastguard Worker   switch (value_tag)
4370*5e7646d2SAndroid Build Coastguard Worker   {
4371*5e7646d2SAndroid Build Coastguard Worker     default :
4372*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
4373*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
4374*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_TEXT;
4375*5e7646d2SAndroid Build Coastguard Worker         break;
4376*5e7646d2SAndroid Build Coastguard Worker 
4377*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
4378*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
4379*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_NAME;
4380*5e7646d2SAndroid Build Coastguard Worker         break;
4381*5e7646d2SAndroid Build Coastguard Worker 
4382*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
4383*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_CHARSET;
4384*5e7646d2SAndroid Build Coastguard Worker         break;
4385*5e7646d2SAndroid Build Coastguard Worker 
4386*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOVALUE :
4387*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNKNOWN :
4388*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
4389*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_KEYWORD;
4390*5e7646d2SAndroid Build Coastguard Worker         break;
4391*5e7646d2SAndroid Build Coastguard Worker 
4392*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
4393*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_LANGUAGE;
4394*5e7646d2SAndroid Build Coastguard Worker         break;
4395*5e7646d2SAndroid Build Coastguard Worker 
4396*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
4397*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_MIMETYPE;
4398*5e7646d2SAndroid Build Coastguard Worker         break;
4399*5e7646d2SAndroid Build Coastguard Worker 
4400*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
4401*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_URI;
4402*5e7646d2SAndroid Build Coastguard Worker         break;
4403*5e7646d2SAndroid Build Coastguard Worker 
4404*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
4405*5e7646d2SAndroid Build Coastguard Worker         max_bytes = IPP_MAX_URISCHEME;
4406*5e7646d2SAndroid Build Coastguard Worker         break;
4407*5e7646d2SAndroid Build Coastguard Worker   }
4408*5e7646d2SAndroid Build Coastguard Worker 
4409*5e7646d2SAndroid Build Coastguard Worker   if (bytes >= max_bytes)
4410*5e7646d2SAndroid Build Coastguard Worker   {
4411*5e7646d2SAndroid Build Coastguard Worker     char	*bufmax,		/* Buffer at max_bytes */
4412*5e7646d2SAndroid Build Coastguard Worker 		*bufptr;		/* Pointer into buffer */
4413*5e7646d2SAndroid Build Coastguard Worker 
4414*5e7646d2SAndroid Build Coastguard Worker     bufptr = buffer + strlen(buffer) - 1;
4415*5e7646d2SAndroid Build Coastguard Worker     bufmax = buffer + max_bytes - 1;
4416*5e7646d2SAndroid Build Coastguard Worker 
4417*5e7646d2SAndroid Build Coastguard Worker     while (bufptr > bufmax)
4418*5e7646d2SAndroid Build Coastguard Worker     {
4419*5e7646d2SAndroid Build Coastguard Worker       if (*bufptr & 0x80)
4420*5e7646d2SAndroid Build Coastguard Worker       {
4421*5e7646d2SAndroid Build Coastguard Worker         while ((*bufptr & 0xc0) == 0x80 && bufptr > buffer)
4422*5e7646d2SAndroid Build Coastguard Worker           bufptr --;
4423*5e7646d2SAndroid Build Coastguard Worker       }
4424*5e7646d2SAndroid Build Coastguard Worker 
4425*5e7646d2SAndroid Build Coastguard Worker       bufptr --;
4426*5e7646d2SAndroid Build Coastguard Worker     }
4427*5e7646d2SAndroid Build Coastguard Worker 
4428*5e7646d2SAndroid Build Coastguard Worker     *bufptr = '\0';
4429*5e7646d2SAndroid Build Coastguard Worker   }
4430*5e7646d2SAndroid Build Coastguard Worker 
4431*5e7646d2SAndroid Build Coastguard Worker  /*
4432*5e7646d2SAndroid Build Coastguard Worker   * Set the formatted string and return...
4433*5e7646d2SAndroid Build Coastguard Worker   */
4434*5e7646d2SAndroid Build Coastguard Worker 
4435*5e7646d2SAndroid Build Coastguard Worker   return (ippSetString(ipp, attr, element, buffer));
4436*5e7646d2SAndroid Build Coastguard Worker }
4437*5e7646d2SAndroid Build Coastguard Worker 
4438*5e7646d2SAndroid Build Coastguard Worker 
4439*5e7646d2SAndroid Build Coastguard Worker /*
4440*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetValueTag()' - Set the value tag of an attribute.
4441*5e7646d2SAndroid Build Coastguard Worker  *
4442*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4443*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4444*5e7646d2SAndroid Build Coastguard Worker  *
4445*5e7646d2SAndroid Build Coastguard Worker  * The @code attr@ parameter may be modified as a result of setting the value.
4446*5e7646d2SAndroid Build Coastguard Worker  *
4447*5e7646d2SAndroid Build Coastguard Worker  * Integer (@code IPP_TAG_INTEGER@) values can be promoted to rangeOfInteger
4448*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_RANGE@) values, the various string tags can be promoted to name
4449*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_NAME@) or nameWithLanguage (@code IPP_TAG_NAMELANG@) values, text
4450*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXT@) values can be promoted to textWithLanguage
4451*5e7646d2SAndroid Build Coastguard Worker  * (@code IPP_TAG_TEXTLANG@) values, and all values can be demoted to the various
4452*5e7646d2SAndroid Build Coastguard Worker  * out-of-band value tags such as no-value (@code IPP_TAG_NOVALUE@). All other changes
4453*5e7646d2SAndroid Build Coastguard Worker  * will be rejected.
4454*5e7646d2SAndroid Build Coastguard Worker  *
4455*5e7646d2SAndroid Build Coastguard Worker  * Promoting a string attribute to nameWithLanguage or textWithLanguage adds the language
4456*5e7646d2SAndroid Build Coastguard Worker  * code in the "attributes-natural-language" attribute or, if not present, the language
4457*5e7646d2SAndroid Build Coastguard Worker  * code for the current locale.
4458*5e7646d2SAndroid Build Coastguard Worker  *
4459*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4460*5e7646d2SAndroid Build Coastguard Worker  */
4461*5e7646d2SAndroid Build Coastguard Worker 
4462*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
ippSetValueTag(ipp_t * ipp,ipp_attribute_t ** attr,ipp_tag_t value_tag)4463*5e7646d2SAndroid Build Coastguard Worker ippSetValueTag(
4464*5e7646d2SAndroid Build Coastguard Worker     ipp_t          *ipp,		/* I  - IPP message */
4465*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t **attr,		/* IO - IPP attribute */
4466*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t       value_tag)		/* I  - Value tag */
4467*5e7646d2SAndroid Build Coastguard Worker {
4468*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
4469*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
4470*5e7646d2SAndroid Build Coastguard Worker   int		integer;		/* Current integer value */
4471*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t	*language;		/* Current language */
4472*5e7646d2SAndroid Build Coastguard Worker   char		code[32];		/* Language code */
4473*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	temp_tag;		/* Temporary value tag */
4474*5e7646d2SAndroid Build Coastguard Worker 
4475*5e7646d2SAndroid Build Coastguard Worker 
4476*5e7646d2SAndroid Build Coastguard Worker  /*
4477*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4478*5e7646d2SAndroid Build Coastguard Worker   */
4479*5e7646d2SAndroid Build Coastguard Worker 
4480*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || !attr || !*attr)
4481*5e7646d2SAndroid Build Coastguard Worker     return (0);
4482*5e7646d2SAndroid Build Coastguard Worker 
4483*5e7646d2SAndroid Build Coastguard Worker  /*
4484*5e7646d2SAndroid Build Coastguard Worker   * If there is no change, return immediately...
4485*5e7646d2SAndroid Build Coastguard Worker   */
4486*5e7646d2SAndroid Build Coastguard Worker 
4487*5e7646d2SAndroid Build Coastguard Worker   if (value_tag == (*attr)->value_tag)
4488*5e7646d2SAndroid Build Coastguard Worker     return (1);
4489*5e7646d2SAndroid Build Coastguard Worker 
4490*5e7646d2SAndroid Build Coastguard Worker  /*
4491*5e7646d2SAndroid Build Coastguard Worker   * Otherwise implement changes as needed...
4492*5e7646d2SAndroid Build Coastguard Worker   */
4493*5e7646d2SAndroid Build Coastguard Worker 
4494*5e7646d2SAndroid Build Coastguard Worker   temp_tag = (ipp_tag_t)((int)((*attr)->value_tag) & IPP_TAG_CUPS_MASK);
4495*5e7646d2SAndroid Build Coastguard Worker 
4496*5e7646d2SAndroid Build Coastguard Worker   switch (value_tag)
4497*5e7646d2SAndroid Build Coastguard Worker   {
4498*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNSUPPORTED_VALUE :
4499*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DEFAULT :
4500*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNKNOWN :
4501*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOVALUE :
4502*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOTSETTABLE :
4503*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DELETEATTR :
4504*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ADMINDEFINE :
4505*5e7646d2SAndroid Build Coastguard Worker        /*
4506*5e7646d2SAndroid Build Coastguard Worker         * Free any existing values...
4507*5e7646d2SAndroid Build Coastguard Worker         */
4508*5e7646d2SAndroid Build Coastguard Worker 
4509*5e7646d2SAndroid Build Coastguard Worker         if ((*attr)->num_values > 0)
4510*5e7646d2SAndroid Build Coastguard Worker           ipp_free_values(*attr, 0, (*attr)->num_values);
4511*5e7646d2SAndroid Build Coastguard Worker 
4512*5e7646d2SAndroid Build Coastguard Worker        /*
4513*5e7646d2SAndroid Build Coastguard Worker         * Set out-of-band value...
4514*5e7646d2SAndroid Build Coastguard Worker         */
4515*5e7646d2SAndroid Build Coastguard Worker 
4516*5e7646d2SAndroid Build Coastguard Worker         (*attr)->value_tag = value_tag;
4517*5e7646d2SAndroid Build Coastguard Worker         break;
4518*5e7646d2SAndroid Build Coastguard Worker 
4519*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
4520*5e7646d2SAndroid Build Coastguard Worker         if (temp_tag != IPP_TAG_INTEGER)
4521*5e7646d2SAndroid Build Coastguard Worker           return (0);
4522*5e7646d2SAndroid Build Coastguard Worker 
4523*5e7646d2SAndroid Build Coastguard Worker         for (i = (*attr)->num_values, value = (*attr)->values;
4524*5e7646d2SAndroid Build Coastguard Worker              i > 0;
4525*5e7646d2SAndroid Build Coastguard Worker              i --, value ++)
4526*5e7646d2SAndroid Build Coastguard Worker         {
4527*5e7646d2SAndroid Build Coastguard Worker           integer            = value->integer;
4528*5e7646d2SAndroid Build Coastguard Worker           value->range.lower = value->range.upper = integer;
4529*5e7646d2SAndroid Build Coastguard Worker         }
4530*5e7646d2SAndroid Build Coastguard Worker 
4531*5e7646d2SAndroid Build Coastguard Worker         (*attr)->value_tag = IPP_TAG_RANGE;
4532*5e7646d2SAndroid Build Coastguard Worker         break;
4533*5e7646d2SAndroid Build Coastguard Worker 
4534*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
4535*5e7646d2SAndroid Build Coastguard Worker         if (temp_tag != IPP_TAG_KEYWORD)
4536*5e7646d2SAndroid Build Coastguard Worker           return (0);
4537*5e7646d2SAndroid Build Coastguard Worker 
4538*5e7646d2SAndroid Build Coastguard Worker         (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_CUPS_CONST));
4539*5e7646d2SAndroid Build Coastguard Worker         break;
4540*5e7646d2SAndroid Build Coastguard Worker 
4541*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
4542*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
4543*5e7646d2SAndroid Build Coastguard Worker         if (value_tag == IPP_TAG_NAMELANG && (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD))
4544*5e7646d2SAndroid Build Coastguard Worker           return (0);
4545*5e7646d2SAndroid Build Coastguard Worker 
4546*5e7646d2SAndroid Build Coastguard Worker         if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT)
4547*5e7646d2SAndroid Build Coastguard Worker           return (0);
4548*5e7646d2SAndroid Build Coastguard Worker 
4549*5e7646d2SAndroid Build Coastguard Worker         if (ipp->attrs && ipp->attrs->next && ipp->attrs->next->name &&
4550*5e7646d2SAndroid Build Coastguard Worker             !strcmp(ipp->attrs->next->name, "attributes-natural-language") && (ipp->attrs->next->value_tag & IPP_TAG_CUPS_MASK) == IPP_TAG_LANGUAGE)
4551*5e7646d2SAndroid Build Coastguard Worker         {
4552*5e7646d2SAndroid Build Coastguard Worker          /*
4553*5e7646d2SAndroid Build Coastguard Worker           * Use the language code from the IPP message...
4554*5e7646d2SAndroid Build Coastguard Worker           */
4555*5e7646d2SAndroid Build Coastguard Worker 
4556*5e7646d2SAndroid Build Coastguard Worker 	  (*attr)->values[0].string.language =
4557*5e7646d2SAndroid Build Coastguard Worker 	      _cupsStrAlloc(ipp->attrs->next->values[0].string.text);
4558*5e7646d2SAndroid Build Coastguard Worker         }
4559*5e7646d2SAndroid Build Coastguard Worker         else
4560*5e7646d2SAndroid Build Coastguard Worker         {
4561*5e7646d2SAndroid Build Coastguard Worker          /*
4562*5e7646d2SAndroid Build Coastguard Worker           * Otherwise, use the language code corresponding to the locale...
4563*5e7646d2SAndroid Build Coastguard Worker           */
4564*5e7646d2SAndroid Build Coastguard Worker 
4565*5e7646d2SAndroid Build Coastguard Worker 	  language = cupsLangDefault();
4566*5e7646d2SAndroid Build Coastguard Worker 	  (*attr)->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language->language,
4567*5e7646d2SAndroid Build Coastguard Worker 									code,
4568*5e7646d2SAndroid Build Coastguard Worker 									sizeof(code)));
4569*5e7646d2SAndroid Build Coastguard Worker         }
4570*5e7646d2SAndroid Build Coastguard Worker 
4571*5e7646d2SAndroid Build Coastguard Worker         for (i = (*attr)->num_values - 1, value = (*attr)->values + 1;
4572*5e7646d2SAndroid Build Coastguard Worker              i > 0;
4573*5e7646d2SAndroid Build Coastguard Worker              i --, value ++)
4574*5e7646d2SAndroid Build Coastguard Worker           value->string.language = (*attr)->values[0].string.language;
4575*5e7646d2SAndroid Build Coastguard Worker 
4576*5e7646d2SAndroid Build Coastguard Worker         if ((int)(*attr)->value_tag & IPP_TAG_CUPS_CONST)
4577*5e7646d2SAndroid Build Coastguard Worker         {
4578*5e7646d2SAndroid Build Coastguard Worker          /*
4579*5e7646d2SAndroid Build Coastguard Worker           * Make copies of all values...
4580*5e7646d2SAndroid Build Coastguard Worker           */
4581*5e7646d2SAndroid Build Coastguard Worker 
4582*5e7646d2SAndroid Build Coastguard Worker 	  for (i = (*attr)->num_values, value = (*attr)->values;
4583*5e7646d2SAndroid Build Coastguard Worker 	       i > 0;
4584*5e7646d2SAndroid Build Coastguard Worker 	       i --, value ++)
4585*5e7646d2SAndroid Build Coastguard Worker 	    value->string.text = _cupsStrAlloc(value->string.text);
4586*5e7646d2SAndroid Build Coastguard Worker         }
4587*5e7646d2SAndroid Build Coastguard Worker 
4588*5e7646d2SAndroid Build Coastguard Worker         (*attr)->value_tag = IPP_TAG_NAMELANG;
4589*5e7646d2SAndroid Build Coastguard Worker         break;
4590*5e7646d2SAndroid Build Coastguard Worker 
4591*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
4592*5e7646d2SAndroid Build Coastguard Worker         if (temp_tag == IPP_TAG_NAME || temp_tag == IPP_TAG_NAMELANG)
4593*5e7646d2SAndroid Build Coastguard Worker           break;			/* Silently "allow" name -> keyword */
4594*5e7646d2SAndroid Build Coastguard Worker 
4595*5e7646d2SAndroid Build Coastguard Worker     default :
4596*5e7646d2SAndroid Build Coastguard Worker         return (0);
4597*5e7646d2SAndroid Build Coastguard Worker   }
4598*5e7646d2SAndroid Build Coastguard Worker 
4599*5e7646d2SAndroid Build Coastguard Worker   return (1);
4600*5e7646d2SAndroid Build Coastguard Worker }
4601*5e7646d2SAndroid Build Coastguard Worker 
4602*5e7646d2SAndroid Build Coastguard Worker 
4603*5e7646d2SAndroid Build Coastguard Worker /*
4604*5e7646d2SAndroid Build Coastguard Worker  * 'ippSetVersion()' - Set the version number in an IPP message.
4605*5e7646d2SAndroid Build Coastguard Worker  *
4606*5e7646d2SAndroid Build Coastguard Worker  * The @code ipp@ parameter refers to an IPP message previously created using
4607*5e7646d2SAndroid Build Coastguard Worker  * the @link ippNew@, @link ippNewRequest@, or  @link ippNewResponse@ functions.
4608*5e7646d2SAndroid Build Coastguard Worker  *
4609*5e7646d2SAndroid Build Coastguard Worker  * The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2.
4610*5e7646d2SAndroid Build Coastguard Worker  *
4611*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
4612*5e7646d2SAndroid Build Coastguard Worker  */
4613*5e7646d2SAndroid Build Coastguard Worker 
4614*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
ippSetVersion(ipp_t * ipp,int major,int minor)4615*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(ipp_t *ipp,		/* I - IPP message */
4616*5e7646d2SAndroid Build Coastguard Worker               int   major,		/* I - Major version number (major.minor) */
4617*5e7646d2SAndroid Build Coastguard Worker               int   minor)		/* I - Minor version number (major.minor) */
4618*5e7646d2SAndroid Build Coastguard Worker {
4619*5e7646d2SAndroid Build Coastguard Worker  /*
4620*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4621*5e7646d2SAndroid Build Coastguard Worker   */
4622*5e7646d2SAndroid Build Coastguard Worker 
4623*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || major < 0 || minor < 0)
4624*5e7646d2SAndroid Build Coastguard Worker     return (0);
4625*5e7646d2SAndroid Build Coastguard Worker 
4626*5e7646d2SAndroid Build Coastguard Worker  /*
4627*5e7646d2SAndroid Build Coastguard Worker   * Set the version number...
4628*5e7646d2SAndroid Build Coastguard Worker   */
4629*5e7646d2SAndroid Build Coastguard Worker 
4630*5e7646d2SAndroid Build Coastguard Worker   ipp->request.any.version[0] = (ipp_uchar_t)major;
4631*5e7646d2SAndroid Build Coastguard Worker   ipp->request.any.version[1] = (ipp_uchar_t)minor;
4632*5e7646d2SAndroid Build Coastguard Worker 
4633*5e7646d2SAndroid Build Coastguard Worker   return (1);
4634*5e7646d2SAndroid Build Coastguard Worker }
4635*5e7646d2SAndroid Build Coastguard Worker 
4636*5e7646d2SAndroid Build Coastguard Worker 
4637*5e7646d2SAndroid Build Coastguard Worker /*
4638*5e7646d2SAndroid Build Coastguard Worker  * 'ippTimeToDate()' - Convert from time in seconds to RFC 2579 format.
4639*5e7646d2SAndroid Build Coastguard Worker  */
4640*5e7646d2SAndroid Build Coastguard Worker 
4641*5e7646d2SAndroid Build Coastguard Worker const ipp_uchar_t *			/* O - RFC-2579 date/time data */
ippTimeToDate(time_t t)4642*5e7646d2SAndroid Build Coastguard Worker ippTimeToDate(time_t t)			/* I - Time in seconds */
4643*5e7646d2SAndroid Build Coastguard Worker {
4644*5e7646d2SAndroid Build Coastguard Worker   struct tm	unixdate;		/* UNIX unixdate/time info */
4645*5e7646d2SAndroid Build Coastguard Worker   ipp_uchar_t	*date = _cupsGlobals()->ipp_date;
4646*5e7646d2SAndroid Build Coastguard Worker 					/* RFC-2579 date/time data */
4647*5e7646d2SAndroid Build Coastguard Worker 
4648*5e7646d2SAndroid Build Coastguard Worker 
4649*5e7646d2SAndroid Build Coastguard Worker  /*
4650*5e7646d2SAndroid Build Coastguard Worker   * RFC-2579 date/time format is:
4651*5e7646d2SAndroid Build Coastguard Worker   *
4652*5e7646d2SAndroid Build Coastguard Worker   *    Byte(s)  Description
4653*5e7646d2SAndroid Build Coastguard Worker   *    -------  -----------
4654*5e7646d2SAndroid Build Coastguard Worker   *    0-1      Year (0 to 65535)
4655*5e7646d2SAndroid Build Coastguard Worker   *    2        Month (1 to 12)
4656*5e7646d2SAndroid Build Coastguard Worker   *    3        Day (1 to 31)
4657*5e7646d2SAndroid Build Coastguard Worker   *    4        Hours (0 to 23)
4658*5e7646d2SAndroid Build Coastguard Worker   *    5        Minutes (0 to 59)
4659*5e7646d2SAndroid Build Coastguard Worker   *    6        Seconds (0 to 60, 60 = "leap second")
4660*5e7646d2SAndroid Build Coastguard Worker   *    7        Deciseconds (0 to 9)
4661*5e7646d2SAndroid Build Coastguard Worker   *    8        +/- UTC
4662*5e7646d2SAndroid Build Coastguard Worker   *    9        UTC hours (0 to 11)
4663*5e7646d2SAndroid Build Coastguard Worker   *    10       UTC minutes (0 to 59)
4664*5e7646d2SAndroid Build Coastguard Worker   */
4665*5e7646d2SAndroid Build Coastguard Worker 
4666*5e7646d2SAndroid Build Coastguard Worker   gmtime_r(&t, &unixdate);
4667*5e7646d2SAndroid Build Coastguard Worker   unixdate.tm_year += 1900;
4668*5e7646d2SAndroid Build Coastguard Worker 
4669*5e7646d2SAndroid Build Coastguard Worker   date[0]  = (ipp_uchar_t)(unixdate.tm_year >> 8);
4670*5e7646d2SAndroid Build Coastguard Worker   date[1]  = (ipp_uchar_t)(unixdate.tm_year);
4671*5e7646d2SAndroid Build Coastguard Worker   date[2]  = (ipp_uchar_t)(unixdate.tm_mon + 1);
4672*5e7646d2SAndroid Build Coastguard Worker   date[3]  = (ipp_uchar_t)unixdate.tm_mday;
4673*5e7646d2SAndroid Build Coastguard Worker   date[4]  = (ipp_uchar_t)unixdate.tm_hour;
4674*5e7646d2SAndroid Build Coastguard Worker   date[5]  = (ipp_uchar_t)unixdate.tm_min;
4675*5e7646d2SAndroid Build Coastguard Worker   date[6]  = (ipp_uchar_t)unixdate.tm_sec;
4676*5e7646d2SAndroid Build Coastguard Worker   date[7]  = 0;
4677*5e7646d2SAndroid Build Coastguard Worker   date[8]  = '+';
4678*5e7646d2SAndroid Build Coastguard Worker   date[9]  = 0;
4679*5e7646d2SAndroid Build Coastguard Worker   date[10] = 0;
4680*5e7646d2SAndroid Build Coastguard Worker 
4681*5e7646d2SAndroid Build Coastguard Worker   return (date);
4682*5e7646d2SAndroid Build Coastguard Worker }
4683*5e7646d2SAndroid Build Coastguard Worker 
4684*5e7646d2SAndroid Build Coastguard Worker 
4685*5e7646d2SAndroid Build Coastguard Worker /*
4686*5e7646d2SAndroid Build Coastguard Worker  * 'ippValidateAttribute()' - Validate the contents of an attribute.
4687*5e7646d2SAndroid Build Coastguard Worker  *
4688*5e7646d2SAndroid Build Coastguard Worker  * This function validates the contents of an attribute based on the name and
4689*5e7646d2SAndroid Build Coastguard Worker  * value tag.  1 is returned if the attribute is valid, 0 otherwise.  On
4690*5e7646d2SAndroid Build Coastguard Worker  * failure, @link cupsLastErrorString@ is set to a human-readable message.
4691*5e7646d2SAndroid Build Coastguard Worker  *
4692*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
4693*5e7646d2SAndroid Build Coastguard Worker  */
4694*5e7646d2SAndroid Build Coastguard Worker 
4695*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if valid, 0 otherwise */
ippValidateAttribute(ipp_attribute_t * attr)4696*5e7646d2SAndroid Build Coastguard Worker ippValidateAttribute(
4697*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr)		/* I - Attribute */
4698*5e7646d2SAndroid Build Coastguard Worker {
4699*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
4700*5e7646d2SAndroid Build Coastguard Worker   char		scheme[64],		/* Scheme from URI */
4701*5e7646d2SAndroid Build Coastguard Worker 		userpass[256],		/* Username/password from URI */
4702*5e7646d2SAndroid Build Coastguard Worker 		hostname[256],		/* Hostname from URI */
4703*5e7646d2SAndroid Build Coastguard Worker 		resource[1024];		/* Resource from URI */
4704*5e7646d2SAndroid Build Coastguard Worker   int		port,			/* Port number from URI */
4705*5e7646d2SAndroid Build Coastguard Worker 		uri_status;		/* URI separation status */
4706*5e7646d2SAndroid Build Coastguard Worker   const char	*ptr;			/* Pointer into string */
4707*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *colattr;		/* Collection attribute */
4708*5e7646d2SAndroid Build Coastguard Worker   regex_t	re;			/* Regular expression */
4709*5e7646d2SAndroid Build Coastguard Worker   ipp_uchar_t	*date;			/* Current date value */
4710*5e7646d2SAndroid Build Coastguard Worker 
4711*5e7646d2SAndroid Build Coastguard Worker 
4712*5e7646d2SAndroid Build Coastguard Worker  /*
4713*5e7646d2SAndroid Build Coastguard Worker   * Skip separators.
4714*5e7646d2SAndroid Build Coastguard Worker   */
4715*5e7646d2SAndroid Build Coastguard Worker 
4716*5e7646d2SAndroid Build Coastguard Worker   if (!attr->name)
4717*5e7646d2SAndroid Build Coastguard Worker     return (1);
4718*5e7646d2SAndroid Build Coastguard Worker 
4719*5e7646d2SAndroid Build Coastguard Worker  /*
4720*5e7646d2SAndroid Build Coastguard Worker   * Validate the attribute name.
4721*5e7646d2SAndroid Build Coastguard Worker   */
4722*5e7646d2SAndroid Build Coastguard Worker 
4723*5e7646d2SAndroid Build Coastguard Worker   for (ptr = attr->name; *ptr; ptr ++)
4724*5e7646d2SAndroid Build Coastguard Worker     if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' && *ptr != '_')
4725*5e7646d2SAndroid Build Coastguard Worker       break;
4726*5e7646d2SAndroid Build Coastguard Worker 
4727*5e7646d2SAndroid Build Coastguard Worker   if (*ptr || ptr == attr->name)
4728*5e7646d2SAndroid Build Coastguard Worker   {
4729*5e7646d2SAndroid Build Coastguard Worker     ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad attribute name - invalid character (RFC 8011 section 5.1.4)."), attr->name);
4730*5e7646d2SAndroid Build Coastguard Worker     return (0);
4731*5e7646d2SAndroid Build Coastguard Worker   }
4732*5e7646d2SAndroid Build Coastguard Worker 
4733*5e7646d2SAndroid Build Coastguard Worker   if ((ptr - attr->name) > 255)
4734*5e7646d2SAndroid Build Coastguard Worker   {
4735*5e7646d2SAndroid Build Coastguard Worker     ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad attribute name - bad length %d (RFC 8011 section 5.1.4)."), attr->name, (int)(ptr - attr->name));
4736*5e7646d2SAndroid Build Coastguard Worker     return (0);
4737*5e7646d2SAndroid Build Coastguard Worker   }
4738*5e7646d2SAndroid Build Coastguard Worker 
4739*5e7646d2SAndroid Build Coastguard Worker   switch (attr->value_tag)
4740*5e7646d2SAndroid Build Coastguard Worker   {
4741*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
4742*5e7646d2SAndroid Build Coastguard Worker         break;
4743*5e7646d2SAndroid Build Coastguard Worker 
4744*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BOOLEAN :
4745*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4746*5e7646d2SAndroid Build Coastguard Worker 	{
4747*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].boolean != 0 &&
4748*5e7646d2SAndroid Build Coastguard Worker 	      attr->values[i].boolean != 1)
4749*5e7646d2SAndroid Build Coastguard Worker 	  {
4750*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad boolean value %d (RFC 8011 section 5.1.21)."), attr->name, attr->values[i].boolean);
4751*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4752*5e7646d2SAndroid Build Coastguard Worker 	  }
4753*5e7646d2SAndroid Build Coastguard Worker 	}
4754*5e7646d2SAndroid Build Coastguard Worker         break;
4755*5e7646d2SAndroid Build Coastguard Worker 
4756*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
4757*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4758*5e7646d2SAndroid Build Coastguard Worker 	{
4759*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].integer < 1)
4760*5e7646d2SAndroid Build Coastguard Worker 	  {
4761*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad enum value %d - out of range (RFC 8011 section 5.1.5)."), attr->name, attr->values[i].integer);
4762*5e7646d2SAndroid Build Coastguard Worker             return (0);
4763*5e7646d2SAndroid Build Coastguard Worker 	  }
4764*5e7646d2SAndroid Build Coastguard Worker 	}
4765*5e7646d2SAndroid Build Coastguard Worker         break;
4766*5e7646d2SAndroid Build Coastguard Worker 
4767*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_STRING :
4768*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4769*5e7646d2SAndroid Build Coastguard Worker 	{
4770*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].unknown.length > IPP_MAX_OCTETSTRING)
4771*5e7646d2SAndroid Build Coastguard Worker 	  {
4772*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad octetString value - bad length %d (RFC 8011 section 5.1.20)."), attr->name, attr->values[i].unknown.length);
4773*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4774*5e7646d2SAndroid Build Coastguard Worker 	  }
4775*5e7646d2SAndroid Build Coastguard Worker 	}
4776*5e7646d2SAndroid Build Coastguard Worker         break;
4777*5e7646d2SAndroid Build Coastguard Worker 
4778*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DATE :
4779*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4780*5e7646d2SAndroid Build Coastguard Worker 	{
4781*5e7646d2SAndroid Build Coastguard Worker 	  date = attr->values[i].date;
4782*5e7646d2SAndroid Build Coastguard Worker 
4783*5e7646d2SAndroid Build Coastguard Worker           if (date[2] < 1 || date[2] > 12)
4784*5e7646d2SAndroid Build Coastguard Worker 	  {
4785*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime month %u (RFC 8011 section 5.1.15)."), attr->name, date[2]);
4786*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4787*5e7646d2SAndroid Build Coastguard Worker 	  }
4788*5e7646d2SAndroid Build Coastguard Worker 
4789*5e7646d2SAndroid Build Coastguard Worker           if (date[3] < 1 || date[3] > 31)
4790*5e7646d2SAndroid Build Coastguard Worker 	  {
4791*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime day %u (RFC 8011 section 5.1.15)."), attr->name, date[3]);
4792*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4793*5e7646d2SAndroid Build Coastguard Worker 	  }
4794*5e7646d2SAndroid Build Coastguard Worker 
4795*5e7646d2SAndroid Build Coastguard Worker           if (date[4] > 23)
4796*5e7646d2SAndroid Build Coastguard Worker 	  {
4797*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime hours %u (RFC 8011 section 5.1.15)."), attr->name, date[4]);
4798*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4799*5e7646d2SAndroid Build Coastguard Worker 	  }
4800*5e7646d2SAndroid Build Coastguard Worker 
4801*5e7646d2SAndroid Build Coastguard Worker           if (date[5] > 59)
4802*5e7646d2SAndroid Build Coastguard Worker 	  {
4803*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime minutes %u (RFC 8011 section 5.1.15)."), attr->name, date[5]);
4804*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4805*5e7646d2SAndroid Build Coastguard Worker 	  }
4806*5e7646d2SAndroid Build Coastguard Worker 
4807*5e7646d2SAndroid Build Coastguard Worker           if (date[6] > 60)
4808*5e7646d2SAndroid Build Coastguard Worker 	  {
4809*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime seconds %u (RFC 8011 section 5.1.15)."), attr->name, date[6]);
4810*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4811*5e7646d2SAndroid Build Coastguard Worker 	  }
4812*5e7646d2SAndroid Build Coastguard Worker 
4813*5e7646d2SAndroid Build Coastguard Worker           if (date[7] > 9)
4814*5e7646d2SAndroid Build Coastguard Worker 	  {
4815*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime deciseconds %u (RFC 8011 section 5.1.15)."), attr->name, date[7]);
4816*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4817*5e7646d2SAndroid Build Coastguard Worker 	  }
4818*5e7646d2SAndroid Build Coastguard Worker 
4819*5e7646d2SAndroid Build Coastguard Worker           if (date[8] != '-' && date[8] != '+')
4820*5e7646d2SAndroid Build Coastguard Worker 	  {
4821*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime UTC sign '%c' (RFC 8011 section 5.1.15)."), attr->name, date[8]);
4822*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4823*5e7646d2SAndroid Build Coastguard Worker 	  }
4824*5e7646d2SAndroid Build Coastguard Worker 
4825*5e7646d2SAndroid Build Coastguard Worker           if (date[9] > 11)
4826*5e7646d2SAndroid Build Coastguard Worker 	  {
4827*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime UTC hours %u (RFC 8011 section 5.1.15)."), attr->name, date[9]);
4828*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4829*5e7646d2SAndroid Build Coastguard Worker 	  }
4830*5e7646d2SAndroid Build Coastguard Worker 
4831*5e7646d2SAndroid Build Coastguard Worker           if (date[10] > 59)
4832*5e7646d2SAndroid Build Coastguard Worker 	  {
4833*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad dateTime UTC minutes %u (RFC 8011 section 5.1.15)."), attr->name, date[10]);
4834*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4835*5e7646d2SAndroid Build Coastguard Worker 	  }
4836*5e7646d2SAndroid Build Coastguard Worker 	}
4837*5e7646d2SAndroid Build Coastguard Worker         break;
4838*5e7646d2SAndroid Build Coastguard Worker 
4839*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
4840*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4841*5e7646d2SAndroid Build Coastguard Worker 	{
4842*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].resolution.xres <= 0)
4843*5e7646d2SAndroid Build Coastguard Worker 	  {
4844*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad resolution value %dx%d%s - cross feed resolution must be positive (RFC 8011 section 5.1.16)."), attr->name, attr->values[i].resolution.xres, attr->values[i].resolution.yres, attr->values[i].resolution.units == IPP_RES_PER_INCH ? "dpi" : attr->values[i].resolution.units == IPP_RES_PER_CM ? "dpcm" : "unknown");
4845*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4846*5e7646d2SAndroid Build Coastguard Worker 	  }
4847*5e7646d2SAndroid Build Coastguard Worker 
4848*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].resolution.yres <= 0)
4849*5e7646d2SAndroid Build Coastguard Worker 	  {
4850*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad resolution value %dx%d%s - feed resolution must be positive (RFC 8011 section 5.1.16)."), attr->name, attr->values[i].resolution.xres, attr->values[i].resolution.yres, attr->values[i].resolution.units == IPP_RES_PER_INCH ? "dpi" : attr->values[i].resolution.units == IPP_RES_PER_CM ? "dpcm" : "unknown");
4851*5e7646d2SAndroid Build Coastguard Worker             return (0);
4852*5e7646d2SAndroid Build Coastguard Worker 	  }
4853*5e7646d2SAndroid Build Coastguard Worker 
4854*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].resolution.units != IPP_RES_PER_INCH && attr->values[i].resolution.units != IPP_RES_PER_CM)
4855*5e7646d2SAndroid Build Coastguard Worker 	  {
4856*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad resolution value %dx%d%s - bad units value (RFC 8011 section 5.1.16)."), attr->name, attr->values[i].resolution.xres, attr->values[i].resolution.yres, attr->values[i].resolution.units == IPP_RES_PER_INCH ? "dpi" : attr->values[i].resolution.units == IPP_RES_PER_CM ? "dpcm" : "unknown");
4857*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4858*5e7646d2SAndroid Build Coastguard Worker 	  }
4859*5e7646d2SAndroid Build Coastguard Worker 	}
4860*5e7646d2SAndroid Build Coastguard Worker         break;
4861*5e7646d2SAndroid Build Coastguard Worker 
4862*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
4863*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4864*5e7646d2SAndroid Build Coastguard Worker 	{
4865*5e7646d2SAndroid Build Coastguard Worker 	  if (attr->values[i].range.lower > attr->values[i].range.upper)
4866*5e7646d2SAndroid Build Coastguard Worker 	  {
4867*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad rangeOfInteger value %d-%d - lower greater than upper (RFC 8011 section 5.1.14)."), attr->name, attr->values[i].range.lower, attr->values[i].range.upper);
4868*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4869*5e7646d2SAndroid Build Coastguard Worker 	  }
4870*5e7646d2SAndroid Build Coastguard Worker 	}
4871*5e7646d2SAndroid Build Coastguard Worker         break;
4872*5e7646d2SAndroid Build Coastguard Worker 
4873*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BEGIN_COLLECTION :
4874*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4875*5e7646d2SAndroid Build Coastguard Worker 	{
4876*5e7646d2SAndroid Build Coastguard Worker 	  for (colattr = attr->values[i].collection->attrs;
4877*5e7646d2SAndroid Build Coastguard Worker 	       colattr;
4878*5e7646d2SAndroid Build Coastguard Worker 	       colattr = colattr->next)
4879*5e7646d2SAndroid Build Coastguard Worker 	  {
4880*5e7646d2SAndroid Build Coastguard Worker 	    if (!ippValidateAttribute(colattr))
4881*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
4882*5e7646d2SAndroid Build Coastguard Worker 	  }
4883*5e7646d2SAndroid Build Coastguard Worker 	}
4884*5e7646d2SAndroid Build Coastguard Worker         break;
4885*5e7646d2SAndroid Build Coastguard Worker 
4886*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
4887*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
4888*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4889*5e7646d2SAndroid Build Coastguard Worker 	{
4890*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = attr->values[i].string.text; *ptr; ptr ++)
4891*5e7646d2SAndroid Build Coastguard Worker 	  {
4892*5e7646d2SAndroid Build Coastguard Worker 	    if ((*ptr & 0xe0) == 0xc0)
4893*5e7646d2SAndroid Build Coastguard Worker 	    {
4894*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80)
4895*5e7646d2SAndroid Build Coastguard Worker 	        break;
4896*5e7646d2SAndroid Build Coastguard Worker 
4897*5e7646d2SAndroid Build Coastguard Worker 	      ptr ++;
4898*5e7646d2SAndroid Build Coastguard Worker 	    }
4899*5e7646d2SAndroid Build Coastguard Worker 	    else if ((*ptr & 0xf0) == 0xe0)
4900*5e7646d2SAndroid Build Coastguard Worker 	    {
4901*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80 || (ptr[2] & 0xc0) != 0x80)
4902*5e7646d2SAndroid Build Coastguard Worker 	        break;
4903*5e7646d2SAndroid Build Coastguard Worker 
4904*5e7646d2SAndroid Build Coastguard Worker 	      ptr += 2;
4905*5e7646d2SAndroid Build Coastguard Worker 	    }
4906*5e7646d2SAndroid Build Coastguard Worker 	    else if ((*ptr & 0xf8) == 0xf0)
4907*5e7646d2SAndroid Build Coastguard Worker 	    {
4908*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80 || (ptr[2] & 0xc0) != 0x80 || (ptr[3] & 0xc0) != 0x80)
4909*5e7646d2SAndroid Build Coastguard Worker 	        break;
4910*5e7646d2SAndroid Build Coastguard Worker 
4911*5e7646d2SAndroid Build Coastguard Worker 	      ptr += 3;
4912*5e7646d2SAndroid Build Coastguard Worker 	    }
4913*5e7646d2SAndroid Build Coastguard Worker 	    else if (*ptr & 0x80)
4914*5e7646d2SAndroid Build Coastguard Worker 	      break;
4915*5e7646d2SAndroid Build Coastguard Worker 	    else if ((*ptr < ' ' && *ptr != '\n' && *ptr != '\r' && *ptr != '\t') || *ptr == 0x7f)
4916*5e7646d2SAndroid Build Coastguard Worker 	      break;
4917*5e7646d2SAndroid Build Coastguard Worker 	  }
4918*5e7646d2SAndroid Build Coastguard Worker 
4919*5e7646d2SAndroid Build Coastguard Worker           if (*ptr)
4920*5e7646d2SAndroid Build Coastguard Worker           {
4921*5e7646d2SAndroid Build Coastguard Worker 	    if (*ptr < ' ' || *ptr == 0x7f)
4922*5e7646d2SAndroid Build Coastguard Worker 	    {
4923*5e7646d2SAndroid Build Coastguard Worker 	      ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad text value \"%s\" - bad control character (PWG 5100.14 section 8.3)."), attr->name, attr->values[i].string.text);
4924*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
4925*5e7646d2SAndroid Build Coastguard Worker 	    }
4926*5e7646d2SAndroid Build Coastguard Worker 	    else
4927*5e7646d2SAndroid Build Coastguard Worker 	    {
4928*5e7646d2SAndroid Build Coastguard Worker 	      ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad text value \"%s\" - bad UTF-8 sequence (RFC 8011 section 5.1.2)."), attr->name, attr->values[i].string.text);
4929*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
4930*5e7646d2SAndroid Build Coastguard Worker 	    }
4931*5e7646d2SAndroid Build Coastguard Worker           }
4932*5e7646d2SAndroid Build Coastguard Worker 
4933*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr - attr->values[i].string.text) > (IPP_MAX_TEXT - 1))
4934*5e7646d2SAndroid Build Coastguard Worker 	  {
4935*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad text value \"%s\" - bad length %d (RFC 8011 section 5.1.2)."), attr->name, attr->values[i].string.text, (int)(ptr - attr->values[i].string.text));
4936*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4937*5e7646d2SAndroid Build Coastguard Worker 	  }
4938*5e7646d2SAndroid Build Coastguard Worker 	}
4939*5e7646d2SAndroid Build Coastguard Worker         break;
4940*5e7646d2SAndroid Build Coastguard Worker 
4941*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
4942*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
4943*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4944*5e7646d2SAndroid Build Coastguard Worker 	{
4945*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = attr->values[i].string.text; *ptr; ptr ++)
4946*5e7646d2SAndroid Build Coastguard Worker 	  {
4947*5e7646d2SAndroid Build Coastguard Worker 	    if ((*ptr & 0xe0) == 0xc0)
4948*5e7646d2SAndroid Build Coastguard Worker 	    {
4949*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80)
4950*5e7646d2SAndroid Build Coastguard Worker 	        break;
4951*5e7646d2SAndroid Build Coastguard Worker 
4952*5e7646d2SAndroid Build Coastguard Worker 	      ptr ++;
4953*5e7646d2SAndroid Build Coastguard Worker 	    }
4954*5e7646d2SAndroid Build Coastguard Worker 	    else if ((*ptr & 0xf0) == 0xe0)
4955*5e7646d2SAndroid Build Coastguard Worker 	    {
4956*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80 || (ptr[2] & 0xc0) != 0x80)
4957*5e7646d2SAndroid Build Coastguard Worker 	        break;
4958*5e7646d2SAndroid Build Coastguard Worker 
4959*5e7646d2SAndroid Build Coastguard Worker 	      ptr += 2;
4960*5e7646d2SAndroid Build Coastguard Worker 	    }
4961*5e7646d2SAndroid Build Coastguard Worker 	    else if ((*ptr & 0xf8) == 0xf0)
4962*5e7646d2SAndroid Build Coastguard Worker 	    {
4963*5e7646d2SAndroid Build Coastguard Worker 	      if ((ptr[1] & 0xc0) != 0x80 || (ptr[2] & 0xc0) != 0x80 || (ptr[3] & 0xc0) != 0x80)
4964*5e7646d2SAndroid Build Coastguard Worker 	        break;
4965*5e7646d2SAndroid Build Coastguard Worker 
4966*5e7646d2SAndroid Build Coastguard Worker 	      ptr += 3;
4967*5e7646d2SAndroid Build Coastguard Worker 	    }
4968*5e7646d2SAndroid Build Coastguard Worker 	    else if (*ptr & 0x80)
4969*5e7646d2SAndroid Build Coastguard Worker 	      break;
4970*5e7646d2SAndroid Build Coastguard Worker 	    else if (*ptr < ' ' || *ptr == 0x7f)
4971*5e7646d2SAndroid Build Coastguard Worker 	      break;
4972*5e7646d2SAndroid Build Coastguard Worker 	  }
4973*5e7646d2SAndroid Build Coastguard Worker 
4974*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr)
4975*5e7646d2SAndroid Build Coastguard Worker 	  {
4976*5e7646d2SAndroid Build Coastguard Worker 	    if (*ptr < ' ' || *ptr == 0x7f)
4977*5e7646d2SAndroid Build Coastguard Worker 	    {
4978*5e7646d2SAndroid Build Coastguard Worker 	      ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad name value \"%s\" - bad control character (PWG 5100.14 section 8.1)."), attr->name, attr->values[i].string.text);
4979*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
4980*5e7646d2SAndroid Build Coastguard Worker 	    }
4981*5e7646d2SAndroid Build Coastguard Worker 	    else
4982*5e7646d2SAndroid Build Coastguard Worker 	    {
4983*5e7646d2SAndroid Build Coastguard Worker 	      ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad name value \"%s\" - bad UTF-8 sequence (RFC 8011 section 5.1.3)."), attr->name, attr->values[i].string.text);
4984*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
4985*5e7646d2SAndroid Build Coastguard Worker 	    }
4986*5e7646d2SAndroid Build Coastguard Worker           }
4987*5e7646d2SAndroid Build Coastguard Worker 
4988*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr - attr->values[i].string.text) > (IPP_MAX_NAME - 1))
4989*5e7646d2SAndroid Build Coastguard Worker 	  {
4990*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad name value \"%s\" - bad length %d (RFC 8011 section 5.1.3)."), attr->name, attr->values[i].string.text, (int)(ptr - attr->values[i].string.text));
4991*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
4992*5e7646d2SAndroid Build Coastguard Worker 	  }
4993*5e7646d2SAndroid Build Coastguard Worker 	}
4994*5e7646d2SAndroid Build Coastguard Worker         break;
4995*5e7646d2SAndroid Build Coastguard Worker 
4996*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
4997*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
4998*5e7646d2SAndroid Build Coastguard Worker 	{
4999*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = attr->values[i].string.text; *ptr; ptr ++)
5000*5e7646d2SAndroid Build Coastguard Worker 	  {
5001*5e7646d2SAndroid Build Coastguard Worker 	    if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' &&
5002*5e7646d2SAndroid Build Coastguard Worker 	        *ptr != '_')
5003*5e7646d2SAndroid Build Coastguard Worker 	      break;
5004*5e7646d2SAndroid Build Coastguard Worker 	  }
5005*5e7646d2SAndroid Build Coastguard Worker 
5006*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr || ptr == attr->values[i].string.text)
5007*5e7646d2SAndroid Build Coastguard Worker 	  {
5008*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad keyword value \"%s\" - invalid character (RFC 8011 section 5.1.4)."), attr->name, attr->values[i].string.text);
5009*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5010*5e7646d2SAndroid Build Coastguard Worker 	  }
5011*5e7646d2SAndroid Build Coastguard Worker 
5012*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr - attr->values[i].string.text) > (IPP_MAX_KEYWORD - 1))
5013*5e7646d2SAndroid Build Coastguard Worker 	  {
5014*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad keyword value \"%s\" - bad length %d (RFC 8011 section 5.1.4)."), attr->name, attr->values[i].string.text, (int)(ptr - attr->values[i].string.text));
5015*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5016*5e7646d2SAndroid Build Coastguard Worker 	  }
5017*5e7646d2SAndroid Build Coastguard Worker 	}
5018*5e7646d2SAndroid Build Coastguard Worker         break;
5019*5e7646d2SAndroid Build Coastguard Worker 
5020*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
5021*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
5022*5e7646d2SAndroid Build Coastguard Worker 	{
5023*5e7646d2SAndroid Build Coastguard Worker 	  uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource));
5024*5e7646d2SAndroid Build Coastguard Worker 
5025*5e7646d2SAndroid Build Coastguard Worker 	  if (uri_status < HTTP_URI_STATUS_OK)
5026*5e7646d2SAndroid Build Coastguard Worker 	  {
5027*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad URI value \"%s\" - %s (RFC 8011 section 5.1.6)."), attr->name, attr->values[i].string.text, httpURIStatusString(uri_status));
5028*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5029*5e7646d2SAndroid Build Coastguard Worker 	  }
5030*5e7646d2SAndroid Build Coastguard Worker 
5031*5e7646d2SAndroid Build Coastguard Worker 	  if (strlen(attr->values[i].string.text) > (IPP_MAX_URI - 1))
5032*5e7646d2SAndroid Build Coastguard Worker 	  {
5033*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad URI value \"%s\" - bad length %d (RFC 8011 section 5.1.6)."), attr->name, attr->values[i].string.text, (int)strlen(attr->values[i].string.text));
5034*5e7646d2SAndroid Build Coastguard Worker 	  }
5035*5e7646d2SAndroid Build Coastguard Worker 	}
5036*5e7646d2SAndroid Build Coastguard Worker         break;
5037*5e7646d2SAndroid Build Coastguard Worker 
5038*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
5039*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
5040*5e7646d2SAndroid Build Coastguard Worker 	{
5041*5e7646d2SAndroid Build Coastguard Worker 	  ptr = attr->values[i].string.text;
5042*5e7646d2SAndroid Build Coastguard Worker 	  if (islower(*ptr & 255))
5043*5e7646d2SAndroid Build Coastguard Worker 	  {
5044*5e7646d2SAndroid Build Coastguard Worker 	    for (ptr ++; *ptr; ptr ++)
5045*5e7646d2SAndroid Build Coastguard Worker 	    {
5046*5e7646d2SAndroid Build Coastguard Worker 	      if (!islower(*ptr & 255) && !isdigit(*ptr & 255) &&
5047*5e7646d2SAndroid Build Coastguard Worker 	          *ptr != '+' && *ptr != '-' && *ptr != '.')
5048*5e7646d2SAndroid Build Coastguard Worker                 break;
5049*5e7646d2SAndroid Build Coastguard Worker 	    }
5050*5e7646d2SAndroid Build Coastguard Worker 	  }
5051*5e7646d2SAndroid Build Coastguard Worker 
5052*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr || ptr == attr->values[i].string.text)
5053*5e7646d2SAndroid Build Coastguard Worker 	  {
5054*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad uriScheme value \"%s\" - bad characters (RFC 8011 section 5.1.7)."), attr->name, attr->values[i].string.text);
5055*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5056*5e7646d2SAndroid Build Coastguard Worker 	  }
5057*5e7646d2SAndroid Build Coastguard Worker 
5058*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr - attr->values[i].string.text) > (IPP_MAX_URISCHEME - 1))
5059*5e7646d2SAndroid Build Coastguard Worker 	  {
5060*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad uriScheme value \"%s\" - bad length %d (RFC 8011 section 5.1.7)."), attr->name, attr->values[i].string.text, (int)(ptr - attr->values[i].string.text));
5061*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5062*5e7646d2SAndroid Build Coastguard Worker 	  }
5063*5e7646d2SAndroid Build Coastguard Worker 	}
5064*5e7646d2SAndroid Build Coastguard Worker         break;
5065*5e7646d2SAndroid Build Coastguard Worker 
5066*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
5067*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
5068*5e7646d2SAndroid Build Coastguard Worker 	{
5069*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = attr->values[i].string.text; *ptr; ptr ++)
5070*5e7646d2SAndroid Build Coastguard Worker 	  {
5071*5e7646d2SAndroid Build Coastguard Worker 	    if (!isprint(*ptr & 255) || isupper(*ptr & 255) ||
5072*5e7646d2SAndroid Build Coastguard Worker 	        isspace(*ptr & 255))
5073*5e7646d2SAndroid Build Coastguard Worker 	      break;
5074*5e7646d2SAndroid Build Coastguard Worker 	  }
5075*5e7646d2SAndroid Build Coastguard Worker 
5076*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr || ptr == attr->values[i].string.text)
5077*5e7646d2SAndroid Build Coastguard Worker 	  {
5078*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad charset value \"%s\" - bad characters (RFC 8011 section 5.1.8)."), attr->name, attr->values[i].string.text);
5079*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5080*5e7646d2SAndroid Build Coastguard Worker 	  }
5081*5e7646d2SAndroid Build Coastguard Worker 
5082*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr - attr->values[i].string.text) > (IPP_MAX_CHARSET - 1))
5083*5e7646d2SAndroid Build Coastguard Worker 	  {
5084*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad charset value \"%s\" - bad length %d (RFC 8011 section 5.1.8)."), attr->name, attr->values[i].string.text, (int)(ptr - attr->values[i].string.text));
5085*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5086*5e7646d2SAndroid Build Coastguard Worker 	  }
5087*5e7646d2SAndroid Build Coastguard Worker 	}
5088*5e7646d2SAndroid Build Coastguard Worker         break;
5089*5e7646d2SAndroid Build Coastguard Worker 
5090*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
5091*5e7646d2SAndroid Build Coastguard Worker        /*
5092*5e7646d2SAndroid Build Coastguard Worker         * The following regular expression is derived from the ABNF for
5093*5e7646d2SAndroid Build Coastguard Worker 	* language tags in RFC 4646.  All I can say is that this is the
5094*5e7646d2SAndroid Build Coastguard Worker 	* easiest way to check the values...
5095*5e7646d2SAndroid Build Coastguard Worker 	*/
5096*5e7646d2SAndroid Build Coastguard Worker 
5097*5e7646d2SAndroid Build Coastguard Worker         if ((i = regcomp(&re,
5098*5e7646d2SAndroid Build Coastguard Worker 			 "^("
5099*5e7646d2SAndroid Build Coastguard Worker 			 "(([a-z]{2,3}(-[a-z][a-z][a-z]){0,3})|[a-z]{4,8})"
5100*5e7646d2SAndroid Build Coastguard Worker 								/* language */
5101*5e7646d2SAndroid Build Coastguard Worker 			 "(-[a-z][a-z][a-z][a-z]){0,1}"		/* script */
5102*5e7646d2SAndroid Build Coastguard Worker 			 "(-([a-z][a-z]|[0-9][0-9][0-9])){0,1}"	/* region */
5103*5e7646d2SAndroid Build Coastguard Worker 			 "(-([a-z]{5,8}|[0-9][0-9][0-9]))*"	/* variant */
5104*5e7646d2SAndroid Build Coastguard Worker 			 "(-[a-wy-z](-[a-z0-9]{2,8})+)*"	/* extension */
5105*5e7646d2SAndroid Build Coastguard Worker 			 "(-x(-[a-z0-9]{1,8})+)*"		/* privateuse */
5106*5e7646d2SAndroid Build Coastguard Worker 			 "|"
5107*5e7646d2SAndroid Build Coastguard Worker 			 "x(-[a-z0-9]{1,8})+"			/* privateuse */
5108*5e7646d2SAndroid Build Coastguard Worker 			 "|"
5109*5e7646d2SAndroid Build Coastguard Worker 			 "[a-z]{1,3}(-[a-z][0-9]{2,8}){1,2}"	/* grandfathered */
5110*5e7646d2SAndroid Build Coastguard Worker 			 ")$",
5111*5e7646d2SAndroid Build Coastguard Worker 			 REG_NOSUB | REG_EXTENDED)) != 0)
5112*5e7646d2SAndroid Build Coastguard Worker         {
5113*5e7646d2SAndroid Build Coastguard Worker           char	temp[256];		/* Temporary error string */
5114*5e7646d2SAndroid Build Coastguard Worker 
5115*5e7646d2SAndroid Build Coastguard Worker           regerror(i, &re, temp, sizeof(temp));
5116*5e7646d2SAndroid Build Coastguard Worker 	  ipp_set_error(IPP_STATUS_ERROR_INTERNAL, _("Unable to compile naturalLanguage regular expression: %s."), temp);
5117*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
5118*5e7646d2SAndroid Build Coastguard Worker         }
5119*5e7646d2SAndroid Build Coastguard Worker 
5120*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
5121*5e7646d2SAndroid Build Coastguard Worker 	{
5122*5e7646d2SAndroid Build Coastguard Worker 	  if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
5123*5e7646d2SAndroid Build Coastguard Worker 	  {
5124*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad naturalLanguage value \"%s\" - bad characters (RFC 8011 section 5.1.9)."), attr->name, attr->values[i].string.text);
5125*5e7646d2SAndroid Build Coastguard Worker 	    regfree(&re);
5126*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5127*5e7646d2SAndroid Build Coastguard Worker 	  }
5128*5e7646d2SAndroid Build Coastguard Worker 
5129*5e7646d2SAndroid Build Coastguard Worker 	  if (strlen(attr->values[i].string.text) > (IPP_MAX_LANGUAGE - 1))
5130*5e7646d2SAndroid Build Coastguard Worker 	  {
5131*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad naturalLanguage value \"%s\" - bad length %d (RFC 8011 section 5.1.9)."), attr->name, attr->values[i].string.text, (int)strlen(attr->values[i].string.text));
5132*5e7646d2SAndroid Build Coastguard Worker 	    regfree(&re);
5133*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5134*5e7646d2SAndroid Build Coastguard Worker 	  }
5135*5e7646d2SAndroid Build Coastguard Worker 	}
5136*5e7646d2SAndroid Build Coastguard Worker 
5137*5e7646d2SAndroid Build Coastguard Worker 	regfree(&re);
5138*5e7646d2SAndroid Build Coastguard Worker         break;
5139*5e7646d2SAndroid Build Coastguard Worker 
5140*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
5141*5e7646d2SAndroid Build Coastguard Worker        /*
5142*5e7646d2SAndroid Build Coastguard Worker         * The following regular expression is derived from the ABNF for
5143*5e7646d2SAndroid Build Coastguard Worker 	* MIME media types in RFC 2045 and 4288.  All I can say is that this is
5144*5e7646d2SAndroid Build Coastguard Worker 	* the easiest way to check the values...
5145*5e7646d2SAndroid Build Coastguard Worker 	*/
5146*5e7646d2SAndroid Build Coastguard Worker 
5147*5e7646d2SAndroid Build Coastguard Worker         if ((i = regcomp(&re,
5148*5e7646d2SAndroid Build Coastguard Worker 			 "^"
5149*5e7646d2SAndroid Build Coastguard Worker 			 "[-a-zA-Z0-9!#$&.+^_]{1,127}"		/* type-name */
5150*5e7646d2SAndroid Build Coastguard Worker 			 "/"
5151*5e7646d2SAndroid Build Coastguard Worker 			 "[-a-zA-Z0-9!#$&.+^_]{1,127}"		/* subtype-name */
5152*5e7646d2SAndroid Build Coastguard Worker 			 "(;[-a-zA-Z0-9!#$&.+^_]{1,127}="	/* parameter= */
5153*5e7646d2SAndroid Build Coastguard Worker 			 "([-a-zA-Z0-9!#$&.+^_]{1,127}|\"[^\"]*\"))*"
5154*5e7646d2SAndroid Build Coastguard Worker 			 					/* value */
5155*5e7646d2SAndroid Build Coastguard Worker 			 "$",
5156*5e7646d2SAndroid Build Coastguard Worker 			 REG_NOSUB | REG_EXTENDED)) != 0)
5157*5e7646d2SAndroid Build Coastguard Worker         {
5158*5e7646d2SAndroid Build Coastguard Worker           char	temp[256];		/* Temporary error string */
5159*5e7646d2SAndroid Build Coastguard Worker 
5160*5e7646d2SAndroid Build Coastguard Worker           regerror(i, &re, temp, sizeof(temp));
5161*5e7646d2SAndroid Build Coastguard Worker 	  ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("Unable to compile mimeMediaType regular expression: %s."), temp);
5162*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
5163*5e7646d2SAndroid Build Coastguard Worker         }
5164*5e7646d2SAndroid Build Coastguard Worker 
5165*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
5166*5e7646d2SAndroid Build Coastguard Worker 	{
5167*5e7646d2SAndroid Build Coastguard Worker 	  if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
5168*5e7646d2SAndroid Build Coastguard Worker 	  {
5169*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad mimeMediaType value \"%s\" - bad characters (RFC 8011 section 5.1.10)."), attr->name, attr->values[i].string.text);
5170*5e7646d2SAndroid Build Coastguard Worker 	    regfree(&re);
5171*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5172*5e7646d2SAndroid Build Coastguard Worker 	  }
5173*5e7646d2SAndroid Build Coastguard Worker 
5174*5e7646d2SAndroid Build Coastguard Worker 	  if (strlen(attr->values[i].string.text) > (IPP_MAX_MIMETYPE - 1))
5175*5e7646d2SAndroid Build Coastguard Worker 	  {
5176*5e7646d2SAndroid Build Coastguard Worker 	    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad mimeMediaType value \"%s\" - bad length %d (RFC 8011 section 5.1.10)."), attr->name, attr->values[i].string.text, (int)strlen(attr->values[i].string.text));
5177*5e7646d2SAndroid Build Coastguard Worker 	    regfree(&re);
5178*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5179*5e7646d2SAndroid Build Coastguard Worker 	  }
5180*5e7646d2SAndroid Build Coastguard Worker 	}
5181*5e7646d2SAndroid Build Coastguard Worker 
5182*5e7646d2SAndroid Build Coastguard Worker 	regfree(&re);
5183*5e7646d2SAndroid Build Coastguard Worker         break;
5184*5e7646d2SAndroid Build Coastguard Worker 
5185*5e7646d2SAndroid Build Coastguard Worker     default :
5186*5e7646d2SAndroid Build Coastguard Worker         break;
5187*5e7646d2SAndroid Build Coastguard Worker   }
5188*5e7646d2SAndroid Build Coastguard Worker 
5189*5e7646d2SAndroid Build Coastguard Worker   return (1);
5190*5e7646d2SAndroid Build Coastguard Worker }
5191*5e7646d2SAndroid Build Coastguard Worker 
5192*5e7646d2SAndroid Build Coastguard Worker 
5193*5e7646d2SAndroid Build Coastguard Worker /*
5194*5e7646d2SAndroid Build Coastguard Worker  * 'ippValidateAttributes()' - Validate all attributes in an IPP message.
5195*5e7646d2SAndroid Build Coastguard Worker  *
5196*5e7646d2SAndroid Build Coastguard Worker  * This function validates the contents of the IPP message, including each
5197*5e7646d2SAndroid Build Coastguard Worker  * attribute.  Like @link ippValidateAttribute@, @link cupsLastErrorString@ is
5198*5e7646d2SAndroid Build Coastguard Worker  * set to a human-readable message on failure.
5199*5e7646d2SAndroid Build Coastguard Worker  *
5200*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
5201*5e7646d2SAndroid Build Coastguard Worker  */
5202*5e7646d2SAndroid Build Coastguard Worker 
5203*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if valid, 0 otherwise */
ippValidateAttributes(ipp_t * ipp)5204*5e7646d2SAndroid Build Coastguard Worker ippValidateAttributes(ipp_t *ipp)	/* I - IPP message */
5205*5e7646d2SAndroid Build Coastguard Worker {
5206*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
5207*5e7646d2SAndroid Build Coastguard Worker 
5208*5e7646d2SAndroid Build Coastguard Worker 
5209*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
5210*5e7646d2SAndroid Build Coastguard Worker     return (1);
5211*5e7646d2SAndroid Build Coastguard Worker 
5212*5e7646d2SAndroid Build Coastguard Worker   for (attr = ipp->attrs; attr; attr = attr->next)
5213*5e7646d2SAndroid Build Coastguard Worker     if (!ippValidateAttribute(attr))
5214*5e7646d2SAndroid Build Coastguard Worker       return (0);
5215*5e7646d2SAndroid Build Coastguard Worker 
5216*5e7646d2SAndroid Build Coastguard Worker   return (1);
5217*5e7646d2SAndroid Build Coastguard Worker }
5218*5e7646d2SAndroid Build Coastguard Worker 
5219*5e7646d2SAndroid Build Coastguard Worker 
5220*5e7646d2SAndroid Build Coastguard Worker /*
5221*5e7646d2SAndroid Build Coastguard Worker  * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
5222*5e7646d2SAndroid Build Coastguard Worker  */
5223*5e7646d2SAndroid Build Coastguard Worker 
5224*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippWrite(http_t * http,ipp_t * ipp)5225*5e7646d2SAndroid Build Coastguard Worker ippWrite(http_t *http,			/* I - HTTP connection */
5226*5e7646d2SAndroid Build Coastguard Worker          ipp_t  *ipp)			/* I - IPP data */
5227*5e7646d2SAndroid Build Coastguard Worker {
5228*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippWrite(http=%p, ipp=%p)", (void *)http, (void *)ipp));
5229*5e7646d2SAndroid Build Coastguard Worker 
5230*5e7646d2SAndroid Build Coastguard Worker   if (!http)
5231*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
5232*5e7646d2SAndroid Build Coastguard Worker 
5233*5e7646d2SAndroid Build Coastguard Worker   return (ippWriteIO(http, (ipp_iocb_t)httpWrite2, http->blocking, NULL, ipp));
5234*5e7646d2SAndroid Build Coastguard Worker }
5235*5e7646d2SAndroid Build Coastguard Worker 
5236*5e7646d2SAndroid Build Coastguard Worker 
5237*5e7646d2SAndroid Build Coastguard Worker /*
5238*5e7646d2SAndroid Build Coastguard Worker  * 'ippWriteFile()' - Write data for an IPP message to a file.
5239*5e7646d2SAndroid Build Coastguard Worker  *
5240*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.1.19/macOS 10.3@
5241*5e7646d2SAndroid Build Coastguard Worker  */
5242*5e7646d2SAndroid Build Coastguard Worker 
5243*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippWriteFile(int fd,ipp_t * ipp)5244*5e7646d2SAndroid Build Coastguard Worker ippWriteFile(int   fd,			/* I - HTTP data */
5245*5e7646d2SAndroid Build Coastguard Worker              ipp_t *ipp)		/* I - IPP data */
5246*5e7646d2SAndroid Build Coastguard Worker {
5247*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd, (void *)ipp));
5248*5e7646d2SAndroid Build Coastguard Worker 
5249*5e7646d2SAndroid Build Coastguard Worker   ipp->state = IPP_STATE_IDLE;
5250*5e7646d2SAndroid Build Coastguard Worker 
5251*5e7646d2SAndroid Build Coastguard Worker   return (ippWriteIO(&fd, (ipp_iocb_t)ipp_write_file, 1, NULL, ipp));
5252*5e7646d2SAndroid Build Coastguard Worker }
5253*5e7646d2SAndroid Build Coastguard Worker 
5254*5e7646d2SAndroid Build Coastguard Worker 
5255*5e7646d2SAndroid Build Coastguard Worker /*
5256*5e7646d2SAndroid Build Coastguard Worker  * 'ippWriteIO()' - Write data for an IPP message.
5257*5e7646d2SAndroid Build Coastguard Worker  *
5258*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
5259*5e7646d2SAndroid Build Coastguard Worker  */
5260*5e7646d2SAndroid Build Coastguard Worker 
5261*5e7646d2SAndroid Build Coastguard Worker ipp_state_t				/* O - Current state */
ippWriteIO(void * dst,ipp_iocb_t cb,int blocking,ipp_t * parent,ipp_t * ipp)5262*5e7646d2SAndroid Build Coastguard Worker ippWriteIO(void       *dst,		/* I - Destination */
5263*5e7646d2SAndroid Build Coastguard Worker            ipp_iocb_t cb,		/* I - Write callback function */
5264*5e7646d2SAndroid Build Coastguard Worker 	   int        blocking,		/* I - Use blocking IO? */
5265*5e7646d2SAndroid Build Coastguard Worker 	   ipp_t      *parent,		/* I - Parent IPP message */
5266*5e7646d2SAndroid Build Coastguard Worker            ipp_t      *ipp)		/* I - IPP data */
5267*5e7646d2SAndroid Build Coastguard Worker {
5268*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
5269*5e7646d2SAndroid Build Coastguard Worker   int			n;		/* Length of data */
5270*5e7646d2SAndroid Build Coastguard Worker   unsigned char		*buffer,	/* Data buffer */
5271*5e7646d2SAndroid Build Coastguard Worker 			*bufptr;	/* Pointer into buffer */
5272*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
5273*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
5274*5e7646d2SAndroid Build Coastguard Worker 
5275*5e7646d2SAndroid Build Coastguard Worker 
5276*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", (void *)dst, (void *)cb, blocking, (void *)parent, (void *)ipp));
5277*5e7646d2SAndroid Build Coastguard Worker 
5278*5e7646d2SAndroid Build Coastguard Worker   if (!dst || !ipp)
5279*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
5280*5e7646d2SAndroid Build Coastguard Worker 
5281*5e7646d2SAndroid Build Coastguard Worker   if ((buffer = (unsigned char *)_cupsBufferGet(IPP_BUF_SIZE)) == NULL)
5282*5e7646d2SAndroid Build Coastguard Worker   {
5283*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1ippWriteIO: Unable to get write buffer");
5284*5e7646d2SAndroid Build Coastguard Worker     return (IPP_STATE_ERROR);
5285*5e7646d2SAndroid Build Coastguard Worker   }
5286*5e7646d2SAndroid Build Coastguard Worker 
5287*5e7646d2SAndroid Build Coastguard Worker   switch (ipp->state)
5288*5e7646d2SAndroid Build Coastguard Worker   {
5289*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_IDLE :
5290*5e7646d2SAndroid Build Coastguard Worker         ipp->state ++; /* Avoid common problem... */
5291*5e7646d2SAndroid Build Coastguard Worker 
5292*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_HEADER :
5293*5e7646d2SAndroid Build Coastguard Worker         if (parent == NULL)
5294*5e7646d2SAndroid Build Coastguard Worker 	{
5295*5e7646d2SAndroid Build Coastguard Worker 	 /*
5296*5e7646d2SAndroid Build Coastguard Worker 	  * Send the request header:
5297*5e7646d2SAndroid Build Coastguard Worker 	  *
5298*5e7646d2SAndroid Build Coastguard Worker 	  *                 Version = 2 bytes
5299*5e7646d2SAndroid Build Coastguard Worker 	  *   Operation/Status Code = 2 bytes
5300*5e7646d2SAndroid Build Coastguard Worker 	  *              Request ID = 4 bytes
5301*5e7646d2SAndroid Build Coastguard Worker 	  *                   Total = 8 bytes
5302*5e7646d2SAndroid Build Coastguard Worker 	  */
5303*5e7646d2SAndroid Build Coastguard Worker 
5304*5e7646d2SAndroid Build Coastguard Worker           bufptr = buffer;
5305*5e7646d2SAndroid Build Coastguard Worker 
5306*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = ipp->request.any.version[0];
5307*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = ipp->request.any.version[1];
5308*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)(ipp->request.any.op_status >> 8);
5309*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)ipp->request.any.op_status;
5310*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)(ipp->request.any.request_id >> 24);
5311*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)(ipp->request.any.request_id >> 16);
5312*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)(ipp->request.any.request_id >> 8);
5313*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = (ipp_uchar_t)ipp->request.any.request_id;
5314*5e7646d2SAndroid Build Coastguard Worker 
5315*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer[0], buffer[1]));
5316*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippWriteIO: op_status=%04x",
5317*5e7646d2SAndroid Build Coastguard Worker 			ipp->request.any.op_status));
5318*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("2ippWriteIO: request_id=%d",
5319*5e7646d2SAndroid Build Coastguard Worker 			ipp->request.any.request_id));
5320*5e7646d2SAndroid Build Coastguard Worker 
5321*5e7646d2SAndroid Build Coastguard Worker           if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5322*5e7646d2SAndroid Build Coastguard Worker 	  {
5323*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippWriteIO: Could not write IPP header...");
5324*5e7646d2SAndroid Build Coastguard Worker 	    _cupsBufferRelease((char *)buffer);
5325*5e7646d2SAndroid Build Coastguard Worker 	    return (IPP_STATE_ERROR);
5326*5e7646d2SAndroid Build Coastguard Worker 	  }
5327*5e7646d2SAndroid Build Coastguard Worker 	}
5328*5e7646d2SAndroid Build Coastguard Worker 
5329*5e7646d2SAndroid Build Coastguard Worker        /*
5330*5e7646d2SAndroid Build Coastguard Worker 	* Reset the state engine to point to the first attribute
5331*5e7646d2SAndroid Build Coastguard Worker 	* in the request/response, with no current group.
5332*5e7646d2SAndroid Build Coastguard Worker 	*/
5333*5e7646d2SAndroid Build Coastguard Worker 
5334*5e7646d2SAndroid Build Coastguard Worker         ipp->state   = IPP_STATE_ATTRIBUTE;
5335*5e7646d2SAndroid Build Coastguard Worker 	ipp->current = ipp->attrs;
5336*5e7646d2SAndroid Build Coastguard Worker 	ipp->curtag  = IPP_TAG_ZERO;
5337*5e7646d2SAndroid Build Coastguard Worker 
5338*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_printf(("1ippWriteIO: ipp->current=%p", (void *)ipp->current));
5339*5e7646d2SAndroid Build Coastguard Worker 
5340*5e7646d2SAndroid Build Coastguard Worker        /*
5341*5e7646d2SAndroid Build Coastguard Worker         * If blocking is disabled, stop here...
5342*5e7646d2SAndroid Build Coastguard Worker 	*/
5343*5e7646d2SAndroid Build Coastguard Worker 
5344*5e7646d2SAndroid Build Coastguard Worker         if (!blocking)
5345*5e7646d2SAndroid Build Coastguard Worker 	  break;
5346*5e7646d2SAndroid Build Coastguard Worker 
5347*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_ATTRIBUTE :
5348*5e7646d2SAndroid Build Coastguard Worker         while (ipp->current != NULL)
5349*5e7646d2SAndroid Build Coastguard Worker 	{
5350*5e7646d2SAndroid Build Coastguard Worker 	 /*
5351*5e7646d2SAndroid Build Coastguard Worker 	  * Write this attribute...
5352*5e7646d2SAndroid Build Coastguard Worker 	  */
5353*5e7646d2SAndroid Build Coastguard Worker 
5354*5e7646d2SAndroid Build Coastguard Worker 	  bufptr = buffer;
5355*5e7646d2SAndroid Build Coastguard Worker 	  attr   = ipp->current;
5356*5e7646d2SAndroid Build Coastguard Worker 
5357*5e7646d2SAndroid Build Coastguard Worker 	  ipp->current = ipp->current->next;
5358*5e7646d2SAndroid Build Coastguard Worker 
5359*5e7646d2SAndroid Build Coastguard Worker           if (!parent)
5360*5e7646d2SAndroid Build Coastguard Worker 	  {
5361*5e7646d2SAndroid Build Coastguard Worker 	    if (ipp->curtag != attr->group_tag)
5362*5e7646d2SAndroid Build Coastguard Worker 	    {
5363*5e7646d2SAndroid Build Coastguard Worker 	     /*
5364*5e7646d2SAndroid Build Coastguard Worker 	      * Send a group tag byte...
5365*5e7646d2SAndroid Build Coastguard Worker 	      */
5366*5e7646d2SAndroid Build Coastguard Worker 
5367*5e7646d2SAndroid Build Coastguard Worker 	      ipp->curtag = attr->group_tag;
5368*5e7646d2SAndroid Build Coastguard Worker 
5369*5e7646d2SAndroid Build Coastguard Worker 	      if (attr->group_tag == IPP_TAG_ZERO)
5370*5e7646d2SAndroid Build Coastguard Worker 		continue;
5371*5e7646d2SAndroid Build Coastguard Worker 
5372*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
5373*5e7646d2SAndroid Build Coastguard Worker 			    attr->group_tag, ippTagString(attr->group_tag)));
5374*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)attr->group_tag;
5375*5e7646d2SAndroid Build Coastguard Worker 	    }
5376*5e7646d2SAndroid Build Coastguard Worker 	    else if (attr->group_tag == IPP_TAG_ZERO)
5377*5e7646d2SAndroid Build Coastguard Worker 	      continue;
5378*5e7646d2SAndroid Build Coastguard Worker 	  }
5379*5e7646d2SAndroid Build Coastguard Worker 
5380*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr->name,
5381*5e7646d2SAndroid Build Coastguard Worker 	                attr->num_values > 1 ? "1setOf " : "",
5382*5e7646d2SAndroid Build Coastguard Worker 			ippTagString(attr->value_tag)));
5383*5e7646d2SAndroid Build Coastguard Worker 
5384*5e7646d2SAndroid Build Coastguard Worker          /*
5385*5e7646d2SAndroid Build Coastguard Worker 	  * Write the attribute tag and name.
5386*5e7646d2SAndroid Build Coastguard Worker 	  *
5387*5e7646d2SAndroid Build Coastguard Worker 	  * The attribute name length does not include the trailing nul
5388*5e7646d2SAndroid Build Coastguard Worker 	  * character in the source string.
5389*5e7646d2SAndroid Build Coastguard Worker 	  *
5390*5e7646d2SAndroid Build Coastguard Worker 	  * Collection values (parent != NULL) are written differently...
5391*5e7646d2SAndroid Build Coastguard Worker 	  */
5392*5e7646d2SAndroid Build Coastguard Worker 
5393*5e7646d2SAndroid Build Coastguard Worker           if (parent == NULL)
5394*5e7646d2SAndroid Build Coastguard Worker 	  {
5395*5e7646d2SAndroid Build Coastguard Worker            /*
5396*5e7646d2SAndroid Build Coastguard Worker 	    * Get the length of the attribute name, and make sure it won't
5397*5e7646d2SAndroid Build Coastguard Worker 	    * overflow the buffer...
5398*5e7646d2SAndroid Build Coastguard Worker 	    */
5399*5e7646d2SAndroid Build Coastguard Worker 
5400*5e7646d2SAndroid Build Coastguard Worker             if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 8))
5401*5e7646d2SAndroid Build Coastguard Worker 	    {
5402*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
5403*5e7646d2SAndroid Build Coastguard Worker 	      _cupsBufferRelease((char *)buffer);
5404*5e7646d2SAndroid Build Coastguard Worker 	      return (IPP_STATE_ERROR);
5405*5e7646d2SAndroid Build Coastguard Worker 	    }
5406*5e7646d2SAndroid Build Coastguard Worker 
5407*5e7646d2SAndroid Build Coastguard Worker            /*
5408*5e7646d2SAndroid Build Coastguard Worker 	    * Write the value tag, name length, and name string...
5409*5e7646d2SAndroid Build Coastguard Worker 	    */
5410*5e7646d2SAndroid Build Coastguard Worker 
5411*5e7646d2SAndroid Build Coastguard Worker             DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
5412*5e7646d2SAndroid Build Coastguard Worker 	                  attr->value_tag, ippTagString(attr->value_tag)));
5413*5e7646d2SAndroid Build Coastguard Worker             DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
5414*5e7646d2SAndroid Build Coastguard Worker 	                  attr->name));
5415*5e7646d2SAndroid Build Coastguard Worker 
5416*5e7646d2SAndroid Build Coastguard Worker             if (attr->value_tag > 0xff)
5417*5e7646d2SAndroid Build Coastguard Worker             {
5418*5e7646d2SAndroid Build Coastguard Worker               *bufptr++ = IPP_TAG_EXTENSION;
5419*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 24);
5420*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 16);
5421*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 8);
5422*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)attr->value_tag;
5423*5e7646d2SAndroid Build Coastguard Worker             }
5424*5e7646d2SAndroid Build Coastguard Worker             else
5425*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)attr->value_tag;
5426*5e7646d2SAndroid Build Coastguard Worker 
5427*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = (ipp_uchar_t)(n >> 8);
5428*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = (ipp_uchar_t)n;
5429*5e7646d2SAndroid Build Coastguard Worker 	    memcpy(bufptr, attr->name, (size_t)n);
5430*5e7646d2SAndroid Build Coastguard Worker 	    bufptr += n;
5431*5e7646d2SAndroid Build Coastguard Worker           }
5432*5e7646d2SAndroid Build Coastguard Worker 	  else
5433*5e7646d2SAndroid Build Coastguard Worker 	  {
5434*5e7646d2SAndroid Build Coastguard Worker            /*
5435*5e7646d2SAndroid Build Coastguard Worker 	    * Get the length of the attribute name, and make sure it won't
5436*5e7646d2SAndroid Build Coastguard Worker 	    * overflow the buffer...
5437*5e7646d2SAndroid Build Coastguard Worker 	    */
5438*5e7646d2SAndroid Build Coastguard Worker 
5439*5e7646d2SAndroid Build Coastguard Worker             if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 12))
5440*5e7646d2SAndroid Build Coastguard Worker 	    {
5441*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
5442*5e7646d2SAndroid Build Coastguard Worker 	      _cupsBufferRelease((char *)buffer);
5443*5e7646d2SAndroid Build Coastguard Worker 	      return (IPP_STATE_ERROR);
5444*5e7646d2SAndroid Build Coastguard Worker 	    }
5445*5e7646d2SAndroid Build Coastguard Worker 
5446*5e7646d2SAndroid Build Coastguard Worker            /*
5447*5e7646d2SAndroid Build Coastguard Worker 	    * Write the member name tag, name length, name string, value tag,
5448*5e7646d2SAndroid Build Coastguard Worker 	    * and empty name for the collection member attribute...
5449*5e7646d2SAndroid Build Coastguard Worker 	    */
5450*5e7646d2SAndroid Build Coastguard Worker 
5451*5e7646d2SAndroid Build Coastguard Worker             DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
5452*5e7646d2SAndroid Build Coastguard Worker 	                  IPP_TAG_MEMBERNAME));
5453*5e7646d2SAndroid Build Coastguard Worker             DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
5454*5e7646d2SAndroid Build Coastguard Worker 	                  attr->name));
5455*5e7646d2SAndroid Build Coastguard Worker             DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
5456*5e7646d2SAndroid Build Coastguard Worker 	                  attr->value_tag, ippTagString(attr->value_tag)));
5457*5e7646d2SAndroid Build Coastguard Worker             DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
5458*5e7646d2SAndroid Build Coastguard Worker 
5459*5e7646d2SAndroid Build Coastguard Worker             *bufptr++ = IPP_TAG_MEMBERNAME;
5460*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = 0;
5461*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = 0;
5462*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = (ipp_uchar_t)(n >> 8);
5463*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = (ipp_uchar_t)n;
5464*5e7646d2SAndroid Build Coastguard Worker 	    memcpy(bufptr, attr->name, (size_t)n);
5465*5e7646d2SAndroid Build Coastguard Worker 	    bufptr += n;
5466*5e7646d2SAndroid Build Coastguard Worker 
5467*5e7646d2SAndroid Build Coastguard Worker             if (attr->value_tag > 0xff)
5468*5e7646d2SAndroid Build Coastguard Worker             {
5469*5e7646d2SAndroid Build Coastguard Worker               *bufptr++ = IPP_TAG_EXTENSION;
5470*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 24);
5471*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 16);
5472*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)(attr->value_tag >> 8);
5473*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)attr->value_tag;
5474*5e7646d2SAndroid Build Coastguard Worker             }
5475*5e7646d2SAndroid Build Coastguard Worker             else
5476*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = (ipp_uchar_t)attr->value_tag;
5477*5e7646d2SAndroid Build Coastguard Worker 
5478*5e7646d2SAndroid Build Coastguard Worker             *bufptr++ = 0;
5479*5e7646d2SAndroid Build Coastguard Worker             *bufptr++ = 0;
5480*5e7646d2SAndroid Build Coastguard Worker 	  }
5481*5e7646d2SAndroid Build Coastguard Worker 
5482*5e7646d2SAndroid Build Coastguard Worker          /*
5483*5e7646d2SAndroid Build Coastguard Worker 	  * Now write the attribute value(s)...
5484*5e7646d2SAndroid Build Coastguard Worker 	  */
5485*5e7646d2SAndroid Build Coastguard Worker 
5486*5e7646d2SAndroid Build Coastguard Worker 	  switch (attr->value_tag & ~IPP_TAG_CUPS_CONST)
5487*5e7646d2SAndroid Build Coastguard Worker 	  {
5488*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_UNSUPPORTED_VALUE :
5489*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DEFAULT :
5490*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_UNKNOWN :
5491*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NOVALUE :
5492*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NOTSETTABLE :
5493*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DELETEATTR :
5494*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ADMINDEFINE :
5495*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = 0;
5496*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = 0;
5497*5e7646d2SAndroid Build Coastguard Worker 	        break;
5498*5e7646d2SAndroid Build Coastguard Worker 
5499*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_INTEGER :
5500*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ENUM :
5501*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5502*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5503*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5504*5e7646d2SAndroid Build Coastguard Worker 		{
5505*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 9)
5506*5e7646d2SAndroid Build Coastguard Worker 		  {
5507*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5508*5e7646d2SAndroid Build Coastguard Worker 	            {
5509*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5510*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5511*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5512*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5513*5e7646d2SAndroid Build Coastguard Worker 	            }
5514*5e7646d2SAndroid Build Coastguard Worker 
5515*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5516*5e7646d2SAndroid Build Coastguard Worker 		  }
5517*5e7646d2SAndroid Build Coastguard Worker 
5518*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5519*5e7646d2SAndroid Build Coastguard Worker 		  {
5520*5e7646d2SAndroid Build Coastguard Worker 		   /*
5521*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5522*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5523*5e7646d2SAndroid Build Coastguard Worker 		    */
5524*5e7646d2SAndroid Build Coastguard Worker 
5525*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5526*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5527*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5528*5e7646d2SAndroid Build Coastguard Worker 		  }
5529*5e7646d2SAndroid Build Coastguard Worker 
5530*5e7646d2SAndroid Build Coastguard Worker 		 /*
5531*5e7646d2SAndroid Build Coastguard Worker 	          * Integers and enumerations are both 4-byte signed
5532*5e7646d2SAndroid Build Coastguard Worker 		  * (twos-complement) values.
5533*5e7646d2SAndroid Build Coastguard Worker 		  *
5534*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and 4-byte value into the buffer...
5535*5e7646d2SAndroid Build Coastguard Worker 		  */
5536*5e7646d2SAndroid Build Coastguard Worker 
5537*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5538*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 4;
5539*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->integer >> 24);
5540*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->integer >> 16);
5541*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->integer >> 8);
5542*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->integer;
5543*5e7646d2SAndroid Build Coastguard Worker 		}
5544*5e7646d2SAndroid Build Coastguard Worker 		break;
5545*5e7646d2SAndroid Build Coastguard Worker 
5546*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_BOOLEAN :
5547*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5548*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5549*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5550*5e7646d2SAndroid Build Coastguard Worker 		{
5551*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 6)
5552*5e7646d2SAndroid Build Coastguard Worker 		  {
5553*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5554*5e7646d2SAndroid Build Coastguard Worker 	            {
5555*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5556*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5557*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5558*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5559*5e7646d2SAndroid Build Coastguard Worker 	            }
5560*5e7646d2SAndroid Build Coastguard Worker 
5561*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5562*5e7646d2SAndroid Build Coastguard Worker 		  }
5563*5e7646d2SAndroid Build Coastguard Worker 
5564*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5565*5e7646d2SAndroid Build Coastguard Worker 		  {
5566*5e7646d2SAndroid Build Coastguard Worker 		   /*
5567*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5568*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5569*5e7646d2SAndroid Build Coastguard Worker 		    */
5570*5e7646d2SAndroid Build Coastguard Worker 
5571*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5572*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5573*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5574*5e7646d2SAndroid Build Coastguard Worker 		  }
5575*5e7646d2SAndroid Build Coastguard Worker 
5576*5e7646d2SAndroid Build Coastguard Worker                  /*
5577*5e7646d2SAndroid Build Coastguard Worker 		  * Boolean values are 1-byte; 0 = false, 1 = true.
5578*5e7646d2SAndroid Build Coastguard Worker 		  *
5579*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and 1-byte value into the buffer...
5580*5e7646d2SAndroid Build Coastguard Worker 		  */
5581*5e7646d2SAndroid Build Coastguard Worker 
5582*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5583*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 1;
5584*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->boolean;
5585*5e7646d2SAndroid Build Coastguard Worker 		}
5586*5e7646d2SAndroid Build Coastguard Worker 		break;
5587*5e7646d2SAndroid Build Coastguard Worker 
5588*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXT :
5589*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAME :
5590*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_KEYWORD :
5591*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URI :
5592*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URISCHEME :
5593*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_CHARSET :
5594*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_LANGUAGE :
5595*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_MIMETYPE :
5596*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5597*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5598*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5599*5e7646d2SAndroid Build Coastguard Worker 		{
5600*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5601*5e7646d2SAndroid Build Coastguard Worker 		  {
5602*5e7646d2SAndroid Build Coastguard Worker 		   /*
5603*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5604*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5605*5e7646d2SAndroid Build Coastguard Worker 		    */
5606*5e7646d2SAndroid Build Coastguard Worker 
5607*5e7646d2SAndroid Build Coastguard Worker         	    DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
5608*5e7646d2SAndroid Build Coastguard Worker 		                  attr->value_tag,
5609*5e7646d2SAndroid Build Coastguard Worker 				  ippTagString(attr->value_tag)));
5610*5e7646d2SAndroid Build Coastguard Worker         	    DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
5611*5e7646d2SAndroid Build Coastguard Worker 
5612*5e7646d2SAndroid Build Coastguard Worker                     if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
5613*5e7646d2SAndroid Build Coastguard Worker 		    {
5614*5e7646d2SAndroid Build Coastguard Worker                       if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5615*5e7646d2SAndroid Build Coastguard Worker 	              {
5616*5e7646d2SAndroid Build Coastguard Worker 	        	DEBUG_puts("1ippWriteIO: Could not write IPP "
5617*5e7646d2SAndroid Build Coastguard Worker 			           "attribute...");
5618*5e7646d2SAndroid Build Coastguard Worker 			_cupsBufferRelease((char *)buffer);
5619*5e7646d2SAndroid Build Coastguard Worker 	        	return (IPP_STATE_ERROR);
5620*5e7646d2SAndroid Build Coastguard Worker 	              }
5621*5e7646d2SAndroid Build Coastguard Worker 
5622*5e7646d2SAndroid Build Coastguard Worker 		      bufptr = buffer;
5623*5e7646d2SAndroid Build Coastguard Worker 		    }
5624*5e7646d2SAndroid Build Coastguard Worker 
5625*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5626*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5627*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5628*5e7646d2SAndroid Build Coastguard Worker 		  }
5629*5e7646d2SAndroid Build Coastguard Worker 
5630*5e7646d2SAndroid Build Coastguard Worker                   if (value->string.text != NULL)
5631*5e7646d2SAndroid Build Coastguard Worker                     n = (int)strlen(value->string.text);
5632*5e7646d2SAndroid Build Coastguard Worker 		  else
5633*5e7646d2SAndroid Build Coastguard Worker 		    n = 0;
5634*5e7646d2SAndroid Build Coastguard Worker 
5635*5e7646d2SAndroid Build Coastguard Worker                   if (n > (IPP_BUF_SIZE - 2))
5636*5e7646d2SAndroid Build Coastguard Worker 		  {
5637*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_printf(("1ippWriteIO: String too long (%d)", n));
5638*5e7646d2SAndroid Build Coastguard Worker 		    _cupsBufferRelease((char *)buffer);
5639*5e7646d2SAndroid Build Coastguard Worker 		    return (IPP_STATE_ERROR);
5640*5e7646d2SAndroid Build Coastguard Worker 		  }
5641*5e7646d2SAndroid Build Coastguard Worker 
5642*5e7646d2SAndroid Build Coastguard Worker                   DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n,
5643*5e7646d2SAndroid Build Coastguard Worker 		                value->string.text));
5644*5e7646d2SAndroid Build Coastguard Worker 
5645*5e7646d2SAndroid Build Coastguard Worker                   if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
5646*5e7646d2SAndroid Build Coastguard Worker 		  {
5647*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5648*5e7646d2SAndroid Build Coastguard Worker 	            {
5649*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5650*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5651*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5652*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5653*5e7646d2SAndroid Build Coastguard Worker 	            }
5654*5e7646d2SAndroid Build Coastguard Worker 
5655*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5656*5e7646d2SAndroid Build Coastguard Worker 		  }
5657*5e7646d2SAndroid Build Coastguard Worker 
5658*5e7646d2SAndroid Build Coastguard Worker 		 /*
5659*5e7646d2SAndroid Build Coastguard Worker 		  * All simple strings consist of the 2-byte length and
5660*5e7646d2SAndroid Build Coastguard Worker 		  * character data without the trailing nul normally found
5661*5e7646d2SAndroid Build Coastguard Worker 		  * in C strings.  Also, strings cannot be longer than IPP_MAX_LENGTH
5662*5e7646d2SAndroid Build Coastguard Worker 		  * bytes since the 2-byte length is a signed (twos-complement)
5663*5e7646d2SAndroid Build Coastguard Worker 		  * value.
5664*5e7646d2SAndroid Build Coastguard Worker 		  *
5665*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and string characters in the buffer.
5666*5e7646d2SAndroid Build Coastguard Worker 		  */
5667*5e7646d2SAndroid Build Coastguard Worker 
5668*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = (ipp_uchar_t)(n >> 8);
5669*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)n;
5670*5e7646d2SAndroid Build Coastguard Worker 
5671*5e7646d2SAndroid Build Coastguard Worker 		  if (n > 0)
5672*5e7646d2SAndroid Build Coastguard Worker 		  {
5673*5e7646d2SAndroid Build Coastguard Worker 		    memcpy(bufptr, value->string.text, (size_t)n);
5674*5e7646d2SAndroid Build Coastguard Worker 		    bufptr += n;
5675*5e7646d2SAndroid Build Coastguard Worker 		  }
5676*5e7646d2SAndroid Build Coastguard Worker 		}
5677*5e7646d2SAndroid Build Coastguard Worker 		break;
5678*5e7646d2SAndroid Build Coastguard Worker 
5679*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_DATE :
5680*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5681*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5682*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5683*5e7646d2SAndroid Build Coastguard Worker 		{
5684*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 16)
5685*5e7646d2SAndroid Build Coastguard Worker 		  {
5686*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5687*5e7646d2SAndroid Build Coastguard Worker 	            {
5688*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5689*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5690*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5691*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5692*5e7646d2SAndroid Build Coastguard Worker 	            }
5693*5e7646d2SAndroid Build Coastguard Worker 
5694*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5695*5e7646d2SAndroid Build Coastguard Worker 		  }
5696*5e7646d2SAndroid Build Coastguard Worker 
5697*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5698*5e7646d2SAndroid Build Coastguard Worker 		  {
5699*5e7646d2SAndroid Build Coastguard Worker 		   /*
5700*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5701*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5702*5e7646d2SAndroid Build Coastguard Worker 		    */
5703*5e7646d2SAndroid Build Coastguard Worker 
5704*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5705*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5706*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5707*5e7646d2SAndroid Build Coastguard Worker 		  }
5708*5e7646d2SAndroid Build Coastguard Worker 
5709*5e7646d2SAndroid Build Coastguard Worker                  /*
5710*5e7646d2SAndroid Build Coastguard Worker 		  * Date values consist of a 2-byte length and an
5711*5e7646d2SAndroid Build Coastguard Worker 		  * 11-byte date/time structure defined by RFC 1903.
5712*5e7646d2SAndroid Build Coastguard Worker 		  *
5713*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and 11-byte date/time
5714*5e7646d2SAndroid Build Coastguard Worker 		  * structure in the buffer.
5715*5e7646d2SAndroid Build Coastguard Worker 		  */
5716*5e7646d2SAndroid Build Coastguard Worker 
5717*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5718*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 11;
5719*5e7646d2SAndroid Build Coastguard Worker 		  memcpy(bufptr, value->date, 11);
5720*5e7646d2SAndroid Build Coastguard Worker 		  bufptr += 11;
5721*5e7646d2SAndroid Build Coastguard Worker 		}
5722*5e7646d2SAndroid Build Coastguard Worker 		break;
5723*5e7646d2SAndroid Build Coastguard Worker 
5724*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_RESOLUTION :
5725*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5726*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5727*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5728*5e7646d2SAndroid Build Coastguard Worker 		{
5729*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 14)
5730*5e7646d2SAndroid Build Coastguard Worker 		  {
5731*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5732*5e7646d2SAndroid Build Coastguard Worker 	            {
5733*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5734*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5735*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5736*5e7646d2SAndroid Build Coastguard Worker 		      return (IPP_STATE_ERROR);
5737*5e7646d2SAndroid Build Coastguard Worker 	            }
5738*5e7646d2SAndroid Build Coastguard Worker 
5739*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5740*5e7646d2SAndroid Build Coastguard Worker 		  }
5741*5e7646d2SAndroid Build Coastguard Worker 
5742*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5743*5e7646d2SAndroid Build Coastguard Worker 		  {
5744*5e7646d2SAndroid Build Coastguard Worker 		   /*
5745*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5746*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5747*5e7646d2SAndroid Build Coastguard Worker 		    */
5748*5e7646d2SAndroid Build Coastguard Worker 
5749*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5750*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5751*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5752*5e7646d2SAndroid Build Coastguard Worker 		  }
5753*5e7646d2SAndroid Build Coastguard Worker 
5754*5e7646d2SAndroid Build Coastguard Worker                  /*
5755*5e7646d2SAndroid Build Coastguard Worker 		  * Resolution values consist of a 2-byte length,
5756*5e7646d2SAndroid Build Coastguard Worker 		  * 4-byte horizontal resolution value, 4-byte vertical
5757*5e7646d2SAndroid Build Coastguard Worker 		  * resolution value, and a 1-byte units value.
5758*5e7646d2SAndroid Build Coastguard Worker 		  *
5759*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and resolution value data
5760*5e7646d2SAndroid Build Coastguard Worker 		  * into the buffer.
5761*5e7646d2SAndroid Build Coastguard Worker 		  */
5762*5e7646d2SAndroid Build Coastguard Worker 
5763*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5764*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 9;
5765*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.xres >> 24);
5766*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.xres >> 16);
5767*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.xres >> 8);
5768*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->resolution.xres;
5769*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.yres >> 24);
5770*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.yres >> 16);
5771*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->resolution.yres >> 8);
5772*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->resolution.yres;
5773*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->resolution.units;
5774*5e7646d2SAndroid Build Coastguard Worker 		}
5775*5e7646d2SAndroid Build Coastguard Worker 		break;
5776*5e7646d2SAndroid Build Coastguard Worker 
5777*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_RANGE :
5778*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5779*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5780*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5781*5e7646d2SAndroid Build Coastguard Worker 		{
5782*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 13)
5783*5e7646d2SAndroid Build Coastguard Worker 		  {
5784*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5785*5e7646d2SAndroid Build Coastguard Worker 	            {
5786*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5787*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5788*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5789*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5790*5e7646d2SAndroid Build Coastguard Worker 	            }
5791*5e7646d2SAndroid Build Coastguard Worker 
5792*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5793*5e7646d2SAndroid Build Coastguard Worker 		  }
5794*5e7646d2SAndroid Build Coastguard Worker 
5795*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5796*5e7646d2SAndroid Build Coastguard Worker 		  {
5797*5e7646d2SAndroid Build Coastguard Worker 		   /*
5798*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5799*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5800*5e7646d2SAndroid Build Coastguard Worker 		    */
5801*5e7646d2SAndroid Build Coastguard Worker 
5802*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5803*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5804*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5805*5e7646d2SAndroid Build Coastguard Worker 		  }
5806*5e7646d2SAndroid Build Coastguard Worker 
5807*5e7646d2SAndroid Build Coastguard Worker                  /*
5808*5e7646d2SAndroid Build Coastguard Worker 		  * Range values consist of a 2-byte length,
5809*5e7646d2SAndroid Build Coastguard Worker 		  * 4-byte lower value, and 4-byte upper value.
5810*5e7646d2SAndroid Build Coastguard Worker 		  *
5811*5e7646d2SAndroid Build Coastguard Worker 		  * Put the 2-byte length and range value data
5812*5e7646d2SAndroid Build Coastguard Worker 		  * into the buffer.
5813*5e7646d2SAndroid Build Coastguard Worker 		  */
5814*5e7646d2SAndroid Build Coastguard Worker 
5815*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5816*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 8;
5817*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.lower >> 24);
5818*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.lower >> 16);
5819*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.lower >> 8);
5820*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->range.lower;
5821*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.upper >> 24);
5822*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.upper >> 16);
5823*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)(value->range.upper >> 8);
5824*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)value->range.upper;
5825*5e7646d2SAndroid Build Coastguard Worker 		}
5826*5e7646d2SAndroid Build Coastguard Worker 		break;
5827*5e7646d2SAndroid Build Coastguard Worker 
5828*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXTLANG :
5829*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAMELANG :
5830*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5831*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5832*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5833*5e7646d2SAndroid Build Coastguard Worker 		{
5834*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5835*5e7646d2SAndroid Build Coastguard Worker 		  {
5836*5e7646d2SAndroid Build Coastguard Worker 		   /*
5837*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5838*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5839*5e7646d2SAndroid Build Coastguard Worker 		    */
5840*5e7646d2SAndroid Build Coastguard Worker 
5841*5e7646d2SAndroid Build Coastguard Worker                     if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
5842*5e7646d2SAndroid Build Coastguard Worker 		    {
5843*5e7646d2SAndroid Build Coastguard Worker                       if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5844*5e7646d2SAndroid Build Coastguard Worker 	              {
5845*5e7646d2SAndroid Build Coastguard Worker 	        	DEBUG_puts("1ippWriteIO: Could not write IPP "
5846*5e7646d2SAndroid Build Coastguard Worker 		                   "attribute...");
5847*5e7646d2SAndroid Build Coastguard Worker 			_cupsBufferRelease((char *)buffer);
5848*5e7646d2SAndroid Build Coastguard Worker 	        	return (IPP_STATE_ERROR);
5849*5e7646d2SAndroid Build Coastguard Worker 	              }
5850*5e7646d2SAndroid Build Coastguard Worker 
5851*5e7646d2SAndroid Build Coastguard Worker 		      bufptr = buffer;
5852*5e7646d2SAndroid Build Coastguard Worker 		    }
5853*5e7646d2SAndroid Build Coastguard Worker 
5854*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5855*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5856*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5857*5e7646d2SAndroid Build Coastguard Worker 		  }
5858*5e7646d2SAndroid Build Coastguard Worker 
5859*5e7646d2SAndroid Build Coastguard Worker                  /*
5860*5e7646d2SAndroid Build Coastguard Worker 		  * textWithLanguage and nameWithLanguage values consist
5861*5e7646d2SAndroid Build Coastguard Worker 		  * of a 2-byte length for both strings and their
5862*5e7646d2SAndroid Build Coastguard Worker 		  * individual lengths, a 2-byte length for the
5863*5e7646d2SAndroid Build Coastguard Worker 		  * character string, the character string without the
5864*5e7646d2SAndroid Build Coastguard Worker 		  * trailing nul, a 2-byte length for the character
5865*5e7646d2SAndroid Build Coastguard Worker 		  * set string, and the character set string without
5866*5e7646d2SAndroid Build Coastguard Worker 		  * the trailing nul.
5867*5e7646d2SAndroid Build Coastguard Worker 		  */
5868*5e7646d2SAndroid Build Coastguard Worker 
5869*5e7646d2SAndroid Build Coastguard Worker                   n = 4;
5870*5e7646d2SAndroid Build Coastguard Worker 
5871*5e7646d2SAndroid Build Coastguard Worker 		  if (value->string.language != NULL)
5872*5e7646d2SAndroid Build Coastguard Worker                     n += (int)strlen(value->string.language);
5873*5e7646d2SAndroid Build Coastguard Worker 
5874*5e7646d2SAndroid Build Coastguard Worker 		  if (value->string.text != NULL)
5875*5e7646d2SAndroid Build Coastguard Worker                     n += (int)strlen(value->string.text);
5876*5e7646d2SAndroid Build Coastguard Worker 
5877*5e7646d2SAndroid Build Coastguard Worker                   if (n > (IPP_BUF_SIZE - 2))
5878*5e7646d2SAndroid Build Coastguard Worker 		  {
5879*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
5880*5e7646d2SAndroid Build Coastguard Worker 		                  "too long (%d)", n));
5881*5e7646d2SAndroid Build Coastguard Worker 		    _cupsBufferRelease((char *)buffer);
5882*5e7646d2SAndroid Build Coastguard Worker 		    return (IPP_STATE_ERROR);
5883*5e7646d2SAndroid Build Coastguard Worker                   }
5884*5e7646d2SAndroid Build Coastguard Worker 
5885*5e7646d2SAndroid Build Coastguard Worker                   if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
5886*5e7646d2SAndroid Build Coastguard Worker 		  {
5887*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5888*5e7646d2SAndroid Build Coastguard Worker 	            {
5889*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5890*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5891*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5892*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5893*5e7646d2SAndroid Build Coastguard Worker 	            }
5894*5e7646d2SAndroid Build Coastguard Worker 
5895*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5896*5e7646d2SAndroid Build Coastguard Worker 		  }
5897*5e7646d2SAndroid Build Coastguard Worker 
5898*5e7646d2SAndroid Build Coastguard Worker                  /* Length of entire value */
5899*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = (ipp_uchar_t)(n >> 8);
5900*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)n;
5901*5e7646d2SAndroid Build Coastguard Worker 
5902*5e7646d2SAndroid Build Coastguard Worker                  /* Length of language */
5903*5e7646d2SAndroid Build Coastguard Worker 		  if (value->string.language != NULL)
5904*5e7646d2SAndroid Build Coastguard Worker 		    n = (int)strlen(value->string.language);
5905*5e7646d2SAndroid Build Coastguard Worker 		  else
5906*5e7646d2SAndroid Build Coastguard Worker 		    n = 0;
5907*5e7646d2SAndroid Build Coastguard Worker 
5908*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = (ipp_uchar_t)(n >> 8);
5909*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)n;
5910*5e7646d2SAndroid Build Coastguard Worker 
5911*5e7646d2SAndroid Build Coastguard Worker                  /* Language */
5912*5e7646d2SAndroid Build Coastguard Worker 		  if (n > 0)
5913*5e7646d2SAndroid Build Coastguard Worker 		  {
5914*5e7646d2SAndroid Build Coastguard Worker 		    memcpy(bufptr, value->string.language, (size_t)n);
5915*5e7646d2SAndroid Build Coastguard Worker 		    bufptr += n;
5916*5e7646d2SAndroid Build Coastguard Worker 		  }
5917*5e7646d2SAndroid Build Coastguard Worker 
5918*5e7646d2SAndroid Build Coastguard Worker                  /* Length of text */
5919*5e7646d2SAndroid Build Coastguard Worker                   if (value->string.text != NULL)
5920*5e7646d2SAndroid Build Coastguard Worker 		    n = (int)strlen(value->string.text);
5921*5e7646d2SAndroid Build Coastguard Worker 		  else
5922*5e7646d2SAndroid Build Coastguard Worker 		    n = 0;
5923*5e7646d2SAndroid Build Coastguard Worker 
5924*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = (ipp_uchar_t)(n >> 8);
5925*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)n;
5926*5e7646d2SAndroid Build Coastguard Worker 
5927*5e7646d2SAndroid Build Coastguard Worker                  /* Text */
5928*5e7646d2SAndroid Build Coastguard Worker 		  if (n > 0)
5929*5e7646d2SAndroid Build Coastguard Worker 		  {
5930*5e7646d2SAndroid Build Coastguard Worker 		    memcpy(bufptr, value->string.text, (size_t)n);
5931*5e7646d2SAndroid Build Coastguard Worker 		    bufptr += n;
5932*5e7646d2SAndroid Build Coastguard Worker 		  }
5933*5e7646d2SAndroid Build Coastguard Worker 		}
5934*5e7646d2SAndroid Build Coastguard Worker 		break;
5935*5e7646d2SAndroid Build Coastguard Worker 
5936*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_BEGIN_COLLECTION :
5937*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
5938*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
5939*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
5940*5e7646d2SAndroid Build Coastguard Worker 		{
5941*5e7646d2SAndroid Build Coastguard Worker 		 /*
5942*5e7646d2SAndroid Build Coastguard Worker 		  * Collections are written with the begin-collection
5943*5e7646d2SAndroid Build Coastguard Worker 		  * tag first with a value of 0 length, followed by the
5944*5e7646d2SAndroid Build Coastguard Worker 		  * attributes in the collection, then the end-collection
5945*5e7646d2SAndroid Build Coastguard Worker 		  * value...
5946*5e7646d2SAndroid Build Coastguard Worker 		  */
5947*5e7646d2SAndroid Build Coastguard Worker 
5948*5e7646d2SAndroid Build Coastguard Worker                   if ((IPP_BUF_SIZE - (bufptr - buffer)) < 5)
5949*5e7646d2SAndroid Build Coastguard Worker 		  {
5950*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5951*5e7646d2SAndroid Build Coastguard Worker 	            {
5952*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
5953*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
5954*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
5955*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
5956*5e7646d2SAndroid Build Coastguard Worker 	            }
5957*5e7646d2SAndroid Build Coastguard Worker 
5958*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
5959*5e7646d2SAndroid Build Coastguard Worker 		  }
5960*5e7646d2SAndroid Build Coastguard Worker 
5961*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
5962*5e7646d2SAndroid Build Coastguard Worker 		  {
5963*5e7646d2SAndroid Build Coastguard Worker 		   /*
5964*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
5965*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
5966*5e7646d2SAndroid Build Coastguard Worker 		    */
5967*5e7646d2SAndroid Build Coastguard Worker 
5968*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
5969*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5970*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
5971*5e7646d2SAndroid Build Coastguard Worker 		  }
5972*5e7646d2SAndroid Build Coastguard Worker 
5973*5e7646d2SAndroid Build Coastguard Worker                  /*
5974*5e7646d2SAndroid Build Coastguard Worker 		  * Write a data length of 0 and flush the buffer...
5975*5e7646d2SAndroid Build Coastguard Worker 		  */
5976*5e7646d2SAndroid Build Coastguard Worker 
5977*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = 0;
5978*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = 0;
5979*5e7646d2SAndroid Build Coastguard Worker 
5980*5e7646d2SAndroid Build Coastguard Worker                   if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
5981*5e7646d2SAndroid Build Coastguard Worker 	          {
5982*5e7646d2SAndroid Build Coastguard Worker 	            DEBUG_puts("1ippWriteIO: Could not write IPP "
5983*5e7646d2SAndroid Build Coastguard Worker 		               "attribute...");
5984*5e7646d2SAndroid Build Coastguard Worker 		    _cupsBufferRelease((char *)buffer);
5985*5e7646d2SAndroid Build Coastguard Worker 	            return (IPP_STATE_ERROR);
5986*5e7646d2SAndroid Build Coastguard Worker 	          }
5987*5e7646d2SAndroid Build Coastguard Worker 
5988*5e7646d2SAndroid Build Coastguard Worker 		  bufptr = buffer;
5989*5e7646d2SAndroid Build Coastguard Worker 
5990*5e7646d2SAndroid Build Coastguard Worker                  /*
5991*5e7646d2SAndroid Build Coastguard Worker 		  * Then write the collection attribute...
5992*5e7646d2SAndroid Build Coastguard Worker 		  */
5993*5e7646d2SAndroid Build Coastguard Worker 
5994*5e7646d2SAndroid Build Coastguard Worker                   value->collection->state = IPP_STATE_IDLE;
5995*5e7646d2SAndroid Build Coastguard Worker 
5996*5e7646d2SAndroid Build Coastguard Worker 		  if (ippWriteIO(dst, cb, 1, ipp,
5997*5e7646d2SAndroid Build Coastguard Worker 		                 value->collection) == IPP_STATE_ERROR)
5998*5e7646d2SAndroid Build Coastguard Worker 		  {
5999*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_puts("1ippWriteIO: Unable to write collection value");
6000*5e7646d2SAndroid Build Coastguard Worker 		    _cupsBufferRelease((char *)buffer);
6001*5e7646d2SAndroid Build Coastguard Worker 		    return (IPP_STATE_ERROR);
6002*5e7646d2SAndroid Build Coastguard Worker 		  }
6003*5e7646d2SAndroid Build Coastguard Worker 		}
6004*5e7646d2SAndroid Build Coastguard Worker 		break;
6005*5e7646d2SAndroid Build Coastguard Worker 
6006*5e7646d2SAndroid Build Coastguard Worker             default :
6007*5e7646d2SAndroid Build Coastguard Worker 	        for (i = 0, value = attr->values;
6008*5e7646d2SAndroid Build Coastguard Worker 		     i < attr->num_values;
6009*5e7646d2SAndroid Build Coastguard Worker 		     i ++, value ++)
6010*5e7646d2SAndroid Build Coastguard Worker 		{
6011*5e7646d2SAndroid Build Coastguard Worker 		  if (i)
6012*5e7646d2SAndroid Build Coastguard Worker 		  {
6013*5e7646d2SAndroid Build Coastguard Worker 		   /*
6014*5e7646d2SAndroid Build Coastguard Worker 		    * Arrays and sets are done by sending additional
6015*5e7646d2SAndroid Build Coastguard Worker 		    * values with a zero-length name...
6016*5e7646d2SAndroid Build Coastguard Worker 		    */
6017*5e7646d2SAndroid Build Coastguard Worker 
6018*5e7646d2SAndroid Build Coastguard Worker                     if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
6019*5e7646d2SAndroid Build Coastguard Worker 		    {
6020*5e7646d2SAndroid Build Coastguard Worker                       if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
6021*5e7646d2SAndroid Build Coastguard Worker 	              {
6022*5e7646d2SAndroid Build Coastguard Worker 	        	DEBUG_puts("1ippWriteIO: Could not write IPP "
6023*5e7646d2SAndroid Build Coastguard Worker 		                   "attribute...");
6024*5e7646d2SAndroid Build Coastguard Worker 			_cupsBufferRelease((char *)buffer);
6025*5e7646d2SAndroid Build Coastguard Worker 	        	return (IPP_STATE_ERROR);
6026*5e7646d2SAndroid Build Coastguard Worker 	              }
6027*5e7646d2SAndroid Build Coastguard Worker 
6028*5e7646d2SAndroid Build Coastguard Worker 		      bufptr = buffer;
6029*5e7646d2SAndroid Build Coastguard Worker 		    }
6030*5e7646d2SAndroid Build Coastguard Worker 
6031*5e7646d2SAndroid Build Coastguard Worker                     *bufptr++ = (ipp_uchar_t)attr->value_tag;
6032*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
6033*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = 0;
6034*5e7646d2SAndroid Build Coastguard Worker 		  }
6035*5e7646d2SAndroid Build Coastguard Worker 
6036*5e7646d2SAndroid Build Coastguard Worker                  /*
6037*5e7646d2SAndroid Build Coastguard Worker 		  * An unknown value might some new value that a
6038*5e7646d2SAndroid Build Coastguard Worker 		  * vendor has come up with. It consists of a
6039*5e7646d2SAndroid Build Coastguard Worker 		  * 2-byte length and the bytes in the unknown
6040*5e7646d2SAndroid Build Coastguard Worker 		  * value buffer.
6041*5e7646d2SAndroid Build Coastguard Worker 		  */
6042*5e7646d2SAndroid Build Coastguard Worker 
6043*5e7646d2SAndroid Build Coastguard Worker                   n = value->unknown.length;
6044*5e7646d2SAndroid Build Coastguard Worker 
6045*5e7646d2SAndroid Build Coastguard Worker                   if (n > (IPP_BUF_SIZE - 2))
6046*5e7646d2SAndroid Build Coastguard Worker 		  {
6047*5e7646d2SAndroid Build Coastguard Worker 		    DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
6048*5e7646d2SAndroid Build Coastguard Worker 		                  n));
6049*5e7646d2SAndroid Build Coastguard Worker 		    _cupsBufferRelease((char *)buffer);
6050*5e7646d2SAndroid Build Coastguard Worker 		    return (IPP_STATE_ERROR);
6051*5e7646d2SAndroid Build Coastguard Worker 		  }
6052*5e7646d2SAndroid Build Coastguard Worker 
6053*5e7646d2SAndroid Build Coastguard Worker                   if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
6054*5e7646d2SAndroid Build Coastguard Worker 		  {
6055*5e7646d2SAndroid Build Coastguard Worker                     if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
6056*5e7646d2SAndroid Build Coastguard Worker 	            {
6057*5e7646d2SAndroid Build Coastguard Worker 	              DEBUG_puts("1ippWriteIO: Could not write IPP "
6058*5e7646d2SAndroid Build Coastguard Worker 		                 "attribute...");
6059*5e7646d2SAndroid Build Coastguard Worker 		      _cupsBufferRelease((char *)buffer);
6060*5e7646d2SAndroid Build Coastguard Worker 	              return (IPP_STATE_ERROR);
6061*5e7646d2SAndroid Build Coastguard Worker 	            }
6062*5e7646d2SAndroid Build Coastguard Worker 
6063*5e7646d2SAndroid Build Coastguard Worker 		    bufptr = buffer;
6064*5e7646d2SAndroid Build Coastguard Worker 		  }
6065*5e7646d2SAndroid Build Coastguard Worker 
6066*5e7646d2SAndroid Build Coastguard Worker                  /* Length of unknown value */
6067*5e7646d2SAndroid Build Coastguard Worker 	          *bufptr++ = (ipp_uchar_t)(n >> 8);
6068*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = (ipp_uchar_t)n;
6069*5e7646d2SAndroid Build Coastguard Worker 
6070*5e7646d2SAndroid Build Coastguard Worker                  /* Value */
6071*5e7646d2SAndroid Build Coastguard Worker 		  if (n > 0)
6072*5e7646d2SAndroid Build Coastguard Worker 		  {
6073*5e7646d2SAndroid Build Coastguard Worker 		    memcpy(bufptr, value->unknown.data, (size_t)n);
6074*5e7646d2SAndroid Build Coastguard Worker 		    bufptr += n;
6075*5e7646d2SAndroid Build Coastguard Worker 		  }
6076*5e7646d2SAndroid Build Coastguard Worker 		}
6077*5e7646d2SAndroid Build Coastguard Worker 		break;
6078*5e7646d2SAndroid Build Coastguard Worker 	  }
6079*5e7646d2SAndroid Build Coastguard Worker 
6080*5e7646d2SAndroid Build Coastguard Worker          /*
6081*5e7646d2SAndroid Build Coastguard Worker 	  * Write the data out...
6082*5e7646d2SAndroid Build Coastguard Worker 	  */
6083*5e7646d2SAndroid Build Coastguard Worker 
6084*5e7646d2SAndroid Build Coastguard Worker 	  if (bufptr > buffer)
6085*5e7646d2SAndroid Build Coastguard Worker 	  {
6086*5e7646d2SAndroid Build Coastguard Worker 	    if ((*cb)(dst, buffer, (size_t)(bufptr - buffer)) < 0)
6087*5e7646d2SAndroid Build Coastguard Worker 	    {
6088*5e7646d2SAndroid Build Coastguard Worker 	      DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
6089*5e7646d2SAndroid Build Coastguard Worker 	      _cupsBufferRelease((char *)buffer);
6090*5e7646d2SAndroid Build Coastguard Worker 	      return (IPP_STATE_ERROR);
6091*5e7646d2SAndroid Build Coastguard Worker 	    }
6092*5e7646d2SAndroid Build Coastguard Worker 
6093*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("2ippWriteIO: wrote %d bytes",
6094*5e7646d2SAndroid Build Coastguard Worker 			  (int)(bufptr - buffer)));
6095*5e7646d2SAndroid Build Coastguard Worker 	  }
6096*5e7646d2SAndroid Build Coastguard Worker 
6097*5e7646d2SAndroid Build Coastguard Worker 	 /*
6098*5e7646d2SAndroid Build Coastguard Worker           * If blocking is disabled and we aren't at the end of the attribute
6099*5e7646d2SAndroid Build Coastguard Worker           * list, stop here...
6100*5e7646d2SAndroid Build Coastguard Worker 	  */
6101*5e7646d2SAndroid Build Coastguard Worker 
6102*5e7646d2SAndroid Build Coastguard Worker           if (!blocking && ipp->current)
6103*5e7646d2SAndroid Build Coastguard Worker 	    break;
6104*5e7646d2SAndroid Build Coastguard Worker 	}
6105*5e7646d2SAndroid Build Coastguard Worker 
6106*5e7646d2SAndroid Build Coastguard Worker 	if (ipp->current == NULL)
6107*5e7646d2SAndroid Build Coastguard Worker 	{
6108*5e7646d2SAndroid Build Coastguard Worker          /*
6109*5e7646d2SAndroid Build Coastguard Worker 	  * Done with all of the attributes; add the end-of-attributes
6110*5e7646d2SAndroid Build Coastguard Worker 	  * tag or end-collection attribute...
6111*5e7646d2SAndroid Build Coastguard Worker 	  */
6112*5e7646d2SAndroid Build Coastguard Worker 
6113*5e7646d2SAndroid Build Coastguard Worker           if (parent == NULL)
6114*5e7646d2SAndroid Build Coastguard Worker 	  {
6115*5e7646d2SAndroid Build Coastguard Worker             buffer[0] = IPP_TAG_END;
6116*5e7646d2SAndroid Build Coastguard Worker 	    n         = 1;
6117*5e7646d2SAndroid Build Coastguard Worker 	  }
6118*5e7646d2SAndroid Build Coastguard Worker 	  else
6119*5e7646d2SAndroid Build Coastguard Worker 	  {
6120*5e7646d2SAndroid Build Coastguard Worker             buffer[0] = IPP_TAG_END_COLLECTION;
6121*5e7646d2SAndroid Build Coastguard Worker 	    buffer[1] = 0; /* empty name */
6122*5e7646d2SAndroid Build Coastguard Worker 	    buffer[2] = 0;
6123*5e7646d2SAndroid Build Coastguard Worker 	    buffer[3] = 0; /* empty value */
6124*5e7646d2SAndroid Build Coastguard Worker 	    buffer[4] = 0;
6125*5e7646d2SAndroid Build Coastguard Worker 	    n         = 5;
6126*5e7646d2SAndroid Build Coastguard Worker 	  }
6127*5e7646d2SAndroid Build Coastguard Worker 
6128*5e7646d2SAndroid Build Coastguard Worker 	  if ((*cb)(dst, buffer, (size_t)n) < 0)
6129*5e7646d2SAndroid Build Coastguard Worker 	  {
6130*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
6131*5e7646d2SAndroid Build Coastguard Worker 	    _cupsBufferRelease((char *)buffer);
6132*5e7646d2SAndroid Build Coastguard Worker 	    return (IPP_STATE_ERROR);
6133*5e7646d2SAndroid Build Coastguard Worker 	  }
6134*5e7646d2SAndroid Build Coastguard Worker 
6135*5e7646d2SAndroid Build Coastguard Worker 	  ipp->state = IPP_STATE_DATA;
6136*5e7646d2SAndroid Build Coastguard Worker 	}
6137*5e7646d2SAndroid Build Coastguard Worker         break;
6138*5e7646d2SAndroid Build Coastguard Worker 
6139*5e7646d2SAndroid Build Coastguard Worker     case IPP_STATE_DATA :
6140*5e7646d2SAndroid Build Coastguard Worker         break;
6141*5e7646d2SAndroid Build Coastguard Worker 
6142*5e7646d2SAndroid Build Coastguard Worker     default :
6143*5e7646d2SAndroid Build Coastguard Worker         break; /* anti-compiler-warning-code */
6144*5e7646d2SAndroid Build Coastguard Worker   }
6145*5e7646d2SAndroid Build Coastguard Worker 
6146*5e7646d2SAndroid Build Coastguard Worker   _cupsBufferRelease((char *)buffer);
6147*5e7646d2SAndroid Build Coastguard Worker 
6148*5e7646d2SAndroid Build Coastguard Worker   return (ipp->state);
6149*5e7646d2SAndroid Build Coastguard Worker }
6150*5e7646d2SAndroid Build Coastguard Worker 
6151*5e7646d2SAndroid Build Coastguard Worker 
6152*5e7646d2SAndroid Build Coastguard Worker /*
6153*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_add_attr()' - Add a new attribute to the message.
6154*5e7646d2SAndroid Build Coastguard Worker  */
6155*5e7646d2SAndroid Build Coastguard Worker 
6156*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t *		/* O - New attribute */
ipp_add_attr(ipp_t * ipp,const char * name,ipp_tag_t group_tag,ipp_tag_t value_tag,int num_values)6157*5e7646d2SAndroid Build Coastguard Worker ipp_add_attr(ipp_t      *ipp,		/* I - IPP message */
6158*5e7646d2SAndroid Build Coastguard Worker              const char *name,		/* I - Attribute name or NULL */
6159*5e7646d2SAndroid Build Coastguard Worker              ipp_tag_t  group_tag,	/* I - Group tag or IPP_TAG_ZERO */
6160*5e7646d2SAndroid Build Coastguard Worker              ipp_tag_t  value_tag,	/* I - Value tag or IPP_TAG_ZERO */
6161*5e7646d2SAndroid Build Coastguard Worker              int        num_values)	/* I - Number of values */
6162*5e7646d2SAndroid Build Coastguard Worker {
6163*5e7646d2SAndroid Build Coastguard Worker   int			alloc_values;	/* Number of values to allocate */
6164*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* New attribute */
6165*5e7646d2SAndroid Build Coastguard Worker 
6166*5e7646d2SAndroid Build Coastguard Worker 
6167*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4ipp_add_attr(ipp=%p, name=\"%s\", group_tag=0x%x, value_tag=0x%x, num_values=%d)", (void *)ipp, name, group_tag, value_tag, num_values));
6168*5e7646d2SAndroid Build Coastguard Worker 
6169*5e7646d2SAndroid Build Coastguard Worker  /*
6170*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
6171*5e7646d2SAndroid Build Coastguard Worker   */
6172*5e7646d2SAndroid Build Coastguard Worker 
6173*5e7646d2SAndroid Build Coastguard Worker   if (!ipp || num_values < 0)
6174*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
6175*5e7646d2SAndroid Build Coastguard Worker 
6176*5e7646d2SAndroid Build Coastguard Worker  /*
6177*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory, rounding the allocation up as needed...
6178*5e7646d2SAndroid Build Coastguard Worker   */
6179*5e7646d2SAndroid Build Coastguard Worker 
6180*5e7646d2SAndroid Build Coastguard Worker   if (num_values <= 1)
6181*5e7646d2SAndroid Build Coastguard Worker     alloc_values = 1;
6182*5e7646d2SAndroid Build Coastguard Worker   else
6183*5e7646d2SAndroid Build Coastguard Worker     alloc_values = (num_values + IPP_MAX_VALUES - 1) & ~(IPP_MAX_VALUES - 1);
6184*5e7646d2SAndroid Build Coastguard Worker 
6185*5e7646d2SAndroid Build Coastguard Worker   attr = calloc(sizeof(ipp_attribute_t) +
6186*5e7646d2SAndroid Build Coastguard Worker                 (size_t)(alloc_values - 1) * sizeof(_ipp_value_t), 1);
6187*5e7646d2SAndroid Build Coastguard Worker 
6188*5e7646d2SAndroid Build Coastguard Worker   if (attr)
6189*5e7646d2SAndroid Build Coastguard Worker   {
6190*5e7646d2SAndroid Build Coastguard Worker    /*
6191*5e7646d2SAndroid Build Coastguard Worker     * Initialize attribute...
6192*5e7646d2SAndroid Build Coastguard Worker     */
6193*5e7646d2SAndroid Build Coastguard Worker 
6194*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_alloc: %p %s %s%s (%d values)", (void *)attr, name, num_values > 1 ? "1setOf " : "", ippTagString(value_tag), num_values));
6195*5e7646d2SAndroid Build Coastguard Worker 
6196*5e7646d2SAndroid Build Coastguard Worker     if (name)
6197*5e7646d2SAndroid Build Coastguard Worker       attr->name = _cupsStrAlloc(name);
6198*5e7646d2SAndroid Build Coastguard Worker 
6199*5e7646d2SAndroid Build Coastguard Worker     attr->group_tag  = group_tag;
6200*5e7646d2SAndroid Build Coastguard Worker     attr->value_tag  = value_tag;
6201*5e7646d2SAndroid Build Coastguard Worker     attr->num_values = num_values;
6202*5e7646d2SAndroid Build Coastguard Worker 
6203*5e7646d2SAndroid Build Coastguard Worker    /*
6204*5e7646d2SAndroid Build Coastguard Worker     * Add it to the end of the linked list...
6205*5e7646d2SAndroid Build Coastguard Worker     */
6206*5e7646d2SAndroid Build Coastguard Worker 
6207*5e7646d2SAndroid Build Coastguard Worker     if (ipp->last)
6208*5e7646d2SAndroid Build Coastguard Worker       ipp->last->next = attr;
6209*5e7646d2SAndroid Build Coastguard Worker     else
6210*5e7646d2SAndroid Build Coastguard Worker       ipp->attrs = attr;
6211*5e7646d2SAndroid Build Coastguard Worker 
6212*5e7646d2SAndroid Build Coastguard Worker     ipp->prev = ipp->last;
6213*5e7646d2SAndroid Build Coastguard Worker     ipp->last = ipp->current = attr;
6214*5e7646d2SAndroid Build Coastguard Worker   }
6215*5e7646d2SAndroid Build Coastguard Worker 
6216*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("5ipp_add_attr: Returning %p", (void *)attr));
6217*5e7646d2SAndroid Build Coastguard Worker 
6218*5e7646d2SAndroid Build Coastguard Worker   return (attr);
6219*5e7646d2SAndroid Build Coastguard Worker }
6220*5e7646d2SAndroid Build Coastguard Worker 
6221*5e7646d2SAndroid Build Coastguard Worker 
6222*5e7646d2SAndroid Build Coastguard Worker /*
6223*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_free_values()' - Free attribute values.
6224*5e7646d2SAndroid Build Coastguard Worker  */
6225*5e7646d2SAndroid Build Coastguard Worker 
6226*5e7646d2SAndroid Build Coastguard Worker static void
ipp_free_values(ipp_attribute_t * attr,int element,int count)6227*5e7646d2SAndroid Build Coastguard Worker ipp_free_values(ipp_attribute_t *attr,	/* I - Attribute to free values from */
6228*5e7646d2SAndroid Build Coastguard Worker                 int             element,/* I - First value to free */
6229*5e7646d2SAndroid Build Coastguard Worker                 int             count)	/* I - Number of values to free */
6230*5e7646d2SAndroid Build Coastguard Worker {
6231*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
6232*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t	*value;			/* Current value */
6233*5e7646d2SAndroid Build Coastguard Worker 
6234*5e7646d2SAndroid Build Coastguard Worker 
6235*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4ipp_free_values(attr=%p, element=%d, count=%d)", (void *)attr, element, count));
6236*5e7646d2SAndroid Build Coastguard Worker 
6237*5e7646d2SAndroid Build Coastguard Worker   if (!(attr->value_tag & IPP_TAG_CUPS_CONST))
6238*5e7646d2SAndroid Build Coastguard Worker   {
6239*5e7646d2SAndroid Build Coastguard Worker    /*
6240*5e7646d2SAndroid Build Coastguard Worker     * Free values as needed...
6241*5e7646d2SAndroid Build Coastguard Worker     */
6242*5e7646d2SAndroid Build Coastguard Worker 
6243*5e7646d2SAndroid Build Coastguard Worker     switch (attr->value_tag)
6244*5e7646d2SAndroid Build Coastguard Worker     {
6245*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXTLANG :
6246*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAMELANG :
6247*5e7646d2SAndroid Build Coastguard Worker 	  if (element == 0 && count == attr->num_values &&
6248*5e7646d2SAndroid Build Coastguard Worker 	      attr->values[0].string.language)
6249*5e7646d2SAndroid Build Coastguard Worker 	  {
6250*5e7646d2SAndroid Build Coastguard Worker 	    _cupsStrFree(attr->values[0].string.language);
6251*5e7646d2SAndroid Build Coastguard Worker 	    attr->values[0].string.language = NULL;
6252*5e7646d2SAndroid Build Coastguard Worker 	  }
6253*5e7646d2SAndroid Build Coastguard Worker 	  /* Fall through to other string values */
6254*5e7646d2SAndroid Build Coastguard Worker 
6255*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
6256*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
6257*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESERVED_STRING :
6258*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
6259*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URI :
6260*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
6261*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
6262*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
6263*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
6264*5e7646d2SAndroid Build Coastguard Worker 	  for (i = count, value = attr->values + element;
6265*5e7646d2SAndroid Build Coastguard Worker 	       i > 0;
6266*5e7646d2SAndroid Build Coastguard Worker 	       i --, value ++)
6267*5e7646d2SAndroid Build Coastguard Worker 	  {
6268*5e7646d2SAndroid Build Coastguard Worker 	    _cupsStrFree(value->string.text);
6269*5e7646d2SAndroid Build Coastguard Worker 	    value->string.text = NULL;
6270*5e7646d2SAndroid Build Coastguard Worker 	  }
6271*5e7646d2SAndroid Build Coastguard Worker 	  break;
6272*5e7646d2SAndroid Build Coastguard Worker 
6273*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_UNSUPPORTED_VALUE :
6274*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DEFAULT :
6275*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_UNKNOWN :
6276*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NOVALUE :
6277*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NOTSETTABLE :
6278*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DELETEATTR :
6279*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ADMINDEFINE :
6280*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
6281*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
6282*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BOOLEAN :
6283*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DATE :
6284*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESOLUTION :
6285*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
6286*5e7646d2SAndroid Build Coastguard Worker 	  break;
6287*5e7646d2SAndroid Build Coastguard Worker 
6288*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BEGIN_COLLECTION :
6289*5e7646d2SAndroid Build Coastguard Worker 	  for (i = count, value = attr->values + element;
6290*5e7646d2SAndroid Build Coastguard Worker 	       i > 0;
6291*5e7646d2SAndroid Build Coastguard Worker 	       i --, value ++)
6292*5e7646d2SAndroid Build Coastguard Worker 	  {
6293*5e7646d2SAndroid Build Coastguard Worker 	    ippDelete(value->collection);
6294*5e7646d2SAndroid Build Coastguard Worker 	    value->collection = NULL;
6295*5e7646d2SAndroid Build Coastguard Worker 	  }
6296*5e7646d2SAndroid Build Coastguard Worker 	  break;
6297*5e7646d2SAndroid Build Coastguard Worker 
6298*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_STRING :
6299*5e7646d2SAndroid Build Coastguard Worker       default :
6300*5e7646d2SAndroid Build Coastguard Worker 	  for (i = count, value = attr->values + element;
6301*5e7646d2SAndroid Build Coastguard Worker 	       i > 0;
6302*5e7646d2SAndroid Build Coastguard Worker 	       i --, value ++)
6303*5e7646d2SAndroid Build Coastguard Worker 	  {
6304*5e7646d2SAndroid Build Coastguard Worker 	    if (value->unknown.data)
6305*5e7646d2SAndroid Build Coastguard Worker 	    {
6306*5e7646d2SAndroid Build Coastguard Worker 	      free(value->unknown.data);
6307*5e7646d2SAndroid Build Coastguard Worker 	      value->unknown.data = NULL;
6308*5e7646d2SAndroid Build Coastguard Worker 	    }
6309*5e7646d2SAndroid Build Coastguard Worker 	  }
6310*5e7646d2SAndroid Build Coastguard Worker 	  break;
6311*5e7646d2SAndroid Build Coastguard Worker     }
6312*5e7646d2SAndroid Build Coastguard Worker   }
6313*5e7646d2SAndroid Build Coastguard Worker 
6314*5e7646d2SAndroid Build Coastguard Worker  /*
6315*5e7646d2SAndroid Build Coastguard Worker   * If we are not freeing values from the end, move the remaining values up...
6316*5e7646d2SAndroid Build Coastguard Worker   */
6317*5e7646d2SAndroid Build Coastguard Worker 
6318*5e7646d2SAndroid Build Coastguard Worker   if ((element + count) < attr->num_values)
6319*5e7646d2SAndroid Build Coastguard Worker     memmove(attr->values + element, attr->values + element + count,
6320*5e7646d2SAndroid Build Coastguard Worker             (size_t)(attr->num_values - count - element) * sizeof(_ipp_value_t));
6321*5e7646d2SAndroid Build Coastguard Worker 
6322*5e7646d2SAndroid Build Coastguard Worker   attr->num_values -= count;
6323*5e7646d2SAndroid Build Coastguard Worker }
6324*5e7646d2SAndroid Build Coastguard Worker 
6325*5e7646d2SAndroid Build Coastguard Worker 
6326*5e7646d2SAndroid Build Coastguard Worker /*
6327*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_get_code()' - Convert a C locale/charset name into an IPP language/charset code.
6328*5e7646d2SAndroid Build Coastguard Worker  *
6329*5e7646d2SAndroid Build Coastguard Worker  * This typically converts strings of the form "ll_CC", "ll-REGION", and "CHARSET_NUMBER"
6330*5e7646d2SAndroid Build Coastguard Worker  * to "ll-cc", "ll-region", and "charset-number", respectively.
6331*5e7646d2SAndroid Build Coastguard Worker  */
6332*5e7646d2SAndroid Build Coastguard Worker 
6333*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - Language code string */
ipp_get_code(const char * value,char * buffer,size_t bufsize)6334*5e7646d2SAndroid Build Coastguard Worker ipp_get_code(const char *value,		/* I - Locale/charset string */
6335*5e7646d2SAndroid Build Coastguard Worker              char       *buffer,	/* I - String buffer */
6336*5e7646d2SAndroid Build Coastguard Worker              size_t     bufsize)	/* I - Size of string buffer */
6337*5e7646d2SAndroid Build Coastguard Worker {
6338*5e7646d2SAndroid Build Coastguard Worker   char	*bufptr,			/* Pointer into buffer */
6339*5e7646d2SAndroid Build Coastguard Worker 	*bufend;			/* End of buffer */
6340*5e7646d2SAndroid Build Coastguard Worker 
6341*5e7646d2SAndroid Build Coastguard Worker 
6342*5e7646d2SAndroid Build Coastguard Worker  /*
6343*5e7646d2SAndroid Build Coastguard Worker   * Convert values to lowercase and change _ to - as needed...
6344*5e7646d2SAndroid Build Coastguard Worker   */
6345*5e7646d2SAndroid Build Coastguard Worker 
6346*5e7646d2SAndroid Build Coastguard Worker   for (bufptr = buffer, bufend = buffer + bufsize - 1;
6347*5e7646d2SAndroid Build Coastguard Worker        *value && bufptr < bufend;
6348*5e7646d2SAndroid Build Coastguard Worker        value ++)
6349*5e7646d2SAndroid Build Coastguard Worker     if (*value == '_')
6350*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = '-';
6351*5e7646d2SAndroid Build Coastguard Worker     else
6352*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = (char)_cups_tolower(*value);
6353*5e7646d2SAndroid Build Coastguard Worker 
6354*5e7646d2SAndroid Build Coastguard Worker   *bufptr = '\0';
6355*5e7646d2SAndroid Build Coastguard Worker 
6356*5e7646d2SAndroid Build Coastguard Worker  /*
6357*5e7646d2SAndroid Build Coastguard Worker   * Return the converted string...
6358*5e7646d2SAndroid Build Coastguard Worker   */
6359*5e7646d2SAndroid Build Coastguard Worker 
6360*5e7646d2SAndroid Build Coastguard Worker   return (buffer);
6361*5e7646d2SAndroid Build Coastguard Worker }
6362*5e7646d2SAndroid Build Coastguard Worker 
6363*5e7646d2SAndroid Build Coastguard Worker 
6364*5e7646d2SAndroid Build Coastguard Worker /*
6365*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_lang_code()' - Convert a C locale name into an IPP language code.
6366*5e7646d2SAndroid Build Coastguard Worker  *
6367*5e7646d2SAndroid Build Coastguard Worker  * This typically converts strings of the form "ll_CC" and "ll-REGION" to "ll-cc" and
6368*5e7646d2SAndroid Build Coastguard Worker  * "ll-region", respectively.  It also converts the "C" (POSIX) locale to "en".
6369*5e7646d2SAndroid Build Coastguard Worker  */
6370*5e7646d2SAndroid Build Coastguard Worker 
6371*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - Language code string */
ipp_lang_code(const char * locale,char * buffer,size_t bufsize)6372*5e7646d2SAndroid Build Coastguard Worker ipp_lang_code(const char *locale,	/* I - Locale string */
6373*5e7646d2SAndroid Build Coastguard Worker               char       *buffer,	/* I - String buffer */
6374*5e7646d2SAndroid Build Coastguard Worker               size_t     bufsize)	/* I - Size of string buffer */
6375*5e7646d2SAndroid Build Coastguard Worker {
6376*5e7646d2SAndroid Build Coastguard Worker  /*
6377*5e7646d2SAndroid Build Coastguard Worker   * Map POSIX ("C") locale to generic English, otherwise convert the locale string as-is.
6378*5e7646d2SAndroid Build Coastguard Worker   */
6379*5e7646d2SAndroid Build Coastguard Worker 
6380*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(locale, "c"))
6381*5e7646d2SAndroid Build Coastguard Worker   {
6382*5e7646d2SAndroid Build Coastguard Worker     strlcpy(buffer, "en", bufsize);
6383*5e7646d2SAndroid Build Coastguard Worker     return (buffer);
6384*5e7646d2SAndroid Build Coastguard Worker   }
6385*5e7646d2SAndroid Build Coastguard Worker   else
6386*5e7646d2SAndroid Build Coastguard Worker     return (ipp_get_code(locale, buffer, bufsize));
6387*5e7646d2SAndroid Build Coastguard Worker }
6388*5e7646d2SAndroid Build Coastguard Worker 
6389*5e7646d2SAndroid Build Coastguard Worker 
6390*5e7646d2SAndroid Build Coastguard Worker /*
6391*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_length()' - Compute the length of an IPP message or collection value.
6392*5e7646d2SAndroid Build Coastguard Worker  */
6393*5e7646d2SAndroid Build Coastguard Worker 
6394*5e7646d2SAndroid Build Coastguard Worker static size_t				/* O - Size of IPP message */
ipp_length(ipp_t * ipp,int collection)6395*5e7646d2SAndroid Build Coastguard Worker ipp_length(ipp_t *ipp,			/* I - IPP message or collection */
6396*5e7646d2SAndroid Build Coastguard Worker            int   collection)		/* I - 1 if a collection, 0 otherwise */
6397*5e7646d2SAndroid Build Coastguard Worker {
6398*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
6399*5e7646d2SAndroid Build Coastguard Worker   size_t		bytes;		/* Number of bytes */
6400*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
6401*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		group;		/* Current group */
6402*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*value;		/* Current value */
6403*5e7646d2SAndroid Build Coastguard Worker 
6404*5e7646d2SAndroid Build Coastguard Worker 
6405*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3ipp_length(ipp=%p, collection=%d)", (void *)ipp, collection));
6406*5e7646d2SAndroid Build Coastguard Worker 
6407*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
6408*5e7646d2SAndroid Build Coastguard Worker   {
6409*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4ipp_length: Returning 0 bytes");
6410*5e7646d2SAndroid Build Coastguard Worker     return (0);
6411*5e7646d2SAndroid Build Coastguard Worker   }
6412*5e7646d2SAndroid Build Coastguard Worker 
6413*5e7646d2SAndroid Build Coastguard Worker  /*
6414*5e7646d2SAndroid Build Coastguard Worker   * Start with 8 bytes for the IPP message header...
6415*5e7646d2SAndroid Build Coastguard Worker   */
6416*5e7646d2SAndroid Build Coastguard Worker 
6417*5e7646d2SAndroid Build Coastguard Worker   bytes = collection ? 0 : 8;
6418*5e7646d2SAndroid Build Coastguard Worker 
6419*5e7646d2SAndroid Build Coastguard Worker  /*
6420*5e7646d2SAndroid Build Coastguard Worker   * Then add the lengths of each attribute...
6421*5e7646d2SAndroid Build Coastguard Worker   */
6422*5e7646d2SAndroid Build Coastguard Worker 
6423*5e7646d2SAndroid Build Coastguard Worker   group = IPP_TAG_ZERO;
6424*5e7646d2SAndroid Build Coastguard Worker 
6425*5e7646d2SAndroid Build Coastguard Worker   for (attr = ipp->attrs; attr != NULL; attr = attr->next)
6426*5e7646d2SAndroid Build Coastguard Worker   {
6427*5e7646d2SAndroid Build Coastguard Worker     if (attr->group_tag != group && !collection)
6428*5e7646d2SAndroid Build Coastguard Worker     {
6429*5e7646d2SAndroid Build Coastguard Worker       group = attr->group_tag;
6430*5e7646d2SAndroid Build Coastguard Worker       if (group == IPP_TAG_ZERO)
6431*5e7646d2SAndroid Build Coastguard Worker 	continue;
6432*5e7646d2SAndroid Build Coastguard Worker 
6433*5e7646d2SAndroid Build Coastguard Worker       bytes ++;	/* Group tag */
6434*5e7646d2SAndroid Build Coastguard Worker     }
6435*5e7646d2SAndroid Build Coastguard Worker 
6436*5e7646d2SAndroid Build Coastguard Worker     if (!attr->name)
6437*5e7646d2SAndroid Build Coastguard Worker       continue;
6438*5e7646d2SAndroid Build Coastguard Worker 
6439*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5ipp_length: attr->name=\"%s\", attr->num_values=%d, "
6440*5e7646d2SAndroid Build Coastguard Worker                   "bytes=" CUPS_LLFMT, attr->name, attr->num_values, CUPS_LLCAST bytes));
6441*5e7646d2SAndroid Build Coastguard Worker 
6442*5e7646d2SAndroid Build Coastguard Worker     if ((attr->value_tag & ~IPP_TAG_CUPS_CONST) < IPP_TAG_EXTENSION)
6443*5e7646d2SAndroid Build Coastguard Worker       bytes += (size_t)attr->num_values;/* Value tag for each value */
6444*5e7646d2SAndroid Build Coastguard Worker     else
6445*5e7646d2SAndroid Build Coastguard Worker       bytes += (size_t)(5 * attr->num_values);
6446*5e7646d2SAndroid Build Coastguard Worker 					/* Value tag for each value */
6447*5e7646d2SAndroid Build Coastguard Worker     bytes += (size_t)(2 * attr->num_values);
6448*5e7646d2SAndroid Build Coastguard Worker 					/* Name lengths */
6449*5e7646d2SAndroid Build Coastguard Worker     bytes += strlen(attr->name);	/* Name */
6450*5e7646d2SAndroid Build Coastguard Worker     bytes += (size_t)(2 * attr->num_values);
6451*5e7646d2SAndroid Build Coastguard Worker 					/* Value lengths */
6452*5e7646d2SAndroid Build Coastguard Worker 
6453*5e7646d2SAndroid Build Coastguard Worker     if (collection)
6454*5e7646d2SAndroid Build Coastguard Worker       bytes += 5;			/* Add membername overhead */
6455*5e7646d2SAndroid Build Coastguard Worker 
6456*5e7646d2SAndroid Build Coastguard Worker     switch (attr->value_tag & ~IPP_TAG_CUPS_CONST)
6457*5e7646d2SAndroid Build Coastguard Worker     {
6458*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_UNSUPPORTED_VALUE :
6459*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DEFAULT :
6460*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_UNKNOWN :
6461*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NOVALUE :
6462*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NOTSETTABLE :
6463*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DELETEATTR :
6464*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ADMINDEFINE :
6465*5e7646d2SAndroid Build Coastguard Worker           break;
6466*5e7646d2SAndroid Build Coastguard Worker 
6467*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
6468*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
6469*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)(4 * attr->num_values);
6470*5e7646d2SAndroid Build Coastguard Worker 	  break;
6471*5e7646d2SAndroid Build Coastguard Worker 
6472*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BOOLEAN :
6473*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)attr->num_values;
6474*5e7646d2SAndroid Build Coastguard Worker 	  break;
6475*5e7646d2SAndroid Build Coastguard Worker 
6476*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
6477*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
6478*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
6479*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URI :
6480*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
6481*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
6482*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
6483*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
6484*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0, value = attr->values;
6485*5e7646d2SAndroid Build Coastguard Worker 	       i < attr->num_values;
6486*5e7646d2SAndroid Build Coastguard Worker 	       i ++, value ++)
6487*5e7646d2SAndroid Build Coastguard Worker 	    if (value->string.text)
6488*5e7646d2SAndroid Build Coastguard Worker 	      bytes += strlen(value->string.text);
6489*5e7646d2SAndroid Build Coastguard Worker 	  break;
6490*5e7646d2SAndroid Build Coastguard Worker 
6491*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DATE :
6492*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)(11 * attr->num_values);
6493*5e7646d2SAndroid Build Coastguard Worker 	  break;
6494*5e7646d2SAndroid Build Coastguard Worker 
6495*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESOLUTION :
6496*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)(9 * attr->num_values);
6497*5e7646d2SAndroid Build Coastguard Worker 	  break;
6498*5e7646d2SAndroid Build Coastguard Worker 
6499*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
6500*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)(8 * attr->num_values);
6501*5e7646d2SAndroid Build Coastguard Worker 	  break;
6502*5e7646d2SAndroid Build Coastguard Worker 
6503*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXTLANG :
6504*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAMELANG :
6505*5e7646d2SAndroid Build Coastguard Worker           bytes += (size_t)(4 * attr->num_values);
6506*5e7646d2SAndroid Build Coastguard Worker 					/* Charset + text length */
6507*5e7646d2SAndroid Build Coastguard Worker 
6508*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0, value = attr->values;
6509*5e7646d2SAndroid Build Coastguard Worker 	       i < attr->num_values;
6510*5e7646d2SAndroid Build Coastguard Worker 	       i ++, value ++)
6511*5e7646d2SAndroid Build Coastguard Worker 	  {
6512*5e7646d2SAndroid Build Coastguard Worker 	    if (value->string.language)
6513*5e7646d2SAndroid Build Coastguard Worker 	      bytes += strlen(value->string.language);
6514*5e7646d2SAndroid Build Coastguard Worker 
6515*5e7646d2SAndroid Build Coastguard Worker 	    if (value->string.text)
6516*5e7646d2SAndroid Build Coastguard Worker 	      bytes += strlen(value->string.text);
6517*5e7646d2SAndroid Build Coastguard Worker 	  }
6518*5e7646d2SAndroid Build Coastguard Worker 	  break;
6519*5e7646d2SAndroid Build Coastguard Worker 
6520*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BEGIN_COLLECTION :
6521*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0, value = attr->values;
6522*5e7646d2SAndroid Build Coastguard Worker 	       i < attr->num_values;
6523*5e7646d2SAndroid Build Coastguard Worker 	       i ++, value ++)
6524*5e7646d2SAndroid Build Coastguard Worker             bytes += ipp_length(value->collection, 1);
6525*5e7646d2SAndroid Build Coastguard Worker 	  break;
6526*5e7646d2SAndroid Build Coastguard Worker 
6527*5e7646d2SAndroid Build Coastguard Worker       default :
6528*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0, value = attr->values;
6529*5e7646d2SAndroid Build Coastguard Worker 	       i < attr->num_values;
6530*5e7646d2SAndroid Build Coastguard Worker 	       i ++, value ++)
6531*5e7646d2SAndroid Build Coastguard Worker             bytes += (size_t)value->unknown.length;
6532*5e7646d2SAndroid Build Coastguard Worker 	  break;
6533*5e7646d2SAndroid Build Coastguard Worker     }
6534*5e7646d2SAndroid Build Coastguard Worker   }
6535*5e7646d2SAndroid Build Coastguard Worker 
6536*5e7646d2SAndroid Build Coastguard Worker  /*
6537*5e7646d2SAndroid Build Coastguard Worker   * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
6538*5e7646d2SAndroid Build Coastguard Worker   * for the "end of collection" tag and return...
6539*5e7646d2SAndroid Build Coastguard Worker   */
6540*5e7646d2SAndroid Build Coastguard Worker 
6541*5e7646d2SAndroid Build Coastguard Worker   if (collection)
6542*5e7646d2SAndroid Build Coastguard Worker     bytes += 5;
6543*5e7646d2SAndroid Build Coastguard Worker   else
6544*5e7646d2SAndroid Build Coastguard Worker     bytes ++;
6545*5e7646d2SAndroid Build Coastguard Worker 
6546*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4ipp_length: Returning " CUPS_LLFMT " bytes", CUPS_LLCAST bytes));
6547*5e7646d2SAndroid Build Coastguard Worker 
6548*5e7646d2SAndroid Build Coastguard Worker   return (bytes);
6549*5e7646d2SAndroid Build Coastguard Worker }
6550*5e7646d2SAndroid Build Coastguard Worker 
6551*5e7646d2SAndroid Build Coastguard Worker 
6552*5e7646d2SAndroid Build Coastguard Worker /*
6553*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
6554*5e7646d2SAndroid Build Coastguard Worker  */
6555*5e7646d2SAndroid Build Coastguard Worker 
6556*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Number of bytes read */
ipp_read_http(http_t * http,ipp_uchar_t * buffer,size_t length)6557*5e7646d2SAndroid Build Coastguard Worker ipp_read_http(http_t      *http,	/* I - Client connection */
6558*5e7646d2SAndroid Build Coastguard Worker               ipp_uchar_t *buffer,	/* O - Buffer for data */
6559*5e7646d2SAndroid Build Coastguard Worker 	      size_t      length)	/* I - Total length */
6560*5e7646d2SAndroid Build Coastguard Worker {
6561*5e7646d2SAndroid Build Coastguard Worker   ssize_t	tbytes,			/* Total bytes read */
6562*5e7646d2SAndroid Build Coastguard Worker 		bytes;			/* Bytes read this pass */
6563*5e7646d2SAndroid Build Coastguard Worker 
6564*5e7646d2SAndroid Build Coastguard Worker 
6565*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)", (void *)http, (void *)buffer, (int)length));
6566*5e7646d2SAndroid Build Coastguard Worker 
6567*5e7646d2SAndroid Build Coastguard Worker  /*
6568*5e7646d2SAndroid Build Coastguard Worker   * Loop until all bytes are read...
6569*5e7646d2SAndroid Build Coastguard Worker   */
6570*5e7646d2SAndroid Build Coastguard Worker 
6571*5e7646d2SAndroid Build Coastguard Worker   for (tbytes = 0, bytes = 0;
6572*5e7646d2SAndroid Build Coastguard Worker        tbytes < (int)length;
6573*5e7646d2SAndroid Build Coastguard Worker        tbytes += bytes, buffer += bytes)
6574*5e7646d2SAndroid Build Coastguard Worker   {
6575*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("9ipp_read_http: tbytes=" CUPS_LLFMT ", http->state=%d", CUPS_LLCAST tbytes, http->state));
6576*5e7646d2SAndroid Build Coastguard Worker 
6577*5e7646d2SAndroid Build Coastguard Worker     if (http->state == HTTP_STATE_WAITING)
6578*5e7646d2SAndroid Build Coastguard Worker       break;
6579*5e7646d2SAndroid Build Coastguard Worker 
6580*5e7646d2SAndroid Build Coastguard Worker     if (http->used == 0 && !http->blocking)
6581*5e7646d2SAndroid Build Coastguard Worker     {
6582*5e7646d2SAndroid Build Coastguard Worker      /*
6583*5e7646d2SAndroid Build Coastguard Worker       * Wait up to 10 seconds for more data on non-blocking sockets...
6584*5e7646d2SAndroid Build Coastguard Worker       */
6585*5e7646d2SAndroid Build Coastguard Worker 
6586*5e7646d2SAndroid Build Coastguard Worker       if (!httpWait(http, 10000))
6587*5e7646d2SAndroid Build Coastguard Worker       {
6588*5e7646d2SAndroid Build Coastguard Worker        /*
6589*5e7646d2SAndroid Build Coastguard Worker 	* Signal no data...
6590*5e7646d2SAndroid Build Coastguard Worker 	*/
6591*5e7646d2SAndroid Build Coastguard Worker 
6592*5e7646d2SAndroid Build Coastguard Worker 	bytes = -1;
6593*5e7646d2SAndroid Build Coastguard Worker 	break;
6594*5e7646d2SAndroid Build Coastguard Worker       }
6595*5e7646d2SAndroid Build Coastguard Worker     }
6596*5e7646d2SAndroid Build Coastguard Worker     else if (http->used == 0 && http->timeout_value > 0)
6597*5e7646d2SAndroid Build Coastguard Worker     {
6598*5e7646d2SAndroid Build Coastguard Worker      /*
6599*5e7646d2SAndroid Build Coastguard Worker       * Wait up to timeout seconds for more data on blocking sockets...
6600*5e7646d2SAndroid Build Coastguard Worker       */
6601*5e7646d2SAndroid Build Coastguard Worker 
6602*5e7646d2SAndroid Build Coastguard Worker       if (!httpWait(http, (int)(1000 * http->timeout_value)))
6603*5e7646d2SAndroid Build Coastguard Worker       {
6604*5e7646d2SAndroid Build Coastguard Worker        /*
6605*5e7646d2SAndroid Build Coastguard Worker 	* Signal no data...
6606*5e7646d2SAndroid Build Coastguard Worker 	*/
6607*5e7646d2SAndroid Build Coastguard Worker 
6608*5e7646d2SAndroid Build Coastguard Worker 	bytes = -1;
6609*5e7646d2SAndroid Build Coastguard Worker 	break;
6610*5e7646d2SAndroid Build Coastguard Worker       }
6611*5e7646d2SAndroid Build Coastguard Worker     }
6612*5e7646d2SAndroid Build Coastguard Worker 
6613*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = httpRead2(http, (char *)buffer, length - (size_t)tbytes)) < 0)
6614*5e7646d2SAndroid Build Coastguard Worker     {
6615*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
6616*5e7646d2SAndroid Build Coastguard Worker       break;
6617*5e7646d2SAndroid Build Coastguard Worker #else
6618*5e7646d2SAndroid Build Coastguard Worker       if (errno != EAGAIN && errno != EINTR)
6619*5e7646d2SAndroid Build Coastguard Worker 	break;
6620*5e7646d2SAndroid Build Coastguard Worker 
6621*5e7646d2SAndroid Build Coastguard Worker       bytes = 0;
6622*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
6623*5e7646d2SAndroid Build Coastguard Worker     }
6624*5e7646d2SAndroid Build Coastguard Worker     else if (bytes == 0)
6625*5e7646d2SAndroid Build Coastguard Worker       break;
6626*5e7646d2SAndroid Build Coastguard Worker   }
6627*5e7646d2SAndroid Build Coastguard Worker 
6628*5e7646d2SAndroid Build Coastguard Worker  /*
6629*5e7646d2SAndroid Build Coastguard Worker   * Return the number of bytes read...
6630*5e7646d2SAndroid Build Coastguard Worker   */
6631*5e7646d2SAndroid Build Coastguard Worker 
6632*5e7646d2SAndroid Build Coastguard Worker   if (tbytes == 0 && bytes < 0)
6633*5e7646d2SAndroid Build Coastguard Worker     tbytes = -1;
6634*5e7646d2SAndroid Build Coastguard Worker 
6635*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("8ipp_read_http: Returning " CUPS_LLFMT " bytes", CUPS_LLCAST tbytes));
6636*5e7646d2SAndroid Build Coastguard Worker 
6637*5e7646d2SAndroid Build Coastguard Worker   return (tbytes);
6638*5e7646d2SAndroid Build Coastguard Worker }
6639*5e7646d2SAndroid Build Coastguard Worker 
6640*5e7646d2SAndroid Build Coastguard Worker 
6641*5e7646d2SAndroid Build Coastguard Worker /*
6642*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_read_file()' - Read IPP data from a file.
6643*5e7646d2SAndroid Build Coastguard Worker  */
6644*5e7646d2SAndroid Build Coastguard Worker 
6645*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Number of bytes read */
ipp_read_file(int * fd,ipp_uchar_t * buffer,size_t length)6646*5e7646d2SAndroid Build Coastguard Worker ipp_read_file(int         *fd,		/* I - File descriptor */
6647*5e7646d2SAndroid Build Coastguard Worker               ipp_uchar_t *buffer,	/* O - Read buffer */
6648*5e7646d2SAndroid Build Coastguard Worker 	      size_t      length)	/* I - Number of bytes to read */
6649*5e7646d2SAndroid Build Coastguard Worker {
6650*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
6651*5e7646d2SAndroid Build Coastguard Worker   return ((ssize_t)read(*fd, buffer, (unsigned)length));
6652*5e7646d2SAndroid Build Coastguard Worker #else
6653*5e7646d2SAndroid Build Coastguard Worker   return (read(*fd, buffer, length));
6654*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
6655*5e7646d2SAndroid Build Coastguard Worker }
6656*5e7646d2SAndroid Build Coastguard Worker 
6657*5e7646d2SAndroid Build Coastguard Worker 
6658*5e7646d2SAndroid Build Coastguard Worker /*
6659*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_set_error()' - Set a formatted, localized error string.
6660*5e7646d2SAndroid Build Coastguard Worker  */
6661*5e7646d2SAndroid Build Coastguard Worker 
6662*5e7646d2SAndroid Build Coastguard Worker static void
ipp_set_error(ipp_status_t status,const char * format,...)6663*5e7646d2SAndroid Build Coastguard Worker ipp_set_error(ipp_status_t status,	/* I - Status code */
6664*5e7646d2SAndroid Build Coastguard Worker               const char   *format,	/* I - Printf-style error string */
6665*5e7646d2SAndroid Build Coastguard Worker 	      ...)			/* I - Additional arguments as needed */
6666*5e7646d2SAndroid Build Coastguard Worker {
6667*5e7646d2SAndroid Build Coastguard Worker   va_list	ap;			/* Pointer to additional args */
6668*5e7646d2SAndroid Build Coastguard Worker   char		buffer[2048];		/* Message buffer */
6669*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t	*lang = cupsLangDefault();
6670*5e7646d2SAndroid Build Coastguard Worker 					/* Current language */
6671*5e7646d2SAndroid Build Coastguard Worker 
6672*5e7646d2SAndroid Build Coastguard Worker 
6673*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, format);
6674*5e7646d2SAndroid Build Coastguard Worker   vsnprintf(buffer, sizeof(buffer), _cupsLangString(lang, format), ap);
6675*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
6676*5e7646d2SAndroid Build Coastguard Worker 
6677*5e7646d2SAndroid Build Coastguard Worker   _cupsSetError(status, buffer, 0);
6678*5e7646d2SAndroid Build Coastguard Worker }
6679*5e7646d2SAndroid Build Coastguard Worker 
6680*5e7646d2SAndroid Build Coastguard Worker 
6681*5e7646d2SAndroid Build Coastguard Worker /*
6682*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_set_value()' - Get the value element from an attribute, expanding it as
6683*5e7646d2SAndroid Build Coastguard Worker  *                     needed.
6684*5e7646d2SAndroid Build Coastguard Worker  */
6685*5e7646d2SAndroid Build Coastguard Worker 
6686*5e7646d2SAndroid Build Coastguard Worker static _ipp_value_t *			/* O  - IPP value element or NULL on error */
ipp_set_value(ipp_t * ipp,ipp_attribute_t ** attr,int element)6687*5e7646d2SAndroid Build Coastguard Worker ipp_set_value(ipp_t           *ipp,	/* IO - IPP message */
6688*5e7646d2SAndroid Build Coastguard Worker               ipp_attribute_t **attr,	/* IO - IPP attribute */
6689*5e7646d2SAndroid Build Coastguard Worker               int             element)	/* I  - Value number (0-based) */
6690*5e7646d2SAndroid Build Coastguard Worker {
6691*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*temp,		/* New attribute pointer */
6692*5e7646d2SAndroid Build Coastguard Worker 			*current,	/* Current attribute in list */
6693*5e7646d2SAndroid Build Coastguard Worker 			*prev;		/* Previous attribute in list */
6694*5e7646d2SAndroid Build Coastguard Worker   int			alloc_values;	/* Allocated values */
6695*5e7646d2SAndroid Build Coastguard Worker 
6696*5e7646d2SAndroid Build Coastguard Worker 
6697*5e7646d2SAndroid Build Coastguard Worker  /*
6698*5e7646d2SAndroid Build Coastguard Worker   * If we are setting an existing value element, return it...
6699*5e7646d2SAndroid Build Coastguard Worker   */
6700*5e7646d2SAndroid Build Coastguard Worker 
6701*5e7646d2SAndroid Build Coastguard Worker   temp = *attr;
6702*5e7646d2SAndroid Build Coastguard Worker 
6703*5e7646d2SAndroid Build Coastguard Worker   if (temp->num_values <= 1)
6704*5e7646d2SAndroid Build Coastguard Worker     alloc_values = 1;
6705*5e7646d2SAndroid Build Coastguard Worker   else
6706*5e7646d2SAndroid Build Coastguard Worker     alloc_values = (temp->num_values + IPP_MAX_VALUES - 1) &
6707*5e7646d2SAndroid Build Coastguard Worker                    ~(IPP_MAX_VALUES - 1);
6708*5e7646d2SAndroid Build Coastguard Worker 
6709*5e7646d2SAndroid Build Coastguard Worker   if (element < alloc_values)
6710*5e7646d2SAndroid Build Coastguard Worker   {
6711*5e7646d2SAndroid Build Coastguard Worker     if (element >= temp->num_values)
6712*5e7646d2SAndroid Build Coastguard Worker       temp->num_values = element + 1;
6713*5e7646d2SAndroid Build Coastguard Worker 
6714*5e7646d2SAndroid Build Coastguard Worker     return (temp->values + element);
6715*5e7646d2SAndroid Build Coastguard Worker   }
6716*5e7646d2SAndroid Build Coastguard Worker 
6717*5e7646d2SAndroid Build Coastguard Worker  /*
6718*5e7646d2SAndroid Build Coastguard Worker   * Otherwise re-allocate the attribute - we allocate in groups of IPP_MAX_VALUE
6719*5e7646d2SAndroid Build Coastguard Worker   * values when num_values > 1.
6720*5e7646d2SAndroid Build Coastguard Worker   */
6721*5e7646d2SAndroid Build Coastguard Worker 
6722*5e7646d2SAndroid Build Coastguard Worker   if (alloc_values < IPP_MAX_VALUES)
6723*5e7646d2SAndroid Build Coastguard Worker     alloc_values = IPP_MAX_VALUES;
6724*5e7646d2SAndroid Build Coastguard Worker   else
6725*5e7646d2SAndroid Build Coastguard Worker     alloc_values += IPP_MAX_VALUES;
6726*5e7646d2SAndroid Build Coastguard Worker 
6727*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4ipp_set_value: Reallocating for up to %d values.",
6728*5e7646d2SAndroid Build Coastguard Worker                 alloc_values));
6729*5e7646d2SAndroid Build Coastguard Worker 
6730*5e7646d2SAndroid Build Coastguard Worker  /*
6731*5e7646d2SAndroid Build Coastguard Worker   * Reallocate memory...
6732*5e7646d2SAndroid Build Coastguard Worker   */
6733*5e7646d2SAndroid Build Coastguard Worker 
6734*5e7646d2SAndroid Build Coastguard Worker   if ((temp = realloc(temp, sizeof(ipp_attribute_t) + (size_t)(alloc_values - 1) * sizeof(_ipp_value_t))) == NULL)
6735*5e7646d2SAndroid Build Coastguard Worker   {
6736*5e7646d2SAndroid Build Coastguard Worker     _cupsSetHTTPError(HTTP_STATUS_ERROR);
6737*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4ipp_set_value: Unable to resize attribute.");
6738*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
6739*5e7646d2SAndroid Build Coastguard Worker   }
6740*5e7646d2SAndroid Build Coastguard Worker 
6741*5e7646d2SAndroid Build Coastguard Worker  /*
6742*5e7646d2SAndroid Build Coastguard Worker   * Zero the new memory...
6743*5e7646d2SAndroid Build Coastguard Worker   */
6744*5e7646d2SAndroid Build Coastguard Worker 
6745*5e7646d2SAndroid Build Coastguard Worker   memset(temp->values + temp->num_values, 0, (size_t)(alloc_values - temp->num_values) * sizeof(_ipp_value_t));
6746*5e7646d2SAndroid Build Coastguard Worker 
6747*5e7646d2SAndroid Build Coastguard Worker   if (temp != *attr)
6748*5e7646d2SAndroid Build Coastguard Worker   {
6749*5e7646d2SAndroid Build Coastguard Worker    /*
6750*5e7646d2SAndroid Build Coastguard Worker     * Reset pointers in the list...
6751*5e7646d2SAndroid Build Coastguard Worker     */
6752*5e7646d2SAndroid Build Coastguard Worker 
6753*5e7646d2SAndroid Build Coastguard Worker #ifndef __clang_analyzer__
6754*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_free: %p %s", (void *)*attr, temp->name));
6755*5e7646d2SAndroid Build Coastguard Worker #endif /* !__clang_analyzer__ */
6756*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4debug_alloc: %p %s %s%s (%d)", (void *)temp, temp->name, temp->num_values > 1 ? "1setOf " : "", ippTagString(temp->value_tag), temp->num_values));
6757*5e7646d2SAndroid Build Coastguard Worker 
6758*5e7646d2SAndroid Build Coastguard Worker     if (ipp->current == *attr && ipp->prev)
6759*5e7646d2SAndroid Build Coastguard Worker     {
6760*5e7646d2SAndroid Build Coastguard Worker      /*
6761*5e7646d2SAndroid Build Coastguard Worker       * Use current "previous" pointer...
6762*5e7646d2SAndroid Build Coastguard Worker       */
6763*5e7646d2SAndroid Build Coastguard Worker 
6764*5e7646d2SAndroid Build Coastguard Worker       prev = ipp->prev;
6765*5e7646d2SAndroid Build Coastguard Worker     }
6766*5e7646d2SAndroid Build Coastguard Worker     else
6767*5e7646d2SAndroid Build Coastguard Worker     {
6768*5e7646d2SAndroid Build Coastguard Worker      /*
6769*5e7646d2SAndroid Build Coastguard Worker       * Find this attribute in the linked list...
6770*5e7646d2SAndroid Build Coastguard Worker       */
6771*5e7646d2SAndroid Build Coastguard Worker 
6772*5e7646d2SAndroid Build Coastguard Worker       for (prev = NULL, current = ipp->attrs;
6773*5e7646d2SAndroid Build Coastguard Worker 	   current && current != *attr;
6774*5e7646d2SAndroid Build Coastguard Worker 	   prev = current, current = current->next);
6775*5e7646d2SAndroid Build Coastguard Worker 
6776*5e7646d2SAndroid Build Coastguard Worker       if (!current)
6777*5e7646d2SAndroid Build Coastguard Worker       {
6778*5e7646d2SAndroid Build Coastguard Worker        /*
6779*5e7646d2SAndroid Build Coastguard Worker 	* This is a serious error!
6780*5e7646d2SAndroid Build Coastguard Worker 	*/
6781*5e7646d2SAndroid Build Coastguard Worker 
6782*5e7646d2SAndroid Build Coastguard Worker 	*attr = temp;
6783*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL,
6784*5e7646d2SAndroid Build Coastguard Worker 	              _("IPP attribute is not a member of the message."), 1);
6785*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_puts("4ipp_set_value: Unable to find attribute in message.");
6786*5e7646d2SAndroid Build Coastguard Worker 	return (NULL);
6787*5e7646d2SAndroid Build Coastguard Worker       }
6788*5e7646d2SAndroid Build Coastguard Worker     }
6789*5e7646d2SAndroid Build Coastguard Worker 
6790*5e7646d2SAndroid Build Coastguard Worker     if (prev)
6791*5e7646d2SAndroid Build Coastguard Worker       prev->next = temp;
6792*5e7646d2SAndroid Build Coastguard Worker     else
6793*5e7646d2SAndroid Build Coastguard Worker       ipp->attrs = temp;
6794*5e7646d2SAndroid Build Coastguard Worker 
6795*5e7646d2SAndroid Build Coastguard Worker     ipp->current = temp;
6796*5e7646d2SAndroid Build Coastguard Worker     ipp->prev    = prev;
6797*5e7646d2SAndroid Build Coastguard Worker 
6798*5e7646d2SAndroid Build Coastguard Worker     if (ipp->last == *attr)
6799*5e7646d2SAndroid Build Coastguard Worker       ipp->last = temp;
6800*5e7646d2SAndroid Build Coastguard Worker 
6801*5e7646d2SAndroid Build Coastguard Worker     *attr = temp;
6802*5e7646d2SAndroid Build Coastguard Worker   }
6803*5e7646d2SAndroid Build Coastguard Worker 
6804*5e7646d2SAndroid Build Coastguard Worker  /*
6805*5e7646d2SAndroid Build Coastguard Worker   * Return the value element...
6806*5e7646d2SAndroid Build Coastguard Worker   */
6807*5e7646d2SAndroid Build Coastguard Worker 
6808*5e7646d2SAndroid Build Coastguard Worker   if (element >= temp->num_values)
6809*5e7646d2SAndroid Build Coastguard Worker     temp->num_values = element + 1;
6810*5e7646d2SAndroid Build Coastguard Worker 
6811*5e7646d2SAndroid Build Coastguard Worker   return (temp->values + element);
6812*5e7646d2SAndroid Build Coastguard Worker }
6813*5e7646d2SAndroid Build Coastguard Worker 
6814*5e7646d2SAndroid Build Coastguard Worker 
6815*5e7646d2SAndroid Build Coastguard Worker /*
6816*5e7646d2SAndroid Build Coastguard Worker  * 'ipp_write_file()' - Write IPP data to a file.
6817*5e7646d2SAndroid Build Coastguard Worker  */
6818*5e7646d2SAndroid Build Coastguard Worker 
6819*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Number of bytes written */
ipp_write_file(int * fd,ipp_uchar_t * buffer,size_t length)6820*5e7646d2SAndroid Build Coastguard Worker ipp_write_file(int         *fd,		/* I - File descriptor */
6821*5e7646d2SAndroid Build Coastguard Worker                ipp_uchar_t *buffer,	/* I - Data to write */
6822*5e7646d2SAndroid Build Coastguard Worker                size_t      length)	/* I - Number of bytes to write */
6823*5e7646d2SAndroid Build Coastguard Worker {
6824*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
6825*5e7646d2SAndroid Build Coastguard Worker   return ((ssize_t)write(*fd, buffer, (unsigned)length));
6826*5e7646d2SAndroid Build Coastguard Worker #else
6827*5e7646d2SAndroid Build Coastguard Worker   return (write(*fd, buffer, length));
6828*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
6829*5e7646d2SAndroid Build Coastguard Worker }
6830