2 * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
4 * Internet Printing Protocol functions for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * ippAddBoolean() - Add a boolean attribute to an IPP message.
20 * ippAddBooleans() - Add an array of boolean values.
21 * ippAddDate() - Add a date attribute to an IPP message.
22 * ippAddInteger() - Add a integer attribute to an IPP message.
23 * ippAddIntegers() - Add an array of integer values.
24 * ippAddOctetString() - Add an octetString value to an IPP message.
25 * ippAddString() - Add a language-encoded string to an IPP message.
26 * ippAddStrings() - Add language-encoded strings to an IPP message.
27 * ippAddRange() - Add a range of values to an IPP message.
28 * ippAddRanges() - Add ranges of values to an IPP message.
29 * ippAddResolution() - Add a resolution value to an IPP message.
30 * ippAddResolutions() - Add resolution values to an IPP message.
31 * ippAddSeparator() - Add a group separator to an IPP message.
32 * ippDateToTime() - Convert from RFC 1903 Date/Time format to
33 * UNIX time in seconds.
34 * ippDelete() - Delete an IPP message.
35 * ippDeleteAttribute() - Delete a single attribute in an IPP message.
36 * ippFindAttribute() - Find a named attribute in a request...
37 * ippFindNextAttribute() - Find the next named attribute in a request...
38 * ippLength() - Compute the length of an IPP message.
39 * ippNew() - Allocate a new IPP message.
40 * ippNewRequest() - Allocate a new IPP message.
41 * ippRead() - Read data for an IPP message from a HTTP
43 * ippReadFile() - Read data for an IPP message from a file.
44 * ippReadIO() - Read data for an IPP message.
45 * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
46 * ippWrite() - Write data for an IPP message to a HTTP
48 * ippWriteFile() - Write data for an IPP message to a file.
49 * ippWriteIO() - Write data for an IPP message.
50 * _ippAddAttr() - Add a new attribute to the request.
51 * _ippFreeAttr() - Free an attribute.
52 * ipp_length() - Compute the length of an IPP message or
54 * ipp_read_http() - Semi-blocking read on a HTTP connection...
55 * ipp_read_file() - Read IPP data from a file.
56 * ipp_write_file() - Write IPP data to a file.
60 * Include necessary headers...
63 #include "cups-private.h"
73 static unsigned char *ipp_buffer_get(void);
74 static void ipp_buffer_release(unsigned char *b
);
75 static size_t ipp_length(ipp_t
*ipp
, int collection
);
76 static ssize_t
ipp_read_http(http_t
*http
, ipp_uchar_t
*buffer
,
78 static ssize_t
ipp_read_file(int *fd
, ipp_uchar_t
*buffer
,
80 static ssize_t
ipp_write_file(int *fd
, ipp_uchar_t
*buffer
,
85 * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
88 ipp_attribute_t
* /* O - New attribute */
89 ippAddBoolean(ipp_t
*ipp
, /* I - IPP message */
90 ipp_tag_t group
, /* I - IPP group */
91 const char *name
, /* I - Name of attribute */
92 char value
) /* I - Value of attribute */
94 ipp_attribute_t
*attr
; /* New attribute */
97 DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)",
98 ipp
, group
, ippTagString(group
), name
, value
));
103 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
106 attr
->name
= _cupsStrAlloc(name
);
107 attr
->group_tag
= group
;
108 attr
->value_tag
= IPP_TAG_BOOLEAN
;
109 attr
->values
[0].boolean
= value
;
116 * 'ippAddBooleans()' - Add an array of boolean values.
119 ipp_attribute_t
* /* O - New attribute */
120 ippAddBooleans(ipp_t
*ipp
, /* I - IPP message */
121 ipp_tag_t group
, /* I - IPP group */
122 const char *name
, /* I - Name of attribute */
123 int num_values
, /* I - Number of values */
124 const char *values
) /* I - Values */
126 int i
; /* Looping var */
127 ipp_attribute_t
*attr
; /* New attribute */
128 ipp_value_t
*value
; /* Current value */
131 DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", "
132 "num_values=%d, values=%p)", ipp
, group
, ippTagString(group
),
133 name
, num_values
, values
));
135 if (!ipp
|| !name
|| num_values
< 1)
138 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
141 attr
->name
= _cupsStrAlloc(name
);
142 attr
->group_tag
= group
;
143 attr
->value_tag
= IPP_TAG_BOOLEAN
;
146 for (i
= 0, value
= attr
->values
;
149 value
->boolean
= values
[i
];
156 * 'ippAddCollection()' - Add a collection value.
158 * @since CUPS 1.1.19/Mac OS X 10.3@
161 ipp_attribute_t
* /* O - New attribute */
162 ippAddCollection(ipp_t
*ipp
, /* I - IPP message */
163 ipp_tag_t group
, /* I - IPP group */
164 const char *name
, /* I - Name of attribute */
165 ipp_t
*value
) /* I - Value */
167 ipp_attribute_t
*attr
; /* New attribute */
170 DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", "
171 "value=%p)", ipp
, group
, ippTagString(group
), name
, value
));
176 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
179 attr
->name
= _cupsStrAlloc(name
);
180 attr
->group_tag
= group
;
181 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
182 attr
->values
[0].collection
= value
;
191 * 'ippAddCollections()' - Add an array of collection values.
193 * @since CUPS 1.1.19/Mac OS X 10.3@
196 ipp_attribute_t
* /* O - New attribute */
198 ipp_t
*ipp
, /* I - IPP message */
199 ipp_tag_t group
, /* I - IPP group */
200 const char *name
, /* I - Name of attribute */
201 int num_values
, /* I - Number of values */
202 const ipp_t
**values
) /* I - Values */
204 int i
; /* Looping var */
205 ipp_attribute_t
*attr
; /* New attribute */
206 ipp_value_t
*value
; /* Current value */
209 DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
210 "num_values=%d, values=%p)", ipp
, group
, ippTagString(group
),
211 name
, num_values
, values
));
213 if (!ipp
|| !name
|| num_values
< 1)
216 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
219 attr
->name
= _cupsStrAlloc(name
);
220 attr
->group_tag
= group
;
221 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
225 for (i
= 0, value
= attr
->values
;
229 value
->collection
= (ipp_t
*)values
[i
];
230 value
->collection
->use
++;
239 * 'ippAddDate()' - Add a date attribute to an IPP message.
242 ipp_attribute_t
* /* O - New attribute */
243 ippAddDate(ipp_t
*ipp
, /* I - IPP message */
244 ipp_tag_t group
, /* I - IPP group */
245 const char *name
, /* I - Name of attribute */
246 const ipp_uchar_t
*value
) /* I - Value */
248 ipp_attribute_t
*attr
; /* New attribute */
251 DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
252 ipp
, group
, ippTagString(group
), name
, value
));
254 if (!ipp
|| !name
|| !value
)
257 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
260 attr
->name
= _cupsStrAlloc(name
);
261 attr
->group_tag
= group
;
262 attr
->value_tag
= IPP_TAG_DATE
;
263 memcpy(attr
->values
[0].date
, value
, 11);
270 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
273 ipp_attribute_t
* /* O - New attribute */
274 ippAddInteger(ipp_t
*ipp
, /* I - IPP message */
275 ipp_tag_t group
, /* I - IPP group */
276 ipp_tag_t type
, /* I - Type of attribute */
277 const char *name
, /* I - Name of attribute */
278 int value
) /* I - Value of attribute */
280 ipp_attribute_t
*attr
; /* New attribute */
283 DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
284 "name=\"%s\", value=%d)", ipp
, group
, ippTagString(group
),
285 type
, ippTagString(type
), name
, value
));
290 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
293 attr
->name
= _cupsStrAlloc(name
);
294 attr
->group_tag
= group
;
295 attr
->value_tag
= type
;
296 attr
->values
[0].integer
= value
;
303 * 'ippAddIntegers()' - Add an array of integer values.
306 ipp_attribute_t
* /* O - New attribute */
307 ippAddIntegers(ipp_t
*ipp
, /* I - IPP message */
308 ipp_tag_t group
, /* I - IPP group */
309 ipp_tag_t type
, /* I - Type of attribute */
310 const char *name
, /* I - Name of attribute */
311 int num_values
, /* I - Number of values */
312 const int *values
) /* I - Values */
314 int i
; /* Looping var */
315 ipp_attribute_t
*attr
; /* New attribute */
316 ipp_value_t
*value
; /* Current value */
319 DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
320 "name=\"%s\", num_values=%d, values=%p)", ipp
,
321 group
, ippTagString(group
), type
, ippTagString(type
), name
,
322 num_values
, values
));
324 if (!ipp
|| !name
|| num_values
< 1)
327 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
330 attr
->name
= _cupsStrAlloc(name
);
331 attr
->group_tag
= group
;
332 attr
->value_tag
= type
;
335 for (i
= 0, value
= attr
->values
;
338 value
->integer
= values
[i
];
345 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
347 * @since CUPS 1.2/Mac OS X 10.5@
350 ipp_attribute_t
* /* O - New attribute */
351 ippAddOctetString(ipp_t
*ipp
, /* I - IPP message */
352 ipp_tag_t group
, /* I - IPP group */
353 const char *name
, /* I - Name of attribute */
354 const void *data
, /* I - octetString data */
355 int datalen
) /* I - Length of data in bytes */
357 ipp_attribute_t
*attr
; /* New attribute */
360 if (ipp
== NULL
|| name
== NULL
)
363 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
367 * Initialize the attribute data...
370 attr
->name
= _cupsStrAlloc(name
);
371 attr
->group_tag
= group
;
372 attr
->value_tag
= IPP_TAG_STRING
;
373 attr
->values
[0].unknown
.length
= datalen
;
377 if ((attr
->values
[0].unknown
.data
= malloc(datalen
)) == NULL
)
379 ippDeleteAttribute(ipp
, attr
);
383 memcpy(attr
->values
[0].unknown
.data
, data
, datalen
);
387 * Return the new attribute...
395 * 'ippAddString()' - Add a language-encoded string to an IPP message.
398 ipp_attribute_t
* /* O - New attribute */
399 ippAddString(ipp_t
*ipp
, /* I - IPP message */
400 ipp_tag_t group
, /* I - IPP group */
401 ipp_tag_t type
, /* I - Type of attribute */
402 const char *name
, /* I - Name of attribute */
403 const char *charset
, /* I - Character set */
404 const char *value
) /* I - Value */
406 ipp_attribute_t
*attr
; /* New attribute */
407 char buffer
[1024], /* Language/charset value buffer */
408 *bufptr
; /* Pointer into buffer */
411 DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
412 "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp
,
413 group
, ippTagString(group
), type
, ippTagString(type
), name
,
419 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
423 * Force value to be English for the POSIX locale...
426 if (type
== IPP_TAG_LANGUAGE
&& !_cups_strcasecmp(value
, "C"))
430 * Convert language and charset values to lowercase and change _ to - as
434 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
436 strlcpy(buffer
, value
, sizeof(buffer
));
439 for (bufptr
= buffer
; *bufptr
; bufptr
++)
443 *bufptr
= tolower(*bufptr
& 255);
447 * Initialize the attribute data...
450 attr
->name
= _cupsStrAlloc(name
);
451 attr
->group_tag
= group
;
452 attr
->value_tag
= type
;
453 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
454 charset
? _cupsStrAlloc(charset
) : NULL
;
455 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
456 value
? _cupsStrAlloc(value
) : NULL
;
463 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
466 ipp_attribute_t
* /* O - New attribute */
468 ipp_t
*ipp
, /* I - IPP message */
469 ipp_tag_t group
, /* I - IPP group */
470 ipp_tag_t type
, /* I - Type of attribute */
471 const char *name
, /* I - Name of attribute */
472 int num_values
, /* I - Number of values */
473 const char *charset
, /* I - Character set */
474 const char * const *values
) /* I - Values */
476 int i
; /* Looping var */
477 ipp_attribute_t
*attr
; /* New attribute */
478 ipp_value_t
*value
; /* Current value */
479 char buffer
[1024], /* Language/charset value buffer */
480 *bufptr
; /* Pointer into buffer */
483 DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
484 "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp
,
485 group
, ippTagString(group
), type
, ippTagString(type
), name
,
486 num_values
, charset
, values
));
488 if (!ipp
|| !name
|| num_values
< 1)
491 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
495 * Initialize the attribute data...
498 attr
->name
= _cupsStrAlloc(name
);
499 attr
->group_tag
= group
;
500 attr
->value_tag
= type
;
502 for (i
= 0, value
= attr
->values
;
507 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
508 charset
? _cupsStrAlloc(charset
) : NULL
;
510 value
->string
.charset
= attr
->values
[0].string
.charset
;
514 if ((int)type
& IPP_TAG_COPY
)
515 value
->string
.text
= (char *)values
[i
];
516 else if (type
== IPP_TAG_LANGUAGE
&& !_cups_strcasecmp(values
[i
], "C"))
519 * Force language to be English for the POSIX locale...
522 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
525 else if (type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
)
528 * Convert language values to lowercase and change _ to - as needed...
531 strlcpy(buffer
, values
[i
], sizeof(buffer
));
533 for (bufptr
= buffer
; *bufptr
; bufptr
++)
537 *bufptr
= tolower(*bufptr
& 255);
539 value
->string
.text
= _cupsStrAlloc(buffer
);
542 value
->string
.text
= _cupsStrAlloc(values
[i
]);
552 * 'ippAddRange()' - Add a range of values to an IPP message.
555 ipp_attribute_t
* /* O - New attribute */
556 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
557 ipp_tag_t group
, /* I - IPP group */
558 const char *name
, /* I - Name of attribute */
559 int lower
, /* I - Lower value */
560 int upper
) /* I - Upper value */
562 ipp_attribute_t
*attr
; /* New attribute */
565 DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
566 "upper=%d)", ipp
, group
, ippTagString(group
), name
, lower
,
572 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
575 attr
->name
= _cupsStrAlloc(name
);
576 attr
->group_tag
= group
;
577 attr
->value_tag
= IPP_TAG_RANGE
;
578 attr
->values
[0].range
.lower
= lower
;
579 attr
->values
[0].range
.upper
= upper
;
586 * 'ippAddRanges()' - Add ranges of values to an IPP message.
589 ipp_attribute_t
* /* O - New attribute */
590 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
591 ipp_tag_t group
, /* I - IPP group */
592 const char *name
, /* I - Name of attribute */
593 int num_values
, /* I - Number of values */
594 const int *lower
, /* I - Lower values */
595 const int *upper
) /* I - Upper values */
597 int i
; /* Looping var */
598 ipp_attribute_t
*attr
; /* New attribute */
599 ipp_value_t
*value
; /* Current value */
602 DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
603 "num_values=%d, lower=%p, upper=%p)", ipp
, group
,
604 ippTagString(group
), name
, num_values
, lower
, upper
));
606 if (!ipp
|| !name
|| num_values
< 1)
609 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
612 attr
->name
= _cupsStrAlloc(name
);
613 attr
->group_tag
= group
;
614 attr
->value_tag
= IPP_TAG_RANGE
;
616 if (lower
!= NULL
&& upper
!= NULL
)
617 for (i
= 0, value
= attr
->values
;
621 value
->range
.lower
= lower
[i
];
622 value
->range
.upper
= upper
[i
];
630 * 'ippAddResolution()' - Add a resolution value to an IPP message.
633 ipp_attribute_t
* /* O - New attribute */
634 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
635 ipp_tag_t group
, /* I - IPP group */
636 const char *name
, /* I - Name of attribute */
637 ipp_res_t units
, /* I - Units for resolution */
638 int xres
, /* I - X resolution */
639 int yres
) /* I - Y resolution */
641 ipp_attribute_t
*attr
; /* New attribute */
644 DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
645 "units=%d, xres=%d, yres=%d)", ipp
, group
,
646 ippTagString(group
), name
, units
, xres
, yres
));
651 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
654 attr
->name
= _cupsStrAlloc(name
);
655 attr
->group_tag
= group
;
656 attr
->value_tag
= IPP_TAG_RESOLUTION
;
657 attr
->values
[0].resolution
.xres
= xres
;
658 attr
->values
[0].resolution
.yres
= yres
;
659 attr
->values
[0].resolution
.units
= units
;
666 * 'ippAddResolutions()' - Add resolution values to an IPP message.
669 ipp_attribute_t
* /* O - New attribute */
670 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
671 ipp_tag_t group
, /* I - IPP group */
672 const char *name
, /* I - Name of attribute */
673 int num_values
,/* I - Number of values */
674 ipp_res_t units
, /* I - Units for resolution */
675 const int *xres
, /* I - X resolutions */
676 const int *yres
) /* I - Y resolutions */
678 int i
; /* Looping var */
679 ipp_attribute_t
*attr
; /* New attribute */
680 ipp_value_t
*value
; /* Current value */
683 DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
684 "num_value=%d, units=%d, xres=%p, yres=%p)", ipp
, group
,
685 ippTagString(group
), name
, num_values
, units
, xres
, yres
));
687 if (!ipp
|| !name
|| num_values
< 1)
690 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
693 attr
->name
= _cupsStrAlloc(name
);
694 attr
->group_tag
= group
;
695 attr
->value_tag
= IPP_TAG_RESOLUTION
;
697 if (xres
!= NULL
&& yres
!= NULL
)
698 for (i
= 0, value
= attr
->values
;
702 value
->resolution
.xres
= xres
[i
];
703 value
->resolution
.yres
= yres
[i
];
704 value
->resolution
.units
= units
;
712 * 'ippAddSeparator()' - Add a group separator to an IPP message.
715 ipp_attribute_t
* /* O - New attribute */
716 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
718 ipp_attribute_t
*attr
; /* New attribute */
721 DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp
));
726 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
729 attr
->group_tag
= IPP_TAG_ZERO
;
730 attr
->value_tag
= IPP_TAG_ZERO
;
737 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
741 time_t /* O - UNIX time value */
742 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
744 struct tm unixdate
; /* UNIX date/time info */
745 time_t t
; /* Computed time */
751 memset(&unixdate
, 0, sizeof(unixdate
));
754 * RFC-1903 date/time format is:
756 * Byte(s) Description
757 * ------- -----------
758 * 0-1 Year (0 to 65535)
762 * 5 Minutes (0 to 59)
763 * 6 Seconds (0 to 60, 60 = "leap second")
764 * 7 Deciseconds (0 to 9)
766 * 9 UTC hours (0 to 11)
767 * 10 UTC minutes (0 to 59)
770 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
771 unixdate
.tm_mon
= date
[2] - 1;
772 unixdate
.tm_mday
= date
[3];
773 unixdate
.tm_hour
= date
[4];
774 unixdate
.tm_min
= date
[5];
775 unixdate
.tm_sec
= date
[6];
777 t
= mktime(&unixdate
);
780 t
+= date
[9] * 3600 + date
[10] * 60;
782 t
-= date
[9] * 3600 + date
[10] * 60;
789 * 'ippDelete()' - Delete an IPP message.
793 ippDelete(ipp_t
*ipp
) /* I - IPP message */
795 ipp_attribute_t
*attr
, /* Current attribute */
796 *next
; /* Next attribute */
799 DEBUG_printf(("ippDelete(ipp=%p)", ipp
));
808 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
819 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
821 * @since CUPS 1.1.19/Mac OS X 10.3@
826 ipp_t
*ipp
, /* I - IPP message */
827 ipp_attribute_t
*attr
) /* I - Attribute to delete */
829 ipp_attribute_t
*current
, /* Current attribute */
830 *prev
; /* Previous attribute */
833 DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp
, attr
,
834 attr
? attr
->name
: "(null)"));
837 * Find the attribute in the list...
840 for (current
= ipp
->attrs
, prev
= NULL
;
841 current
!= NULL
&& current
!= attr
;
842 prev
= current
, current
= current
->next
);
847 * Found it, remove the attribute from the list...
851 prev
->next
= current
->next
;
853 ipp
->attrs
= current
->next
;
855 if (current
== ipp
->last
)
859 * Free memory used by the attribute...
862 _ippFreeAttr(current
);
868 * 'ippFindAttribute()' - Find a named attribute in a request...
871 ipp_attribute_t
* /* O - Matching attribute */
872 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
873 const char *name
, /* I - Name of attribute */
874 ipp_tag_t type
) /* I - Type of attribute */
876 DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp
,
877 name
, type
, ippTagString(type
)));
883 * Reset the current pointer...
889 * Search for the attribute...
892 return (ippFindNextAttribute(ipp
, name
, type
));
897 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
900 ipp_attribute_t
* /* O - Matching attribute */
901 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
902 const char *name
, /* I - Name of attribute */
903 ipp_tag_t type
) /* I - Type of attribute */
905 ipp_attribute_t
*attr
; /* Current atttribute */
906 ipp_tag_t value_tag
; /* Value tag */
909 DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
910 ipp
, name
, type
, ippTagString(type
)));
917 ipp
->prev
= ipp
->current
;
918 attr
= ipp
->current
->next
;
926 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
928 DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr
,
931 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
933 if (attr
->name
!= NULL
&& _cups_strcasecmp(attr
->name
, name
) == 0 &&
934 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
935 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
936 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
952 * 'ippLength()' - Compute the length of an IPP message.
955 size_t /* O - Size of IPP message */
956 ippLength(ipp_t
*ipp
) /* I - IPP message */
958 return (ipp_length(ipp
, 0));
963 * 'ippNew()' - Allocate a new IPP message.
966 ipp_t
* /* O - New IPP message */
969 ipp_t
*temp
; /* New IPP message */
972 DEBUG_puts("ippNew()");
974 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
977 * Default to IPP 1.1...
980 temp
->request
.any
.version
[0] = 1;
981 temp
->request
.any
.version
[1] = 1;
985 DEBUG_printf(("1ippNew: Returning %p", temp
));
992 * 'ippNewRequest()' - Allocate a new IPP request message.
994 * The new request message is initialized with the attributes-charset and
995 * attributes-natural-language attributes added. The
996 * attributes-natural-language value is derived from the current locale.
998 * @since CUPS 1.2/Mac OS X 10.5@
1001 ipp_t
* /* O - IPP request message */
1002 ippNewRequest(ipp_op_t op
) /* I - Operation code */
1004 ipp_t
*request
; /* IPP request message */
1005 cups_lang_t
*language
; /* Current language localization */
1008 DEBUG_printf(("ippNewRequest(op=%02x(%s))", op
, ippOpString(op
)));
1011 * Create a new IPP message...
1014 if ((request
= ippNew()) == NULL
)
1018 * Set the operation and request ID...
1021 request
->request
.op
.operation_id
= op
;
1022 request
->request
.op
.request_id
= 1;
1025 * Use UTF-8 as the character set...
1028 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1029 "attributes-charset", NULL
, "utf-8");
1032 * Get the language from the current locale...
1035 language
= cupsLangDefault();
1037 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1038 "attributes-natural-language", NULL
, language
->language
);
1041 * Return the new request...
1049 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
1052 ipp_state_t
/* O - Current state */
1053 ippRead(http_t
*http
, /* I - HTTP connection */
1054 ipp_t
*ipp
) /* I - IPP data */
1056 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
,
1057 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
1062 DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http
->state
,
1065 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
, http
->blocking
, NULL
,
1071 * 'ippReadFile()' - Read data for an IPP message from a file.
1073 * @since CUPS 1.1.19/Mac OS X 10.3@
1076 ipp_state_t
/* O - Current state */
1077 ippReadFile(int fd
, /* I - HTTP data */
1078 ipp_t
*ipp
) /* I - IPP data */
1080 DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd
, ipp
));
1082 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1087 * 'ippReadIO()' - Read data for an IPP message.
1089 * @since CUPS 1.2/Mac OS X 10.5@
1092 ipp_state_t
/* O - Current state */
1093 ippReadIO(void *src
, /* I - Data source */
1094 ipp_iocb_t cb
, /* I - Read callback function */
1095 int blocking
, /* I - Use blocking IO? */
1096 ipp_t
*parent
, /* I - Parent request, if any */
1097 ipp_t
*ipp
) /* I - IPP data */
1099 int n
; /* Length of data */
1100 unsigned char *buffer
, /* Data buffer */
1101 string
[IPP_MAX_NAME
],
1102 /* Small string buffer */
1103 *bufptr
; /* Pointer into buffer */
1104 ipp_attribute_t
*attr
; /* Current attribute */
1105 ipp_tag_t tag
; /* Current tag */
1106 ipp_tag_t value_tag
; /* Current value tag */
1107 ipp_value_t
*value
; /* Current value */
1110 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1111 src
, cb
, blocking
, parent
, ipp
));
1112 DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp
->state
));
1117 if ((buffer
= ipp_buffer_get()) == NULL
)
1119 DEBUG_puts("1ippReadIO: Unable to get read buffer.");
1126 ipp
->state
++; /* Avoid common problem... */
1132 * Get the request header...
1135 if ((*cb
)(src
, buffer
, 8) < 8)
1137 DEBUG_puts("1ippReadIO: Unable to read header.");
1138 ipp_buffer_release(buffer
);
1143 * Then copy the request header over...
1146 ipp
->request
.any
.version
[0] = buffer
[0];
1147 ipp
->request
.any
.version
[1] = buffer
[1];
1148 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1149 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1150 buffer
[6]) << 8) | buffer
[7];
1152 DEBUG_printf(("2ippReadIO: version=%d.%d", buffer
[0], buffer
[1]));
1153 DEBUG_printf(("2ippReadIO: op_status=%04x",
1154 ipp
->request
.any
.op_status
));
1155 DEBUG_printf(("2ippReadIO: request_id=%d",
1156 ipp
->request
.any
.request_id
));
1159 ipp
->state
= IPP_ATTRIBUTE
;
1160 ipp
->current
= NULL
;
1161 ipp
->curtag
= IPP_TAG_ZERO
;
1162 ipp
->prev
= ipp
->last
;
1165 * If blocking is disabled, stop here...
1171 case IPP_ATTRIBUTE
:
1174 if ((*cb
)(src
, buffer
, 1) < 1)
1176 DEBUG_puts("1ippReadIO: Callback returned EOF/error");
1177 ipp_buffer_release(buffer
);
1181 DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
1182 ipp
->current
, ipp
->prev
));
1185 * Read this attribute...
1188 tag
= (ipp_tag_t
)buffer
[0];
1190 if (tag
== IPP_TAG_END
)
1193 * No more attributes left...
1196 DEBUG_puts("2ippReadIO: IPP_TAG_END.");
1198 ipp
->state
= IPP_DATA
;
1201 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1204 * Group tag... Set the current group and continue...
1207 if (ipp
->curtag
== tag
)
1208 ipp
->prev
= ippAddSeparator(ipp
);
1209 else if (ipp
->current
)
1210 ipp
->prev
= ipp
->current
;
1213 ipp
->current
= NULL
;
1214 DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag
,
1215 ippTagString(tag
), ipp
->prev
));
1219 DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag
,
1220 ippTagString(tag
)));
1226 if ((*cb
)(src
, buffer
, 2) < 2)
1228 DEBUG_puts("1ippReadIO: unable to read name length.");
1229 ipp_buffer_release(buffer
);
1233 n
= (buffer
[0] << 8) | buffer
[1];
1235 if (n
>= IPP_BUF_SIZE
)
1237 _cupsSetError(IPP_ERROR
, _("IPP name larger than 32767 bytes."), 1);
1238 DEBUG_printf(("1ippReadIO: bad name length %d.", n
));
1239 ipp_buffer_release(buffer
);
1243 DEBUG_printf(("2ippReadIO: name length=%d", n
));
1245 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1246 tag
!= IPP_TAG_END_COLLECTION
)
1249 * More values for current attribute...
1252 if (ipp
->current
== NULL
)
1254 _cupsSetError(IPP_ERROR
, _("IPP attribute has no name."), 1);
1255 DEBUG_puts("1ippReadIO: Attribute without name and no current.");
1256 ipp_buffer_release(buffer
);
1260 attr
= ipp
->current
;
1261 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1264 * Make sure we aren't adding a new value of a different
1268 if (value_tag
== IPP_TAG_ZERO
)
1271 * Setting the value of a collection member...
1274 attr
->value_tag
= tag
;
1276 else if (value_tag
== IPP_TAG_TEXTLANG
||
1277 value_tag
== IPP_TAG_NAMELANG
||
1278 (value_tag
>= IPP_TAG_TEXT
&&
1279 value_tag
<= IPP_TAG_MIMETYPE
))
1282 * String values can sometimes come across in different
1283 * forms; accept sets of differing values...
1286 if (tag
!= IPP_TAG_TEXTLANG
&& tag
!= IPP_TAG_NAMELANG
&&
1287 (tag
< IPP_TAG_TEXT
|| tag
> IPP_TAG_MIMETYPE
) &&
1288 tag
!= IPP_TAG_NOVALUE
)
1290 _cupsSetError(IPP_ERROR
,
1291 _("IPP 1setOf attribute with incompatible value "
1293 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1294 value_tag
, ippTagString(value_tag
), tag
,
1295 ippTagString(tag
)));
1296 ipp_buffer_release(buffer
);
1300 else if (value_tag
== IPP_TAG_INTEGER
||
1301 value_tag
== IPP_TAG_RANGE
)
1304 * Integer and rangeOfInteger values can sometimes be mixed; accept
1305 * sets of differing values...
1308 if (tag
!= IPP_TAG_INTEGER
&& tag
!= IPP_TAG_RANGE
)
1310 _cupsSetError(IPP_ERROR
,
1311 _("IPP 1setOf attribute with incompatible value "
1313 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1314 value_tag
, ippTagString(value_tag
), tag
,
1315 ippTagString(tag
)));
1316 ipp_buffer_release(buffer
);
1320 if (value_tag
== IPP_TAG_INTEGER
&& tag
== IPP_TAG_RANGE
)
1323 * Convert integer values to rangeOfInteger values...
1326 int i
; /* Looping var */
1328 DEBUG_printf(("1ippReadIO: Converting %s attribute to "
1329 "rangeOfInteger.", attr
->name
));
1331 attr
->value_tag
= IPP_TAG_RANGE
;
1333 for (i
= attr
->num_values
, value
= attr
->values
;
1338 value
->range
.lower
= value
->range
.upper
= n
;
1342 else if (value_tag
!= tag
)
1344 _cupsSetError(IPP_ERROR
,
1345 _("IPP 1setOf attribute with incompatible value "
1347 DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
1348 value_tag
, ippTagString(value_tag
), tag
,
1349 ippTagString(tag
)));
1350 ipp_buffer_release(buffer
);
1355 * Finally, reallocate the attribute array as needed...
1358 if (attr
->num_values
== 1 ||
1359 (attr
->num_values
> 0 &&
1360 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1362 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1364 DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
1365 attr
->num_values
+ IPP_MAX_VALUES
));
1368 * Reallocate memory...
1371 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1372 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1373 sizeof(ipp_value_t
))) == NULL
)
1375 _cupsSetHTTPError(HTTP_ERROR
);
1376 DEBUG_puts("1ippReadIO: Unable to resize attribute");
1377 ipp_buffer_release(buffer
);
1384 * Reset pointers in the list...
1388 ipp
->prev
->next
= temp
;
1392 attr
= ipp
->current
= ipp
->last
= temp
;
1396 else if (tag
== IPP_TAG_MEMBERNAME
)
1399 * Name must be length 0!
1404 _cupsSetError(IPP_ERROR
, _("IPP member name is not empty."), 1);
1405 DEBUG_puts("1ippReadIO: member name not empty.");
1406 ipp_buffer_release(buffer
);
1411 ipp
->prev
= ipp
->current
;
1413 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1415 DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
1416 "ipp->prev=%p", ipp
->current
, ipp
->prev
));
1418 attr
->group_tag
= ipp
->curtag
;
1419 attr
->value_tag
= IPP_TAG_ZERO
;
1420 attr
->num_values
= 0;
1422 else if (tag
!= IPP_TAG_END_COLLECTION
)
1425 * New attribute; read the name and add it...
1428 if ((*cb
)(src
, buffer
, n
) < n
)
1430 DEBUG_puts("1ippReadIO: unable to read name.");
1431 ipp_buffer_release(buffer
);
1438 ipp
->prev
= ipp
->current
;
1440 if ((attr
= ipp
->current
= _ippAddAttr(ipp
, 1)) == NULL
)
1442 _cupsSetHTTPError(HTTP_ERROR
);
1443 DEBUG_puts("1ippReadIO: unable to allocate attribute.");
1444 ipp_buffer_release(buffer
);
1448 DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
1449 "ipp->prev=%p", buffer
, ipp
->current
, ipp
->prev
));
1451 attr
->group_tag
= ipp
->curtag
;
1452 attr
->value_tag
= tag
;
1453 attr
->name
= _cupsStrAlloc((char *)buffer
);
1454 attr
->num_values
= 0;
1459 if (tag
!= IPP_TAG_END_COLLECTION
)
1460 value
= attr
->values
+ attr
->num_values
;
1464 if ((*cb
)(src
, buffer
, 2) < 2)
1466 DEBUG_puts("1ippReadIO: unable to read value length.");
1467 ipp_buffer_release(buffer
);
1471 n
= (buffer
[0] << 8) | buffer
[1];
1472 DEBUG_printf(("2ippReadIO: value length=%d", n
));
1474 if (n
>= IPP_BUF_SIZE
)
1476 _cupsSetError(IPP_ERROR
,
1477 _("IPP value larger than 32767 bytes."), 1);
1478 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1479 ipp_buffer_release(buffer
);
1485 case IPP_TAG_INTEGER
:
1489 if (tag
== IPP_TAG_INTEGER
)
1490 _cupsSetError(IPP_ERROR
,
1491 _("IPP integer value not 4 bytes."), 1);
1493 _cupsSetError(IPP_ERROR
,
1494 _("IPP enum value not 4 bytes."), 1);
1495 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1496 ipp_buffer_release(buffer
);
1500 if ((*cb
)(src
, buffer
, 4) < 4)
1502 DEBUG_puts("1ippReadIO: Unable to read integer value.");
1503 ipp_buffer_release(buffer
);
1507 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1510 if (attr
->value_tag
== IPP_TAG_RANGE
)
1511 value
->range
.lower
= value
->range
.upper
= n
;
1516 case IPP_TAG_BOOLEAN
:
1519 _cupsSetError(IPP_ERROR
, _("IPP boolean value not 1 byte."),
1521 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1522 ipp_buffer_release(buffer
);
1526 if ((*cb
)(src
, buffer
, 1) < 1)
1528 DEBUG_puts("1ippReadIO: Unable to read boolean value.");
1529 ipp_buffer_release(buffer
);
1533 value
->boolean
= buffer
[0];
1536 case IPP_TAG_NOVALUE
:
1537 case IPP_TAG_NOTSETTABLE
:
1538 case IPP_TAG_DELETEATTR
:
1539 case IPP_TAG_ADMINDEFINE
:
1541 * These value types are not supposed to have values, however
1542 * some vendors (Brother) do not implement IPP correctly and so
1543 * we need to map non-empty values to text...
1546 if (attr
->value_tag
== tag
)
1551 attr
->value_tag
= IPP_TAG_TEXT
;
1556 case IPP_TAG_KEYWORD
:
1558 case IPP_TAG_URISCHEME
:
1559 case IPP_TAG_CHARSET
:
1560 case IPP_TAG_LANGUAGE
:
1561 case IPP_TAG_MIMETYPE
:
1562 if ((*cb
)(src
, buffer
, n
) < n
)
1564 DEBUG_puts("1ippReadIO: unable to read string value.");
1565 ipp_buffer_release(buffer
);
1570 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1571 DEBUG_printf(("2ippReadIO: value=\"%s\"", value
->string
.text
));
1577 _cupsSetError(IPP_ERROR
, _("IPP date value not 11 bytes."),
1579 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1580 ipp_buffer_release(buffer
);
1584 if ((*cb
)(src
, value
->date
, 11) < 11)
1586 DEBUG_puts("1ippReadIO: Unable to read date value.");
1587 ipp_buffer_release(buffer
);
1592 case IPP_TAG_RESOLUTION
:
1595 _cupsSetError(IPP_ERROR
,
1596 _("IPP resolution value not 9 bytes."), 1);
1597 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1598 ipp_buffer_release(buffer
);
1602 if ((*cb
)(src
, buffer
, 9) < 9)
1604 DEBUG_puts("1ippReadIO: Unable to read resolution value.");
1605 ipp_buffer_release(buffer
);
1609 value
->resolution
.xres
=
1610 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1612 value
->resolution
.yres
=
1613 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1615 value
->resolution
.units
=
1616 (ipp_res_t
)buffer
[8];
1619 case IPP_TAG_RANGE
:
1622 _cupsSetError(IPP_ERROR
,
1623 _("IPP rangeOfInteger value not 8 bytes."), 1);
1624 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1625 ipp_buffer_release(buffer
);
1629 if ((*cb
)(src
, buffer
, 8) < 8)
1631 DEBUG_puts("1ippReadIO: Unable to read range value.");
1632 ipp_buffer_release(buffer
);
1636 value
->range
.lower
=
1637 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1639 value
->range
.upper
=
1640 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1644 case IPP_TAG_TEXTLANG
:
1645 case IPP_TAG_NAMELANG
:
1648 if (tag
== IPP_TAG_TEXTLANG
)
1649 _cupsSetError(IPP_ERROR
,
1650 _("IPP textWithLanguage value less than "
1651 "minimum 4 bytes."), 1);
1653 _cupsSetError(IPP_ERROR
,
1654 _("IPP nameWithLanguage value less than "
1655 "minimum 4 bytes."), 1);
1656 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1657 ipp_buffer_release(buffer
);
1661 if ((*cb
)(src
, buffer
, n
) < n
)
1663 DEBUG_puts("1ippReadIO: Unable to read string w/language "
1665 ipp_buffer_release(buffer
);
1672 * text-with-language and name-with-language are composite
1680 * The "charset" field name is an unfortunate typo from
1684 n
= (bufptr
[0] << 8) | bufptr
[1];
1686 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
) ||
1687 n
>= sizeof(string
))
1689 _cupsSetError(IPP_ERROR
,
1690 _("IPP language length overflows value."), 1);
1691 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1692 ipp_buffer_release(buffer
);
1696 memcpy(string
, bufptr
+ 2, n
);
1699 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1702 n
= (bufptr
[0] << 8) | bufptr
[1];
1704 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
))
1706 _cupsSetError(IPP_ERROR
,
1707 _("IPP string length overflows value."), 1);
1708 DEBUG_printf(("1ippReadIO: bad value length %d.", n
));
1709 ipp_buffer_release(buffer
);
1713 bufptr
[2 + n
] = '\0';
1714 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1717 case IPP_TAG_BEGIN_COLLECTION
:
1719 * Oh, boy, here comes a collection value, so read it...
1722 value
->collection
= ippNew();
1726 _cupsSetError(IPP_ERROR
,
1727 _("IPP begCollection value not 0 bytes."), 1);
1728 DEBUG_puts("1ippReadIO: begCollection tag with value length "
1730 ipp_buffer_release(buffer
);
1734 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1736 DEBUG_puts("1ippReadIO: Unable to read collection value.");
1737 ipp_buffer_release(buffer
);
1742 case IPP_TAG_END_COLLECTION
:
1743 ipp_buffer_release(buffer
);
1747 _cupsSetError(IPP_ERROR
,
1748 _("IPP endCollection value not 0 bytes."), 1);
1749 DEBUG_puts("1ippReadIO: endCollection tag with value length "
1754 DEBUG_puts("1ippReadIO: endCollection tag...");
1755 return (ipp
->state
= IPP_DATA
);
1757 case IPP_TAG_MEMBERNAME
:
1759 * The value the name of the member in the collection, which
1760 * we need to carry over...
1763 if ((*cb
)(src
, buffer
, n
) < n
)
1765 DEBUG_puts("1ippReadIO: Unable to read member name value.");
1766 ipp_buffer_release(buffer
);
1771 attr
->name
= _cupsStrAlloc((char *)buffer
);
1774 * Since collection members are encoded differently than
1775 * regular attributes, make sure we don't start with an
1779 attr
->num_values
--;
1781 DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr
->name
));
1784 default : /* Other unsupported values */
1785 value
->unknown
.length
= n
;
1788 if ((value
->unknown
.data
= malloc(n
)) == NULL
)
1790 _cupsSetHTTPError(HTTP_ERROR
);
1791 DEBUG_puts("1ippReadIO: Unable to allocate value");
1792 ipp_buffer_release(buffer
);
1796 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1798 DEBUG_puts("1ippReadIO: Unable to read unsupported value.");
1799 ipp_buffer_release(buffer
);
1804 value
->unknown
.data
= NULL
;
1808 attr
->num_values
++;
1811 * If blocking is disabled, stop here...
1823 break; /* anti-compiler-warning-code */
1826 DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp
->state
));
1827 ipp_buffer_release(buffer
);
1829 return (ipp
->state
);
1834 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1837 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1838 ippTimeToDate(time_t t
) /* I - UNIX time value */
1840 struct tm
*unixdate
; /* UNIX unixdate/time info */
1841 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1842 /* RFC-1903 date/time data */
1846 * RFC-1903 date/time format is:
1848 * Byte(s) Description
1849 * ------- -----------
1850 * 0-1 Year (0 to 65535)
1854 * 5 Minutes (0 to 59)
1855 * 6 Seconds (0 to 60, 60 = "leap second")
1856 * 7 Deciseconds (0 to 9)
1858 * 9 UTC hours (0 to 11)
1859 * 10 UTC minutes (0 to 59)
1862 unixdate
= gmtime(&t
);
1863 unixdate
->tm_year
+= 1900;
1865 date
[0] = unixdate
->tm_year
>> 8;
1866 date
[1] = unixdate
->tm_year
;
1867 date
[2] = unixdate
->tm_mon
+ 1;
1868 date
[3] = unixdate
->tm_mday
;
1869 date
[4] = unixdate
->tm_hour
;
1870 date
[5] = unixdate
->tm_min
;
1871 date
[6] = unixdate
->tm_sec
;
1882 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1885 ipp_state_t
/* O - Current state */
1886 ippWrite(http_t
*http
, /* I - HTTP connection */
1887 ipp_t
*ipp
) /* I - IPP data */
1889 DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http
, ipp
));
1894 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
, http
->blocking
, NULL
, ipp
));
1899 * 'ippWriteFile()' - Write data for an IPP message to a file.
1901 * @since CUPS 1.1.19/Mac OS X 10.3@
1904 ipp_state_t
/* O - Current state */
1905 ippWriteFile(int fd
, /* I - HTTP data */
1906 ipp_t
*ipp
) /* I - IPP data */
1908 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd
, ipp
));
1910 ipp
->state
= IPP_IDLE
;
1912 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1917 * 'ippWriteIO()' - Write data for an IPP message.
1919 * @since CUPS 1.2/Mac OS X 10.5@
1922 ipp_state_t
/* O - Current state */
1923 ippWriteIO(void *dst
, /* I - Destination */
1924 ipp_iocb_t cb
, /* I - Write callback function */
1925 int blocking
, /* I - Use blocking IO? */
1926 ipp_t
*parent
, /* I - Parent IPP message */
1927 ipp_t
*ipp
) /* I - IPP data */
1929 int i
; /* Looping var */
1930 int n
; /* Length of data */
1931 unsigned char *buffer
, /* Data buffer */
1932 *bufptr
; /* Pointer into buffer */
1933 ipp_attribute_t
*attr
; /* Current attribute */
1934 ipp_value_t
*value
; /* Current value */
1937 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1938 dst
, cb
, blocking
, parent
, ipp
));
1943 if ((buffer
= ipp_buffer_get()) == NULL
)
1945 DEBUG_puts("1ippWriteIO: Unable to get write buffer");
1952 ipp
->state
++; /* Avoid common problem... */
1958 * Send the request header:
1961 * Operation/Status Code = 2 bytes
1962 * Request ID = 4 bytes
1968 *bufptr
++ = ipp
->request
.any
.version
[0];
1969 *bufptr
++ = ipp
->request
.any
.version
[1];
1970 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1971 *bufptr
++ = ipp
->request
.any
.op_status
;
1972 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1973 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1974 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1975 *bufptr
++ = ipp
->request
.any
.request_id
;
1977 DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer
[0], buffer
[1]));
1978 DEBUG_printf(("2ippWriteIO: op_status=%04x",
1979 ipp
->request
.any
.op_status
));
1980 DEBUG_printf(("2ippWriteIO: request_id=%d",
1981 ipp
->request
.any
.request_id
));
1983 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1985 DEBUG_puts("1ippWriteIO: Could not write IPP header...");
1986 ipp_buffer_release(buffer
);
1992 * Reset the state engine to point to the first attribute
1993 * in the request/response, with no current group.
1996 ipp
->state
= IPP_ATTRIBUTE
;
1997 ipp
->current
= ipp
->attrs
;
1998 ipp
->curtag
= IPP_TAG_ZERO
;
2000 DEBUG_printf(("1ippWriteIO: ipp->current=%p", ipp
->current
));
2003 * If blocking is disabled, stop here...
2009 case IPP_ATTRIBUTE
:
2010 while (ipp
->current
!= NULL
)
2013 * Write this attribute...
2017 attr
= ipp
->current
;
2019 ipp
->current
= ipp
->current
->next
;
2023 if (ipp
->curtag
!= attr
->group_tag
)
2026 * Send a group tag byte...
2029 ipp
->curtag
= attr
->group_tag
;
2031 if (attr
->group_tag
== IPP_TAG_ZERO
)
2034 DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
2035 attr
->group_tag
, ippTagString(attr
->group_tag
)));
2036 *bufptr
++ = attr
->group_tag
;
2038 else if (attr
->group_tag
== IPP_TAG_ZERO
)
2042 DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr
->name
,
2043 attr
->num_values
> 1 ? "1setOf " : "",
2044 ippTagString(attr
->value_tag
)));
2047 * Write the attribute tag and name. The current implementation
2048 * does not support the extension value tags above 0x7f, so all
2049 * value tags are 1 byte.
2051 * The attribute name length does not include the trailing nul
2052 * character in the source string.
2054 * Collection values (parent != NULL) are written differently...
2060 * Get the length of the attribute name, and make sure it won't
2061 * overflow the buffer...
2064 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 4))
2066 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
2067 ipp_buffer_release(buffer
);
2072 * Write the value tag, name length, and name string...
2075 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2076 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2077 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2080 *bufptr
++ = attr
->value_tag
;
2083 memcpy(bufptr
, attr
->name
, n
);
2089 * Get the length of the attribute name, and make sure it won't
2090 * overflow the buffer...
2093 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 7))
2095 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
2096 ipp_buffer_release(buffer
);
2101 * Write the member name tag, name length, name string, value tag,
2102 * and empty name for the collection member attribute...
2105 DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
2106 IPP_TAG_MEMBERNAME
));
2107 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2109 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2110 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2111 DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
2113 *bufptr
++ = IPP_TAG_MEMBERNAME
;
2118 memcpy(bufptr
, attr
->name
, n
);
2121 *bufptr
++ = attr
->value_tag
;
2127 * Now write the attribute value(s)...
2130 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2132 case IPP_TAG_INTEGER
:
2134 for (i
= 0, value
= attr
->values
;
2135 i
< attr
->num_values
;
2138 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 9)
2140 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2142 DEBUG_puts("1ippWriteIO: Could not write IPP "
2144 ipp_buffer_release(buffer
);
2154 * Arrays and sets are done by sending additional
2155 * values with a zero-length name...
2158 *bufptr
++ = attr
->value_tag
;
2164 * Integers and enumerations are both 4-byte signed
2165 * (twos-complement) values.
2167 * Put the 2-byte length and 4-byte value into the buffer...
2172 *bufptr
++ = value
->integer
>> 24;
2173 *bufptr
++ = value
->integer
>> 16;
2174 *bufptr
++ = value
->integer
>> 8;
2175 *bufptr
++ = value
->integer
;
2179 case IPP_TAG_BOOLEAN
:
2180 for (i
= 0, value
= attr
->values
;
2181 i
< attr
->num_values
;
2184 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 6)
2186 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2188 DEBUG_puts("1ippWriteIO: Could not write IPP "
2190 ipp_buffer_release(buffer
);
2200 * Arrays and sets are done by sending additional
2201 * values with a zero-length name...
2204 *bufptr
++ = attr
->value_tag
;
2210 * Boolean values are 1-byte; 0 = false, 1 = true.
2212 * Put the 2-byte length and 1-byte value into the buffer...
2217 *bufptr
++ = value
->boolean
;
2223 case IPP_TAG_KEYWORD
:
2225 case IPP_TAG_URISCHEME
:
2226 case IPP_TAG_CHARSET
:
2227 case IPP_TAG_LANGUAGE
:
2228 case IPP_TAG_MIMETYPE
:
2229 for (i
= 0, value
= attr
->values
;
2230 i
< attr
->num_values
;
2236 * Arrays and sets are done by sending additional
2237 * values with a zero-length name...
2240 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2242 ippTagString(attr
->value_tag
)));
2243 DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
2245 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2247 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2249 DEBUG_puts("1ippWriteIO: Could not write IPP "
2251 ipp_buffer_release(buffer
);
2258 *bufptr
++ = attr
->value_tag
;
2263 if (value
->string
.text
!= NULL
)
2264 n
= (int)strlen(value
->string
.text
);
2268 if (n
> (IPP_BUF_SIZE
- 2))
2270 DEBUG_printf(("1ippWriteIO: String too long (%d)", n
));
2271 ipp_buffer_release(buffer
);
2275 DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n
,
2276 value
->string
.text
));
2278 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2280 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2282 DEBUG_puts("1ippWriteIO: Could not write IPP "
2284 ipp_buffer_release(buffer
);
2292 * All simple strings consist of the 2-byte length and
2293 * character data without the trailing nul normally found
2294 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2295 * bytes since the 2-byte length is a signed (twos-complement)
2298 * Put the 2-byte length and string characters in the buffer.
2306 memcpy(bufptr
, value
->string
.text
, n
);
2313 for (i
= 0, value
= attr
->values
;
2314 i
< attr
->num_values
;
2317 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 16)
2319 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2321 DEBUG_puts("1ippWriteIO: Could not write IPP "
2323 ipp_buffer_release(buffer
);
2333 * Arrays and sets are done by sending additional
2334 * values with a zero-length name...
2337 *bufptr
++ = attr
->value_tag
;
2343 * Date values consist of a 2-byte length and an
2344 * 11-byte date/time structure defined by RFC 1903.
2346 * Put the 2-byte length and 11-byte date/time
2347 * structure in the buffer.
2352 memcpy(bufptr
, value
->date
, 11);
2357 case IPP_TAG_RESOLUTION
:
2358 for (i
= 0, value
= attr
->values
;
2359 i
< attr
->num_values
;
2362 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 14)
2364 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2366 DEBUG_puts("1ippWriteIO: Could not write IPP "
2368 ipp_buffer_release(buffer
);
2378 * Arrays and sets are done by sending additional
2379 * values with a zero-length name...
2382 *bufptr
++ = attr
->value_tag
;
2388 * Resolution values consist of a 2-byte length,
2389 * 4-byte horizontal resolution value, 4-byte vertical
2390 * resolution value, and a 1-byte units value.
2392 * Put the 2-byte length and resolution value data
2398 *bufptr
++ = value
->resolution
.xres
>> 24;
2399 *bufptr
++ = value
->resolution
.xres
>> 16;
2400 *bufptr
++ = value
->resolution
.xres
>> 8;
2401 *bufptr
++ = value
->resolution
.xres
;
2402 *bufptr
++ = value
->resolution
.yres
>> 24;
2403 *bufptr
++ = value
->resolution
.yres
>> 16;
2404 *bufptr
++ = value
->resolution
.yres
>> 8;
2405 *bufptr
++ = value
->resolution
.yres
;
2406 *bufptr
++ = value
->resolution
.units
;
2410 case IPP_TAG_RANGE
:
2411 for (i
= 0, value
= attr
->values
;
2412 i
< attr
->num_values
;
2415 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 13)
2417 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2419 DEBUG_puts("1ippWriteIO: Could not write IPP "
2421 ipp_buffer_release(buffer
);
2431 * Arrays and sets are done by sending additional
2432 * values with a zero-length name...
2435 *bufptr
++ = attr
->value_tag
;
2441 * Range values consist of a 2-byte length,
2442 * 4-byte lower value, and 4-byte upper value.
2444 * Put the 2-byte length and range value data
2450 *bufptr
++ = value
->range
.lower
>> 24;
2451 *bufptr
++ = value
->range
.lower
>> 16;
2452 *bufptr
++ = value
->range
.lower
>> 8;
2453 *bufptr
++ = value
->range
.lower
;
2454 *bufptr
++ = value
->range
.upper
>> 24;
2455 *bufptr
++ = value
->range
.upper
>> 16;
2456 *bufptr
++ = value
->range
.upper
>> 8;
2457 *bufptr
++ = value
->range
.upper
;
2461 case IPP_TAG_TEXTLANG
:
2462 case IPP_TAG_NAMELANG
:
2463 for (i
= 0, value
= attr
->values
;
2464 i
< attr
->num_values
;
2470 * Arrays and sets are done by sending additional
2471 * values with a zero-length name...
2474 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2476 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2478 DEBUG_puts("1ippWriteIO: Could not write IPP "
2480 ipp_buffer_release(buffer
);
2487 *bufptr
++ = attr
->value_tag
;
2493 * textWithLanguage and nameWithLanguage values consist
2494 * of a 2-byte length for both strings and their
2495 * individual lengths, a 2-byte length for the
2496 * character string, the character string without the
2497 * trailing nul, a 2-byte length for the character
2498 * set string, and the character set string without
2504 if (value
->string
.charset
!= NULL
)
2505 n
+= (int)strlen(value
->string
.charset
);
2507 if (value
->string
.text
!= NULL
)
2508 n
+= (int)strlen(value
->string
.text
);
2510 if (n
> (IPP_BUF_SIZE
- 2))
2512 DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
2513 "too long (%d)", n
));
2514 ipp_buffer_release(buffer
);
2518 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2520 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2522 DEBUG_puts("1ippWriteIO: Could not write IPP "
2524 ipp_buffer_release(buffer
);
2531 /* Length of entire value */
2535 /* Length of charset */
2536 if (value
->string
.charset
!= NULL
)
2537 n
= (int)strlen(value
->string
.charset
);
2547 memcpy(bufptr
, value
->string
.charset
, n
);
2551 /* Length of text */
2552 if (value
->string
.text
!= NULL
)
2553 n
= (int)strlen(value
->string
.text
);
2563 memcpy(bufptr
, value
->string
.text
, n
);
2569 case IPP_TAG_BEGIN_COLLECTION
:
2570 for (i
= 0, value
= attr
->values
;
2571 i
< attr
->num_values
;
2575 * Collections are written with the begin-collection
2576 * tag first with a value of 0 length, followed by the
2577 * attributes in the collection, then the end-collection
2581 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 5)
2583 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2585 DEBUG_puts("1ippWriteIO: Could not write IPP "
2587 ipp_buffer_release(buffer
);
2597 * Arrays and sets are done by sending additional
2598 * values with a zero-length name...
2601 *bufptr
++ = attr
->value_tag
;
2607 * Write a data length of 0 and flush the buffer...
2613 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2615 DEBUG_puts("1ippWriteIO: Could not write IPP "
2617 ipp_buffer_release(buffer
);
2624 * Then write the collection attribute...
2627 value
->collection
->state
= IPP_IDLE
;
2629 if (ippWriteIO(dst
, cb
, 1, ipp
,
2630 value
->collection
) == IPP_ERROR
)
2632 DEBUG_puts("1ippWriteIO: Unable to write collection value");
2633 ipp_buffer_release(buffer
);
2640 for (i
= 0, value
= attr
->values
;
2641 i
< attr
->num_values
;
2647 * Arrays and sets are done by sending additional
2648 * values with a zero-length name...
2651 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2653 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2655 DEBUG_puts("1ippWriteIO: Could not write IPP "
2657 ipp_buffer_release(buffer
);
2664 *bufptr
++ = attr
->value_tag
;
2670 * An unknown value might some new value that a
2671 * vendor has come up with. It consists of a
2672 * 2-byte length and the bytes in the unknown
2676 n
= value
->unknown
.length
;
2678 if (n
> (IPP_BUF_SIZE
- 2))
2680 DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
2682 ipp_buffer_release(buffer
);
2686 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2688 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2690 DEBUG_puts("1ippWriteIO: Could not write IPP "
2692 ipp_buffer_release(buffer
);
2699 /* Length of unknown value */
2706 memcpy(bufptr
, value
->unknown
.data
, n
);
2714 * Write the data out...
2717 if (bufptr
> buffer
)
2719 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2721 DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
2722 ipp_buffer_release(buffer
);
2726 DEBUG_printf(("2ippWriteIO: wrote %d bytes",
2727 (int)(bufptr
- buffer
)));
2731 * If blocking is disabled, stop here...
2738 if (ipp
->current
== NULL
)
2741 * Done with all of the attributes; add the end-of-attributes
2742 * tag or end-collection attribute...
2747 buffer
[0] = IPP_TAG_END
;
2752 buffer
[0] = IPP_TAG_END_COLLECTION
;
2753 buffer
[1] = 0; /* empty name */
2755 buffer
[3] = 0; /* empty value */
2760 if ((*cb
)(dst
, buffer
, n
) < 0)
2762 DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
2763 ipp_buffer_release(buffer
);
2767 ipp
->state
= IPP_DATA
;
2775 break; /* anti-compiler-warning-code */
2778 ipp_buffer_release(buffer
);
2780 return (ipp
->state
);
2785 * '_ippAddAttr()' - Add a new attribute to the request.
2788 ipp_attribute_t
* /* O - New attribute */
2789 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2790 int num_values
) /* I - Number of values */
2792 ipp_attribute_t
*attr
; /* New attribute */
2795 DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp
, num_values
));
2797 if (!ipp
|| num_values
< 0)
2800 attr
= calloc(sizeof(ipp_attribute_t
) +
2801 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2805 attr
->num_values
= num_values
;
2807 if (ipp
->last
== NULL
)
2810 ipp
->last
->next
= attr
;
2815 DEBUG_printf(("5_ippAddAttr: Returning %p", attr
));
2822 * '_ippFreeAttr()' - Free an attribute.
2826 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2828 int i
; /* Looping var */
2829 ipp_value_t
*value
; /* Current value */
2832 DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr
));
2834 switch (attr
->value_tag
)
2838 case IPP_TAG_RESERVED_STRING
:
2839 case IPP_TAG_KEYWORD
:
2841 case IPP_TAG_URISCHEME
:
2842 case IPP_TAG_CHARSET
:
2843 case IPP_TAG_LANGUAGE
:
2844 case IPP_TAG_MIMETYPE
:
2845 for (i
= 0, value
= attr
->values
;
2846 i
< attr
->num_values
;
2848 _cupsStrFree(value
->string
.text
);
2851 case IPP_TAG_TEXTLANG
:
2852 case IPP_TAG_NAMELANG
:
2853 for (i
= 0, value
= attr
->values
;
2854 i
< attr
->num_values
;
2857 if (value
->string
.charset
&& i
== 0)
2858 _cupsStrFree(value
->string
.charset
);
2859 _cupsStrFree(value
->string
.text
);
2863 case IPP_TAG_INTEGER
:
2865 case IPP_TAG_BOOLEAN
:
2867 case IPP_TAG_RESOLUTION
:
2868 case IPP_TAG_RANGE
:
2871 case IPP_TAG_BEGIN_COLLECTION
:
2872 for (i
= 0, value
= attr
->values
;
2873 i
< attr
->num_values
;
2875 ippDelete(value
->collection
);
2878 case IPP_TAG_STRING
:
2879 for (i
= 0, value
= attr
->values
;
2880 i
< attr
->num_values
;
2882 free(value
->unknown
.data
);
2886 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2888 for (i
= 0, value
= attr
->values
;
2889 i
< attr
->num_values
;
2891 if (value
->unknown
.data
)
2892 free(value
->unknown
.data
);
2898 _cupsStrFree(attr
->name
);
2905 * 'ipp_buffer_get()' - Get a read/write buffer.
2908 static unsigned char * /* O - Buffer */
2909 ipp_buffer_get(void)
2911 _ipp_buffer_t
*buffer
; /* Current buffer */
2912 _cups_globals_t
*cg
= _cupsGlobals();
2916 for (buffer
= cg
->ipp_buffers
; buffer
; buffer
= buffer
->next
)
2923 if ((buffer
= malloc(sizeof(_ipp_buffer_t
))) == NULL
)
2927 buffer
->next
= cg
->ipp_buffers
;
2928 cg
->ipp_buffers
= buffer
;
2935 * 'ipp_buffer_release()' - Release a read/write buffer.
2939 ipp_buffer_release(unsigned char *b
) /* I - Buffer to release */
2941 ((_ipp_buffer_t
*)b
)->used
= 0;
2946 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2949 static size_t /* O - Size of IPP message */
2950 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2951 int collection
) /* I - 1 if a collection, 0 otherwise */
2953 int i
; /* Looping var */
2954 int bytes
; /* Number of bytes */
2955 ipp_attribute_t
*attr
; /* Current attribute */
2956 ipp_tag_t group
; /* Current group */
2957 ipp_value_t
*value
; /* Current value */
2964 * Start with 8 bytes for the IPP message header...
2967 bytes
= collection
? 0 : 8;
2970 * Then add the lengths of each attribute...
2973 group
= IPP_TAG_ZERO
;
2975 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2977 if (attr
->group_tag
!= group
&& !collection
)
2979 group
= attr
->group_tag
;
2980 if (group
== IPP_TAG_ZERO
)
2983 bytes
++; /* Group tag */
2989 DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2990 "bytes=%d", attr
->name
, attr
->num_values
, bytes
));
2992 bytes
+= (int)strlen(attr
->name
); /* Name */
2993 bytes
+= attr
->num_values
; /* Value tag for each value */
2994 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2995 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2998 bytes
+= 5; /* Add membername overhead */
3000 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
3002 case IPP_TAG_INTEGER
:
3004 bytes
+= 4 * attr
->num_values
;
3007 case IPP_TAG_BOOLEAN
:
3008 bytes
+= attr
->num_values
;
3013 case IPP_TAG_KEYWORD
:
3015 case IPP_TAG_URISCHEME
:
3016 case IPP_TAG_CHARSET
:
3017 case IPP_TAG_LANGUAGE
:
3018 case IPP_TAG_MIMETYPE
:
3019 for (i
= 0, value
= attr
->values
;
3020 i
< attr
->num_values
;
3022 if (value
->string
.text
!= NULL
)
3023 bytes
+= (int)strlen(value
->string
.text
);
3027 bytes
+= 11 * attr
->num_values
;
3030 case IPP_TAG_RESOLUTION
:
3031 bytes
+= 9 * attr
->num_values
;
3034 case IPP_TAG_RANGE
:
3035 bytes
+= 8 * attr
->num_values
;
3038 case IPP_TAG_TEXTLANG
:
3039 case IPP_TAG_NAMELANG
:
3040 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
3042 for (i
= 0, value
= attr
->values
;
3043 i
< attr
->num_values
;
3046 if (value
->string
.charset
!= NULL
)
3047 bytes
+= (int)strlen(value
->string
.charset
);
3049 if (value
->string
.text
!= NULL
)
3050 bytes
+= (int)strlen(value
->string
.text
);
3054 case IPP_TAG_BEGIN_COLLECTION
:
3055 for (i
= 0, value
= attr
->values
;
3056 i
< attr
->num_values
;
3058 bytes
+= (int)ipp_length(value
->collection
, 1);
3062 for (i
= 0, value
= attr
->values
;
3063 i
< attr
->num_values
;
3065 bytes
+= value
->unknown
.length
;
3071 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
3072 * for the "end of collection" tag and return...
3080 DEBUG_printf(("8ipp_length: Returning %d bytes", bytes
));
3087 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
3090 static ssize_t
/* O - Number of bytes read */
3091 ipp_read_http(http_t
*http
, /* I - Client connection */
3092 ipp_uchar_t
*buffer
, /* O - Buffer for data */
3093 size_t length
) /* I - Total length */
3095 int tbytes
, /* Total bytes read */
3096 bytes
; /* Bytes read this pass */
3097 char len
[32]; /* Length string */
3100 DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
3101 http
, buffer
, (int)length
));
3104 * Loop until all bytes are read...
3107 for (tbytes
= 0, bytes
= 0;
3108 tbytes
< (int)length
;
3109 tbytes
+= bytes
, buffer
+= bytes
)
3111 DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes
,
3114 if (http
->state
== HTTP_WAITING
)
3117 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
3120 * Do "fast read" from HTTP buffer directly...
3123 if (http
->used
> (int)(length
- tbytes
))
3124 bytes
= (int)(length
- tbytes
);
3129 buffer
[0] = http
->buffer
[0];
3131 memcpy(buffer
, http
->buffer
, bytes
);
3133 http
->used
-= bytes
;
3134 http
->data_remaining
-= bytes
;
3136 if (http
->data_remaining
<= INT_MAX
)
3137 http
->_data_remaining
= (int)http
->data_remaining
;
3139 http
->_data_remaining
= INT_MAX
;
3142 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
3144 if (http
->data_remaining
== 0)
3146 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
3149 * Get the trailing CR LF after the chunk...
3152 if (!httpGets(len
, sizeof(len
), http
))
3156 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
3158 if (http
->state
== HTTP_POST_RECV
)
3161 http
->state
= HTTP_WAITING
;
3168 * Wait a maximum of 1 second for data...
3171 if (!http
->blocking
)
3174 * Wait up to 10 seconds for more data on non-blocking sockets...
3177 if (!httpWait(http
, 10000))
3188 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) < 0)
3193 if (errno
!= EAGAIN
&& errno
!= EINTR
)
3199 else if (bytes
== 0)
3205 * Return the number of bytes read...
3208 if (tbytes
== 0 && bytes
< 0)
3211 DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes
));
3218 * 'ipp_read_file()' - Read IPP data from a file.
3221 static ssize_t
/* O - Number of bytes read */
3222 ipp_read_file(int *fd
, /* I - File descriptor */
3223 ipp_uchar_t
*buffer
, /* O - Read buffer */
3224 size_t length
) /* I - Number of bytes to read */
3227 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
3229 return (read(*fd
, buffer
, length
));
3235 * 'ipp_write_file()' - Write IPP data to a file.
3238 static ssize_t
/* O - Number of bytes written */
3239 ipp_write_file(int *fd
, /* I - File descriptor */
3240 ipp_uchar_t
*buffer
, /* I - Data to write */
3241 size_t length
) /* I - Number of bytes to write */
3244 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
3246 return (write(*fd
, buffer
, length
));
3253 * The following symbol definitions are provided only for KDE
3254 * compatibility during the CUPS 1.2 testing period and will be
3255 * removed in a future release of CUPS. These are PRIVATE APIs
3256 * from CUPS 1.1.x that the KDE developers chose to use...
3259 ipp_attribute_t
* /* O - New attribute */
3260 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
3261 int num_values
) /* I - Number of values */
3263 return (_ippAddAttr(ipp
, num_values
));
3267 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
3271 #endif /* __linux */
3275 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".