2 * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
4 * Internet Printing Protocol functions for CUPS.
6 * Copyright 2007-2010 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
;
189 * 'ippAddCollections()' - Add an array of collection values.
191 * @since CUPS 1.1.19/Mac OS X 10.3@
194 ipp_attribute_t
* /* O - New attribute */
196 ipp_t
*ipp
, /* I - IPP message */
197 ipp_tag_t group
, /* I - IPP group */
198 const char *name
, /* I - Name of attribute */
199 int num_values
, /* I - Number of values */
200 const ipp_t
**values
) /* I - Values */
202 int i
; /* Looping var */
203 ipp_attribute_t
*attr
; /* New attribute */
204 ipp_value_t
*value
; /* Current value */
207 DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
208 "num_values=%d, values=%p)", ipp
, group
, ippTagString(group
),
209 name
, num_values
, values
));
211 if (!ipp
|| !name
|| num_values
< 1)
214 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
217 attr
->name
= _cupsStrAlloc(name
);
218 attr
->group_tag
= group
;
219 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
222 for (i
= 0, value
= attr
->values
;
225 value
->collection
= (ipp_t
*)values
[i
];
232 * 'ippAddDate()' - Add a date attribute to an IPP message.
235 ipp_attribute_t
* /* O - New attribute */
236 ippAddDate(ipp_t
*ipp
, /* I - IPP message */
237 ipp_tag_t group
, /* I - IPP group */
238 const char *name
, /* I - Name of attribute */
239 const ipp_uchar_t
*value
) /* I - Value */
241 ipp_attribute_t
*attr
; /* New attribute */
244 DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
245 ipp
, group
, ippTagString(group
), name
, value
));
247 if (!ipp
|| !name
|| !value
)
250 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
253 attr
->name
= _cupsStrAlloc(name
);
254 attr
->group_tag
= group
;
255 attr
->value_tag
= IPP_TAG_DATE
;
256 memcpy(attr
->values
[0].date
, value
, 11);
263 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
266 ipp_attribute_t
* /* O - New attribute */
267 ippAddInteger(ipp_t
*ipp
, /* I - IPP message */
268 ipp_tag_t group
, /* I - IPP group */
269 ipp_tag_t type
, /* I - Type of attribute */
270 const char *name
, /* I - Name of attribute */
271 int value
) /* I - Value of attribute */
273 ipp_attribute_t
*attr
; /* New attribute */
276 DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
277 "name=\"%s\", value=%d)", ipp
, group
, ippTagString(group
),
278 type
, ippTagString(type
), name
, value
));
283 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
286 attr
->name
= _cupsStrAlloc(name
);
287 attr
->group_tag
= group
;
288 attr
->value_tag
= type
;
289 attr
->values
[0].integer
= value
;
296 * 'ippAddIntegers()' - Add an array of integer values.
299 ipp_attribute_t
* /* O - New attribute */
300 ippAddIntegers(ipp_t
*ipp
, /* I - IPP message */
301 ipp_tag_t group
, /* I - IPP group */
302 ipp_tag_t type
, /* I - Type of attribute */
303 const char *name
, /* I - Name of attribute */
304 int num_values
, /* I - Number of values */
305 const int *values
) /* I - Values */
307 int i
; /* Looping var */
308 ipp_attribute_t
*attr
; /* New attribute */
309 ipp_value_t
*value
; /* Current value */
312 DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
313 "name=\"%s\", num_values=%d, values=%p)", ipp
,
314 group
, ippTagString(group
), type
, ippTagString(type
), name
,
315 num_values
, values
));
317 if (!ipp
|| !name
|| num_values
< 1)
320 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
323 attr
->name
= _cupsStrAlloc(name
);
324 attr
->group_tag
= group
;
325 attr
->value_tag
= type
;
328 for (i
= 0, value
= attr
->values
;
331 value
->integer
= values
[i
];
338 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
340 * @since CUPS 1.2/Mac OS X 10.5@
343 ipp_attribute_t
* /* O - New attribute */
344 ippAddOctetString(ipp_t
*ipp
, /* I - IPP message */
345 ipp_tag_t group
, /* I - IPP group */
346 const char *name
, /* I - Name of attribute */
347 const void *data
, /* I - octetString data */
348 int datalen
) /* I - Length of data in bytes */
350 ipp_attribute_t
*attr
; /* New attribute */
353 if (ipp
== NULL
|| name
== NULL
)
356 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
360 * Initialize the attribute data...
363 attr
->name
= _cupsStrAlloc(name
);
364 attr
->group_tag
= group
;
365 attr
->value_tag
= IPP_TAG_STRING
;
366 attr
->values
[0].unknown
.length
= datalen
;
370 if ((attr
->values
[0].unknown
.data
= malloc(datalen
)) == NULL
)
372 ippDeleteAttribute(ipp
, attr
);
376 memcpy(attr
->values
[0].unknown
.data
, data
, datalen
);
380 * Return the new attribute...
388 * 'ippAddString()' - Add a language-encoded string to an IPP message.
391 ipp_attribute_t
* /* O - New attribute */
392 ippAddString(ipp_t
*ipp
, /* I - IPP message */
393 ipp_tag_t group
, /* I - IPP group */
394 ipp_tag_t type
, /* I - Type of attribute */
395 const char *name
, /* I - Name of attribute */
396 const char *charset
, /* I - Character set */
397 const char *value
) /* I - Value */
399 ipp_attribute_t
*attr
; /* New attribute */
400 char buffer
[1024], /* Language/charset value buffer */
401 *bufptr
; /* Pointer into buffer */
404 DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
405 "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp
,
406 group
, ippTagString(group
), type
, ippTagString(type
), name
,
412 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
416 * Force value to be English for the POSIX locale...
419 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(value
, "C"))
423 * Convert language and charset values to lowercase and change _ to - as
427 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
429 strlcpy(buffer
, value
, sizeof(buffer
));
432 for (bufptr
= buffer
; *bufptr
; bufptr
++)
436 *bufptr
= tolower(*bufptr
& 255);
440 * Initialize the attribute data...
443 attr
->name
= _cupsStrAlloc(name
);
444 attr
->group_tag
= group
;
445 attr
->value_tag
= type
;
446 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
447 charset
? _cupsStrAlloc(charset
) : NULL
;
448 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
449 value
? _cupsStrAlloc(value
) : NULL
;
456 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
459 ipp_attribute_t
* /* O - New attribute */
461 ipp_t
*ipp
, /* I - IPP message */
462 ipp_tag_t group
, /* I - IPP group */
463 ipp_tag_t type
, /* I - Type of attribute */
464 const char *name
, /* I - Name of attribute */
465 int num_values
, /* I - Number of values */
466 const char *charset
, /* I - Character set */
467 const char * const *values
) /* I - Values */
469 int i
; /* Looping var */
470 ipp_attribute_t
*attr
; /* New attribute */
471 ipp_value_t
*value
; /* Current value */
472 char buffer
[1024], /* Language/charset value buffer */
473 *bufptr
; /* Pointer into buffer */
476 DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
477 "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp
,
478 group
, ippTagString(group
), type
, ippTagString(type
), name
,
479 num_values
, charset
, values
));
481 if (!ipp
|| !name
|| num_values
< 1)
484 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
488 * Initialize the attribute data...
491 attr
->name
= _cupsStrAlloc(name
);
492 attr
->group_tag
= group
;
493 attr
->value_tag
= type
;
495 for (i
= 0, value
= attr
->values
;
500 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
501 charset
? _cupsStrAlloc(charset
) : NULL
;
503 value
->string
.charset
= attr
->values
[0].string
.charset
;
507 if ((int)type
& IPP_TAG_COPY
)
508 value
->string
.text
= (char *)values
[i
];
509 else if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(values
[i
], "C"))
512 * Force language to be English for the POSIX locale...
515 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
518 else if (type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
)
521 * Convert language values to lowercase and change _ to - as needed...
524 strlcpy(buffer
, values
[i
], sizeof(buffer
));
526 for (bufptr
= buffer
; *bufptr
; bufptr
++)
530 *bufptr
= tolower(*bufptr
& 255);
532 value
->string
.text
= _cupsStrAlloc(buffer
);
535 value
->string
.text
= _cupsStrAlloc(values
[i
]);
545 * 'ippAddRange()' - Add a range of values to an IPP message.
548 ipp_attribute_t
* /* O - New attribute */
549 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
550 ipp_tag_t group
, /* I - IPP group */
551 const char *name
, /* I - Name of attribute */
552 int lower
, /* I - Lower value */
553 int upper
) /* I - Upper value */
555 ipp_attribute_t
*attr
; /* New attribute */
558 DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
559 "upper=%d)", ipp
, group
, ippTagString(group
), name
, lower
,
565 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
568 attr
->name
= _cupsStrAlloc(name
);
569 attr
->group_tag
= group
;
570 attr
->value_tag
= IPP_TAG_RANGE
;
571 attr
->values
[0].range
.lower
= lower
;
572 attr
->values
[0].range
.upper
= upper
;
579 * 'ippAddRanges()' - Add ranges of values to an IPP message.
582 ipp_attribute_t
* /* O - New attribute */
583 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
584 ipp_tag_t group
, /* I - IPP group */
585 const char *name
, /* I - Name of attribute */
586 int num_values
, /* I - Number of values */
587 const int *lower
, /* I - Lower values */
588 const int *upper
) /* I - Upper values */
590 int i
; /* Looping var */
591 ipp_attribute_t
*attr
; /* New attribute */
592 ipp_value_t
*value
; /* Current value */
595 DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
596 "num_values=%d, lower=%p, upper=%p)", ipp
, group
,
597 ippTagString(group
), name
, num_values
, lower
, upper
));
599 if (!ipp
|| !name
|| num_values
< 1)
602 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
605 attr
->name
= _cupsStrAlloc(name
);
606 attr
->group_tag
= group
;
607 attr
->value_tag
= IPP_TAG_RANGE
;
609 if (lower
!= NULL
&& upper
!= NULL
)
610 for (i
= 0, value
= attr
->values
;
614 value
->range
.lower
= lower
[i
];
615 value
->range
.upper
= upper
[i
];
623 * 'ippAddResolution()' - Add a resolution value to an IPP message.
626 ipp_attribute_t
* /* O - New attribute */
627 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
628 ipp_tag_t group
, /* I - IPP group */
629 const char *name
, /* I - Name of attribute */
630 ipp_res_t units
, /* I - Units for resolution */
631 int xres
, /* I - X resolution */
632 int yres
) /* I - Y resolution */
634 ipp_attribute_t
*attr
; /* New attribute */
637 DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
638 "units=%d, xres=%d, yres=%d)", ipp
, group
,
639 ippTagString(group
), name
, units
, xres
, yres
));
644 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
647 attr
->name
= _cupsStrAlloc(name
);
648 attr
->group_tag
= group
;
649 attr
->value_tag
= IPP_TAG_RESOLUTION
;
650 attr
->values
[0].resolution
.xres
= xres
;
651 attr
->values
[0].resolution
.yres
= yres
;
652 attr
->values
[0].resolution
.units
= units
;
659 * 'ippAddResolutions()' - Add resolution values to an IPP message.
662 ipp_attribute_t
* /* O - New attribute */
663 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
664 ipp_tag_t group
, /* I - IPP group */
665 const char *name
, /* I - Name of attribute */
666 int num_values
,/* I - Number of values */
667 ipp_res_t units
, /* I - Units for resolution */
668 const int *xres
, /* I - X resolutions */
669 const int *yres
) /* I - Y resolutions */
671 int i
; /* Looping var */
672 ipp_attribute_t
*attr
; /* New attribute */
673 ipp_value_t
*value
; /* Current value */
676 DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
677 "num_value=%d, units=%d, xres=%p, yres=%p)", ipp
, group
,
678 ippTagString(group
), name
, num_values
, units
, xres
, yres
));
680 if (!ipp
|| !name
|| num_values
< 1)
683 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
686 attr
->name
= _cupsStrAlloc(name
);
687 attr
->group_tag
= group
;
688 attr
->value_tag
= IPP_TAG_RESOLUTION
;
690 if (xres
!= NULL
&& yres
!= NULL
)
691 for (i
= 0, value
= attr
->values
;
695 value
->resolution
.xres
= xres
[i
];
696 value
->resolution
.yres
= yres
[i
];
697 value
->resolution
.units
= units
;
705 * 'ippAddSeparator()' - Add a group separator to an IPP message.
708 ipp_attribute_t
* /* O - New attribute */
709 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
711 ipp_attribute_t
*attr
; /* New attribute */
714 DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp
));
719 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
722 attr
->group_tag
= IPP_TAG_ZERO
;
723 attr
->value_tag
= IPP_TAG_ZERO
;
730 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
734 time_t /* O - UNIX time value */
735 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
737 struct tm unixdate
; /* UNIX date/time info */
738 time_t t
; /* Computed time */
744 memset(&unixdate
, 0, sizeof(unixdate
));
747 * RFC-1903 date/time format is:
749 * Byte(s) Description
750 * ------- -----------
751 * 0-1 Year (0 to 65535)
755 * 5 Minutes (0 to 59)
756 * 6 Seconds (0 to 60, 60 = "leap second")
757 * 7 Deciseconds (0 to 9)
759 * 9 UTC hours (0 to 11)
760 * 10 UTC minutes (0 to 59)
763 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
764 unixdate
.tm_mon
= date
[2] - 1;
765 unixdate
.tm_mday
= date
[3];
766 unixdate
.tm_hour
= date
[4];
767 unixdate
.tm_min
= date
[5];
768 unixdate
.tm_sec
= date
[6];
770 t
= mktime(&unixdate
);
773 t
+= date
[9] * 3600 + date
[10] * 60;
775 t
-= date
[9] * 3600 + date
[10] * 60;
782 * 'ippDelete()' - Delete an IPP message.
786 ippDelete(ipp_t
*ipp
) /* I - IPP message */
788 ipp_attribute_t
*attr
, /* Current attribute */
789 *next
; /* Next attribute */
792 DEBUG_printf(("ippDelete(ipp=%p)", ipp
));
797 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
808 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
810 * @since CUPS 1.1.19/Mac OS X 10.3@
815 ipp_t
*ipp
, /* I - IPP message */
816 ipp_attribute_t
*attr
) /* I - Attribute to delete */
818 ipp_attribute_t
*current
, /* Current attribute */
819 *prev
; /* Previous attribute */
822 DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp
, attr
,
823 attr
? attr
->name
: "(null)"));
826 * Find the attribute in the list...
829 for (current
= ipp
->attrs
, prev
= NULL
;
830 current
!= NULL
&& current
!= attr
;
831 prev
= current
, current
= current
->next
);
836 * Found it, remove the attribute from the list...
840 prev
->next
= current
->next
;
842 ipp
->attrs
= current
->next
;
844 if (current
== ipp
->last
)
848 * Free memory used by the attribute...
851 _ippFreeAttr(current
);
857 * 'ippFindAttribute()' - Find a named attribute in a request...
860 ipp_attribute_t
* /* O - Matching attribute */
861 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
862 const char *name
, /* I - Name of attribute */
863 ipp_tag_t type
) /* I - Type of attribute */
865 DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp
,
866 name
, type
, ippTagString(type
)));
872 * Reset the current pointer...
878 * Search for the attribute...
881 return (ippFindNextAttribute(ipp
, name
, type
));
886 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
889 ipp_attribute_t
* /* O - Matching attribute */
890 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
891 const char *name
, /* I - Name of attribute */
892 ipp_tag_t type
) /* I - Type of attribute */
894 ipp_attribute_t
*attr
; /* Current atttribute */
895 ipp_tag_t value_tag
; /* Value tag */
898 DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
899 ipp
, name
, type
, ippTagString(type
)));
906 ipp
->prev
= ipp
->current
;
907 attr
= ipp
->current
->next
;
915 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
917 DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr
,
920 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
922 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
923 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
924 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
925 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
941 * 'ippLength()' - Compute the length of an IPP message.
944 size_t /* O - Size of IPP message */
945 ippLength(ipp_t
*ipp
) /* I - IPP message */
947 return (ipp_length(ipp
, 0));
952 * 'ippNew()' - Allocate a new IPP message.
955 ipp_t
* /* O - New IPP message */
958 ipp_t
*temp
; /* New IPP message */
961 DEBUG_puts("ippNew()");
963 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
966 * Default to IPP 1.1...
969 temp
->request
.any
.version
[0] = 1;
970 temp
->request
.any
.version
[1] = 1;
973 DEBUG_printf(("1ippNew: Returning %p", temp
));
980 * 'ippNewRequest()' - Allocate a new IPP request message.
982 * The new request message is initialized with the attributes-charset and
983 * attributes-natural-language attributes added. The
984 * attributes-natural-language value is derived from the current locale.
986 * @since CUPS 1.2/Mac OS X 10.5@
989 ipp_t
* /* O - IPP request message */
990 ippNewRequest(ipp_op_t op
) /* I - Operation code */
992 ipp_t
*request
; /* IPP request message */
993 cups_lang_t
*language
; /* Current language localization */
996 DEBUG_printf(("ippNewRequest(op=%02x(%s))", op
, ippOpString(op
)));
999 * Create a new IPP message...
1002 if ((request
= ippNew()) == NULL
)
1006 * Set the operation and request ID...
1009 request
->request
.op
.operation_id
= op
;
1010 request
->request
.op
.request_id
= 1;
1013 * Use UTF-8 as the character set...
1016 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1017 "attributes-charset", NULL
, "utf-8");
1020 * Get the language from the current locale...
1023 language
= cupsLangDefault();
1025 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1026 "attributes-natural-language", NULL
, language
->language
);
1029 * Return the new request...
1037 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
1040 ipp_state_t
/* O - Current state */
1041 ippRead(http_t
*http
, /* I - HTTP connection */
1042 ipp_t
*ipp
) /* I - IPP data */
1044 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
,
1045 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
1050 DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http
->state
,
1053 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
, http
->blocking
, NULL
,
1059 * 'ippReadFile()' - Read data for an IPP message from a file.
1061 * @since CUPS 1.1.19/Mac OS X 10.3@
1064 ipp_state_t
/* O - Current state */
1065 ippReadFile(int fd
, /* I - HTTP data */
1066 ipp_t
*ipp
) /* I - IPP data */
1068 DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd
, ipp
));
1070 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1075 * 'ippReadIO()' - Read data for an IPP message.
1077 * @since CUPS 1.2/Mac OS X 10.5@
1080 ipp_state_t
/* O - Current state */
1081 ippReadIO(void *src
, /* I - Data source */
1082 ipp_iocb_t cb
, /* I - Read callback function */
1083 int blocking
, /* I - Use blocking IO? */
1084 ipp_t
*parent
, /* I - Parent request, if any */
1085 ipp_t
*ipp
) /* I - IPP data */
1087 int n
; /* Length of data */
1088 unsigned char *buffer
, /* Data buffer */
1089 string
[IPP_MAX_NAME
],
1090 /* Small string buffer */
1091 *bufptr
; /* Pointer into buffer */
1092 ipp_attribute_t
*attr
; /* Current attribute */
1093 ipp_tag_t tag
; /* Current tag */
1094 ipp_tag_t value_tag
; /* Current value tag */
1095 ipp_value_t
*value
; /* Current value */
1098 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1099 src
, cb
, blocking
, parent
, ipp
));
1100 DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp
->state
));
1105 if ((buffer
= ipp_buffer_get()) == NULL
)
1107 DEBUG_puts("1ippReadIO: Unable to get read buffer!");
1114 ipp
->state
++; /* Avoid common problem... */
1120 * Get the request header...
1123 if ((*cb
)(src
, buffer
, 8) < 8)
1125 DEBUG_puts("1ippReadIO: Unable to read header!");
1126 ipp_buffer_release(buffer
);
1131 * Then copy the request header over...
1134 ipp
->request
.any
.version
[0] = buffer
[0];
1135 ipp
->request
.any
.version
[1] = buffer
[1];
1136 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1137 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1138 buffer
[6]) << 8) | buffer
[7];
1140 DEBUG_printf(("2ippReadIO: version=%d.%d", buffer
[0], buffer
[1]));
1141 DEBUG_printf(("2ippReadIO: op_status=%04x",
1142 ipp
->request
.any
.op_status
));
1143 DEBUG_printf(("2ippReadIO: request_id=%d",
1144 ipp
->request
.any
.request_id
));
1147 ipp
->state
= IPP_ATTRIBUTE
;
1148 ipp
->current
= NULL
;
1149 ipp
->curtag
= IPP_TAG_ZERO
;
1150 ipp
->prev
= ipp
->last
;
1153 * If blocking is disabled, stop here...
1159 case IPP_ATTRIBUTE
:
1162 if ((*cb
)(src
, buffer
, 1) < 1)
1164 DEBUG_puts("1ippReadIO: Callback returned EOF/error");
1165 ipp_buffer_release(buffer
);
1169 DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
1170 ipp
->current
, ipp
->prev
));
1173 * Read this attribute...
1176 tag
= (ipp_tag_t
)buffer
[0];
1178 if (tag
== IPP_TAG_END
)
1181 * No more attributes left...
1184 DEBUG_puts("2ippReadIO: IPP_TAG_END!");
1186 ipp
->state
= IPP_DATA
;
1189 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1192 * Group tag... Set the current group and continue...
1195 if (ipp
->curtag
== tag
)
1196 ipp
->prev
= ippAddSeparator(ipp
);
1197 else if (ipp
->current
)
1198 ipp
->prev
= ipp
->current
;
1201 ipp
->current
= NULL
;
1202 DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag
,
1203 ippTagString(tag
), ipp
->prev
));
1207 DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag
,
1208 ippTagString(tag
)));
1214 if ((*cb
)(src
, buffer
, 2) < 2)
1216 DEBUG_puts("1ippReadIO: unable to read name length!");
1217 ipp_buffer_release(buffer
);
1221 n
= (buffer
[0] << 8) | buffer
[1];
1223 if (n
>= IPP_BUF_SIZE
)
1225 DEBUG_printf(("1ippReadIO: bad name length %d!", n
));
1226 ipp_buffer_release(buffer
);
1230 DEBUG_printf(("2ippReadIO: name length=%d", n
));
1232 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1233 tag
!= IPP_TAG_END_COLLECTION
)
1236 * More values for current attribute...
1239 if (ipp
->current
== NULL
)
1241 DEBUG_puts("1ippReadIO: Attribute without name and no current");
1242 ipp_buffer_release(buffer
);
1246 attr
= ipp
->current
;
1247 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1250 * Make sure we aren't adding a new value of a different
1254 if (value_tag
== IPP_TAG_ZERO
)
1257 * Setting the value of a collection member...
1260 attr
->value_tag
= tag
;
1262 else if ((value_tag
>= IPP_TAG_TEXTLANG
&&
1263 value_tag
<= IPP_TAG_MIMETYPE
))
1266 * String values can sometimes come across in different
1267 * forms; accept sets of differing values...
1270 if ((tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
) &&
1271 tag
!= IPP_TAG_NOVALUE
)
1273 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1274 value_tag
, ippTagString(value_tag
), tag
,
1275 ippTagString(tag
)));
1276 ipp_buffer_release(buffer
);
1280 else if (value_tag
!= tag
)
1282 DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
1283 value_tag
, ippTagString(value_tag
), tag
,
1284 ippTagString(tag
)));
1285 ipp_buffer_release(buffer
);
1290 * Finally, reallocate the attribute array as needed...
1293 if (attr
->num_values
== 1 ||
1294 (attr
->num_values
> 0 &&
1295 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1297 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1300 DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
1301 attr
->num_values
+ IPP_MAX_VALUES
));
1304 * Reallocate memory...
1307 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1308 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1309 sizeof(ipp_value_t
))) == NULL
)
1311 DEBUG_puts("1ippReadIO: Unable to resize attribute");
1312 ipp_buffer_release(buffer
);
1319 * Reset pointers in the list...
1323 ipp
->prev
->next
= temp
;
1327 attr
= ipp
->current
= ipp
->last
= temp
;
1331 else if (tag
== IPP_TAG_MEMBERNAME
)
1334 * Name must be length 0!
1339 DEBUG_puts("1ippReadIO: member name not empty!");
1340 ipp_buffer_release(buffer
);
1345 ipp
->prev
= ipp
->current
;
1347 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1349 DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
1350 "ipp->prev=%p", ipp
->current
, ipp
->prev
));
1352 attr
->group_tag
= ipp
->curtag
;
1353 attr
->value_tag
= IPP_TAG_ZERO
;
1354 attr
->num_values
= 0;
1356 else if (tag
!= IPP_TAG_END_COLLECTION
)
1359 * New attribute; read the name and add it...
1362 if ((*cb
)(src
, buffer
, n
) < n
)
1364 DEBUG_puts("1ippReadIO: unable to read name!");
1365 ipp_buffer_release(buffer
);
1372 ipp
->prev
= ipp
->current
;
1374 if ((attr
= ipp
->current
= _ippAddAttr(ipp
, 1)) == NULL
)
1376 DEBUG_puts("1ippReadIO: unable to allocate attribute!");
1377 ipp_buffer_release(buffer
);
1381 DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
1382 "ipp->prev=%p", buffer
, ipp
->current
, ipp
->prev
));
1384 attr
->group_tag
= ipp
->curtag
;
1385 attr
->value_tag
= tag
;
1386 attr
->name
= _cupsStrAlloc((char *)buffer
);
1387 attr
->num_values
= 0;
1392 if (tag
!= IPP_TAG_END_COLLECTION
)
1393 value
= attr
->values
+ attr
->num_values
;
1397 if ((*cb
)(src
, buffer
, 2) < 2)
1399 DEBUG_puts("1ippReadIO: unable to read value length!");
1400 ipp_buffer_release(buffer
);
1404 n
= (buffer
[0] << 8) | buffer
[1];
1405 DEBUG_printf(("2ippReadIO: value length=%d", n
));
1409 case IPP_TAG_INTEGER
:
1413 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1414 ipp_buffer_release(buffer
);
1418 if ((*cb
)(src
, buffer
, 4) < 4)
1420 DEBUG_puts("1ippReadIO: Unable to read integer value!");
1421 ipp_buffer_release(buffer
);
1425 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1431 case IPP_TAG_BOOLEAN
:
1434 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1435 ipp_buffer_release(buffer
);
1439 if ((*cb
)(src
, buffer
, 1) < 1)
1441 DEBUG_puts("1ippReadIO: Unable to read boolean value!");
1442 ipp_buffer_release(buffer
);
1446 value
->boolean
= buffer
[0];
1449 case IPP_TAG_NOVALUE
:
1450 case IPP_TAG_NOTSETTABLE
:
1451 case IPP_TAG_DELETEATTR
:
1452 case IPP_TAG_ADMINDEFINE
:
1454 * These value types are not supposed to have values, however
1455 * some vendors (Brother) do not implement IPP correctly and so
1456 * we need to map non-empty values to text...
1459 if (attr
->value_tag
== tag
)
1464 attr
->value_tag
= IPP_TAG_TEXT
;
1469 case IPP_TAG_KEYWORD
:
1471 case IPP_TAG_URISCHEME
:
1472 case IPP_TAG_CHARSET
:
1473 case IPP_TAG_LANGUAGE
:
1474 case IPP_TAG_MIMETYPE
:
1475 if (n
>= IPP_BUF_SIZE
)
1477 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1478 ipp_buffer_release(buffer
);
1482 if ((*cb
)(src
, buffer
, n
) < n
)
1484 DEBUG_puts("1ippReadIO: unable to read name!");
1485 ipp_buffer_release(buffer
);
1490 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1491 DEBUG_printf(("2ippReadIO: value=\"%s\"", value
->string
.text
));
1497 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1498 ipp_buffer_release(buffer
);
1502 if ((*cb
)(src
, value
->date
, 11) < 11)
1504 DEBUG_puts("1ippReadIO: Unable to read date value!");
1505 ipp_buffer_release(buffer
);
1510 case IPP_TAG_RESOLUTION
:
1513 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1514 ipp_buffer_release(buffer
);
1518 if ((*cb
)(src
, buffer
, 9) < 9)
1520 DEBUG_puts("1ippReadIO: Unable to read resolution value!");
1521 ipp_buffer_release(buffer
);
1525 value
->resolution
.xres
=
1526 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1528 value
->resolution
.yres
=
1529 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1531 value
->resolution
.units
=
1532 (ipp_res_t
)buffer
[8];
1535 case IPP_TAG_RANGE
:
1538 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1539 ipp_buffer_release(buffer
);
1543 if ((*cb
)(src
, buffer
, 8) < 8)
1545 DEBUG_puts("1ippReadIO: Unable to read range value!");
1546 ipp_buffer_release(buffer
);
1550 value
->range
.lower
=
1551 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1553 value
->range
.upper
=
1554 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1558 case IPP_TAG_TEXTLANG
:
1559 case IPP_TAG_NAMELANG
:
1560 if (n
>= IPP_BUF_SIZE
|| n
< 4)
1562 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1563 ipp_buffer_release(buffer
);
1567 if ((*cb
)(src
, buffer
, n
) < n
)
1569 DEBUG_puts("1ippReadIO: Unable to read string w/language "
1571 ipp_buffer_release(buffer
);
1578 * text-with-language and name-with-language are composite
1587 n
= (bufptr
[0] << 8) | bufptr
[1];
1589 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
) ||
1590 n
>= sizeof(string
))
1592 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1593 ipp_buffer_release(buffer
);
1597 memcpy(string
, bufptr
+ 2, n
);
1600 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1603 n
= (bufptr
[0] << 8) | bufptr
[1];
1605 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
))
1607 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1608 ipp_buffer_release(buffer
);
1612 bufptr
[2 + n
] = '\0';
1613 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1616 case IPP_TAG_BEGIN_COLLECTION
:
1618 * Oh, boy, here comes a collection value, so read it...
1621 value
->collection
= ippNew();
1625 DEBUG_puts("1ippReadIO: begCollection tag with value length "
1627 ipp_buffer_release(buffer
);
1631 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1633 DEBUG_puts("1ippReadIO: Unable to read collection value!");
1634 ipp_buffer_release(buffer
);
1639 case IPP_TAG_END_COLLECTION
:
1640 ipp_buffer_release(buffer
);
1644 DEBUG_puts("1ippReadIO: endCollection tag with value length "
1649 DEBUG_puts("1ippReadIO: endCollection tag...");
1650 return (ipp
->state
= IPP_DATA
);
1652 case IPP_TAG_MEMBERNAME
:
1654 * The value the name of the member in the collection, which
1655 * we need to carry over...
1658 if (n
>= IPP_BUF_SIZE
)
1660 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1661 ipp_buffer_release(buffer
);
1665 if ((*cb
)(src
, buffer
, n
) < n
)
1667 DEBUG_puts("1ippReadIO: Unable to read member name value!");
1668 ipp_buffer_release(buffer
);
1673 attr
->name
= _cupsStrAlloc((char *)buffer
);
1676 * Since collection members are encoded differently than
1677 * regular attributes, make sure we don't start with an
1681 attr
->num_values
--;
1683 DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr
->name
));
1686 default : /* Other unsupported values */
1687 if (n
> IPP_MAX_LENGTH
)
1689 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1690 ipp_buffer_release(buffer
);
1696 DEBUG_puts("1ippReadIO: NULL value!");
1697 ipp_buffer_release(buffer
);
1701 value
->unknown
.length
= n
;
1704 if ((value
->unknown
.data
= malloc(n
)) == NULL
)
1706 DEBUG_puts("1ippReadIO: Unable to allocate value");
1707 ipp_buffer_release(buffer
);
1711 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1713 DEBUG_puts("1ippReadIO: Unable to read unsupported value!");
1714 ipp_buffer_release(buffer
);
1719 value
->unknown
.data
= NULL
;
1723 attr
->num_values
++;
1726 * If blocking is disabled, stop here...
1738 break; /* anti-compiler-warning-code */
1741 DEBUG_printf(("1ippReadIO: returning ipp->state=%d!", ipp
->state
));
1742 ipp_buffer_release(buffer
);
1744 return (ipp
->state
);
1749 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1752 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1753 ippTimeToDate(time_t t
) /* I - UNIX time value */
1755 struct tm
*unixdate
; /* UNIX unixdate/time info */
1756 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1757 /* RFC-1903 date/time data */
1761 * RFC-1903 date/time format is:
1763 * Byte(s) Description
1764 * ------- -----------
1765 * 0-1 Year (0 to 65535)
1769 * 5 Minutes (0 to 59)
1770 * 6 Seconds (0 to 60, 60 = "leap second")
1771 * 7 Deciseconds (0 to 9)
1773 * 9 UTC hours (0 to 11)
1774 * 10 UTC minutes (0 to 59)
1777 unixdate
= gmtime(&t
);
1778 unixdate
->tm_year
+= 1900;
1780 date
[0] = unixdate
->tm_year
>> 8;
1781 date
[1] = unixdate
->tm_year
;
1782 date
[2] = unixdate
->tm_mon
+ 1;
1783 date
[3] = unixdate
->tm_mday
;
1784 date
[4] = unixdate
->tm_hour
;
1785 date
[5] = unixdate
->tm_min
;
1786 date
[6] = unixdate
->tm_sec
;
1797 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1800 ipp_state_t
/* O - Current state */
1801 ippWrite(http_t
*http
, /* I - HTTP connection */
1802 ipp_t
*ipp
) /* I - IPP data */
1804 DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http
, ipp
));
1809 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
, http
->blocking
, NULL
, ipp
));
1814 * 'ippWriteFile()' - Write data for an IPP message to a file.
1816 * @since CUPS 1.1.19/Mac OS X 10.3@
1819 ipp_state_t
/* O - Current state */
1820 ippWriteFile(int fd
, /* I - HTTP data */
1821 ipp_t
*ipp
) /* I - IPP data */
1823 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd
, ipp
));
1825 ipp
->state
= IPP_IDLE
;
1827 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1832 * 'ippWriteIO()' - Write data for an IPP message.
1834 * @since CUPS 1.2/Mac OS X 10.5@
1837 ipp_state_t
/* O - Current state */
1838 ippWriteIO(void *dst
, /* I - Destination */
1839 ipp_iocb_t cb
, /* I - Write callback function */
1840 int blocking
, /* I - Use blocking IO? */
1841 ipp_t
*parent
, /* I - Parent IPP message */
1842 ipp_t
*ipp
) /* I - IPP data */
1844 int i
; /* Looping var */
1845 int n
; /* Length of data */
1846 unsigned char *buffer
, /* Data buffer */
1847 *bufptr
; /* Pointer into buffer */
1848 ipp_attribute_t
*attr
; /* Current attribute */
1849 ipp_value_t
*value
; /* Current value */
1852 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1853 dst
, cb
, blocking
, parent
, ipp
));
1858 if ((buffer
= ipp_buffer_get()) == NULL
)
1860 DEBUG_puts("1ippWriteIO: Unable to get write buffer");
1867 ipp
->state
++; /* Avoid common problem... */
1873 * Send the request header:
1876 * Operation/Status Code = 2 bytes
1877 * Request ID = 4 bytes
1883 *bufptr
++ = ipp
->request
.any
.version
[0];
1884 *bufptr
++ = ipp
->request
.any
.version
[1];
1885 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1886 *bufptr
++ = ipp
->request
.any
.op_status
;
1887 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1888 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1889 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1890 *bufptr
++ = ipp
->request
.any
.request_id
;
1892 DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer
[0], buffer
[1]));
1893 DEBUG_printf(("2ippWriteIO: op_status=%04x",
1894 ipp
->request
.any
.op_status
));
1895 DEBUG_printf(("2ippWriteIO: request_id=%d",
1896 ipp
->request
.any
.request_id
));
1898 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1900 DEBUG_puts("1ippWriteIO: Could not write IPP header...");
1901 ipp_buffer_release(buffer
);
1907 * Reset the state engine to point to the first attribute
1908 * in the request/response, with no current group.
1911 ipp
->state
= IPP_ATTRIBUTE
;
1912 ipp
->current
= ipp
->attrs
;
1913 ipp
->curtag
= IPP_TAG_ZERO
;
1915 DEBUG_printf(("1ippWriteIO: ipp->current=%p", ipp
->current
));
1918 * If blocking is disabled, stop here...
1924 case IPP_ATTRIBUTE
:
1925 while (ipp
->current
!= NULL
)
1928 * Write this attribute...
1932 attr
= ipp
->current
;
1934 ipp
->current
= ipp
->current
->next
;
1938 if (ipp
->curtag
!= attr
->group_tag
)
1941 * Send a group tag byte...
1944 ipp
->curtag
= attr
->group_tag
;
1946 if (attr
->group_tag
== IPP_TAG_ZERO
)
1949 DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
1950 attr
->group_tag
, ippTagString(attr
->group_tag
)));
1951 *bufptr
++ = attr
->group_tag
;
1953 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1957 DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr
->name
,
1958 attr
->num_values
> 1 ? "1setOf " : "",
1959 ippTagString(attr
->value_tag
)));
1962 * Write the attribute tag and name. The current implementation
1963 * does not support the extension value tags above 0x7f, so all
1964 * value tags are 1 byte.
1966 * The attribute name length does not include the trailing nul
1967 * character in the source string.
1969 * Collection values (parent != NULL) are written differently...
1975 * Get the length of the attribute name, and make sure it won't
1976 * overflow the buffer...
1979 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 4))
1981 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
1982 ipp_buffer_release(buffer
);
1987 * Write the value tag, name length, and name string...
1990 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
1991 attr
->value_tag
, ippTagString(attr
->value_tag
)));
1992 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
1995 *bufptr
++ = attr
->value_tag
;
1998 memcpy(bufptr
, attr
->name
, n
);
2004 * Get the length of the attribute name, and make sure it won't
2005 * overflow the buffer...
2008 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 7))
2010 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
2011 ipp_buffer_release(buffer
);
2016 * Write the member name tag, name length, name string, value tag,
2017 * and empty name for the collection member attribute...
2020 DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
2021 IPP_TAG_MEMBERNAME
));
2022 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2024 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2025 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2026 DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
2028 *bufptr
++ = IPP_TAG_MEMBERNAME
;
2033 memcpy(bufptr
, attr
->name
, n
);
2036 *bufptr
++ = attr
->value_tag
;
2042 * Now write the attribute value(s)...
2045 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2047 case IPP_TAG_INTEGER
:
2049 for (i
= 0, value
= attr
->values
;
2050 i
< attr
->num_values
;
2053 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 9)
2055 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2057 DEBUG_puts("1ippWriteIO: Could not write IPP "
2059 ipp_buffer_release(buffer
);
2069 * Arrays and sets are done by sending additional
2070 * values with a zero-length name...
2073 *bufptr
++ = attr
->value_tag
;
2079 * Integers and enumerations are both 4-byte signed
2080 * (twos-complement) values.
2082 * Put the 2-byte length and 4-byte value into the buffer...
2087 *bufptr
++ = value
->integer
>> 24;
2088 *bufptr
++ = value
->integer
>> 16;
2089 *bufptr
++ = value
->integer
>> 8;
2090 *bufptr
++ = value
->integer
;
2094 case IPP_TAG_BOOLEAN
:
2095 for (i
= 0, value
= attr
->values
;
2096 i
< attr
->num_values
;
2099 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 6)
2101 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2103 DEBUG_puts("1ippWriteIO: Could not write IPP "
2105 ipp_buffer_release(buffer
);
2115 * Arrays and sets are done by sending additional
2116 * values with a zero-length name...
2119 *bufptr
++ = attr
->value_tag
;
2125 * Boolean values are 1-byte; 0 = false, 1 = true.
2127 * Put the 2-byte length and 1-byte value into the buffer...
2132 *bufptr
++ = value
->boolean
;
2138 case IPP_TAG_KEYWORD
:
2140 case IPP_TAG_URISCHEME
:
2141 case IPP_TAG_CHARSET
:
2142 case IPP_TAG_LANGUAGE
:
2143 case IPP_TAG_MIMETYPE
:
2144 for (i
= 0, value
= attr
->values
;
2145 i
< attr
->num_values
;
2151 * Arrays and sets are done by sending additional
2152 * values with a zero-length name...
2155 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2157 ippTagString(attr
->value_tag
)));
2158 DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
2160 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2162 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2164 DEBUG_puts("1ippWriteIO: Could not write IPP "
2166 ipp_buffer_release(buffer
);
2173 *bufptr
++ = attr
->value_tag
;
2178 if (value
->string
.text
!= NULL
)
2179 n
= (int)strlen(value
->string
.text
);
2183 if (n
> (IPP_BUF_SIZE
- 2))
2185 DEBUG_printf(("1ippWriteIO: String too long (%d)", n
));
2186 ipp_buffer_release(buffer
);
2190 DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n
,
2191 value
->string
.text
));
2193 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2195 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2197 DEBUG_puts("1ippWriteIO: Could not write IPP "
2199 ipp_buffer_release(buffer
);
2207 * All simple strings consist of the 2-byte length and
2208 * character data without the trailing nul normally found
2209 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2210 * bytes since the 2-byte length is a signed (twos-complement)
2213 * Put the 2-byte length and string characters in the buffer.
2221 memcpy(bufptr
, value
->string
.text
, n
);
2228 for (i
= 0, value
= attr
->values
;
2229 i
< attr
->num_values
;
2232 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 16)
2234 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2236 DEBUG_puts("1ippWriteIO: Could not write IPP "
2238 ipp_buffer_release(buffer
);
2248 * Arrays and sets are done by sending additional
2249 * values with a zero-length name...
2252 *bufptr
++ = attr
->value_tag
;
2258 * Date values consist of a 2-byte length and an
2259 * 11-byte date/time structure defined by RFC 1903.
2261 * Put the 2-byte length and 11-byte date/time
2262 * structure in the buffer.
2267 memcpy(bufptr
, value
->date
, 11);
2272 case IPP_TAG_RESOLUTION
:
2273 for (i
= 0, value
= attr
->values
;
2274 i
< attr
->num_values
;
2277 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 14)
2279 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2281 DEBUG_puts("1ippWriteIO: Could not write IPP "
2283 ipp_buffer_release(buffer
);
2293 * Arrays and sets are done by sending additional
2294 * values with a zero-length name...
2297 *bufptr
++ = attr
->value_tag
;
2303 * Resolution values consist of a 2-byte length,
2304 * 4-byte horizontal resolution value, 4-byte vertical
2305 * resolution value, and a 1-byte units value.
2307 * Put the 2-byte length and resolution value data
2313 *bufptr
++ = value
->resolution
.xres
>> 24;
2314 *bufptr
++ = value
->resolution
.xres
>> 16;
2315 *bufptr
++ = value
->resolution
.xres
>> 8;
2316 *bufptr
++ = value
->resolution
.xres
;
2317 *bufptr
++ = value
->resolution
.yres
>> 24;
2318 *bufptr
++ = value
->resolution
.yres
>> 16;
2319 *bufptr
++ = value
->resolution
.yres
>> 8;
2320 *bufptr
++ = value
->resolution
.yres
;
2321 *bufptr
++ = value
->resolution
.units
;
2325 case IPP_TAG_RANGE
:
2326 for (i
= 0, value
= attr
->values
;
2327 i
< attr
->num_values
;
2330 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 13)
2332 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2334 DEBUG_puts("1ippWriteIO: Could not write IPP "
2336 ipp_buffer_release(buffer
);
2346 * Arrays and sets are done by sending additional
2347 * values with a zero-length name...
2350 *bufptr
++ = attr
->value_tag
;
2356 * Range values consist of a 2-byte length,
2357 * 4-byte lower value, and 4-byte upper value.
2359 * Put the 2-byte length and range value data
2365 *bufptr
++ = value
->range
.lower
>> 24;
2366 *bufptr
++ = value
->range
.lower
>> 16;
2367 *bufptr
++ = value
->range
.lower
>> 8;
2368 *bufptr
++ = value
->range
.lower
;
2369 *bufptr
++ = value
->range
.upper
>> 24;
2370 *bufptr
++ = value
->range
.upper
>> 16;
2371 *bufptr
++ = value
->range
.upper
>> 8;
2372 *bufptr
++ = value
->range
.upper
;
2376 case IPP_TAG_TEXTLANG
:
2377 case IPP_TAG_NAMELANG
:
2378 for (i
= 0, value
= attr
->values
;
2379 i
< attr
->num_values
;
2385 * Arrays and sets are done by sending additional
2386 * values with a zero-length name...
2389 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2391 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2393 DEBUG_puts("1ippWriteIO: Could not write IPP "
2395 ipp_buffer_release(buffer
);
2402 *bufptr
++ = attr
->value_tag
;
2408 * textWithLanguage and nameWithLanguage values consist
2409 * of a 2-byte length for both strings and their
2410 * individual lengths, a 2-byte length for the
2411 * character string, the character string without the
2412 * trailing nul, a 2-byte length for the character
2413 * set string, and the character set string without
2419 if (value
->string
.charset
!= NULL
)
2420 n
+= (int)strlen(value
->string
.charset
);
2422 if (value
->string
.text
!= NULL
)
2423 n
+= (int)strlen(value
->string
.text
);
2425 if (n
> (IPP_BUF_SIZE
- 2))
2427 DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
2428 "too long (%d)", n
));
2429 ipp_buffer_release(buffer
);
2433 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2435 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2437 DEBUG_puts("1ippWriteIO: Could not write IPP "
2439 ipp_buffer_release(buffer
);
2446 /* Length of entire value */
2450 /* Length of charset */
2451 if (value
->string
.charset
!= NULL
)
2452 n
= (int)strlen(value
->string
.charset
);
2462 memcpy(bufptr
, value
->string
.charset
, n
);
2466 /* Length of text */
2467 if (value
->string
.text
!= NULL
)
2468 n
= (int)strlen(value
->string
.text
);
2478 memcpy(bufptr
, value
->string
.text
, n
);
2484 case IPP_TAG_BEGIN_COLLECTION
:
2485 for (i
= 0, value
= attr
->values
;
2486 i
< attr
->num_values
;
2490 * Collections are written with the begin-collection
2491 * tag first with a value of 0 length, followed by the
2492 * attributes in the collection, then the end-collection
2496 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 5)
2498 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2500 DEBUG_puts("1ippWriteIO: Could not write IPP "
2502 ipp_buffer_release(buffer
);
2512 * Arrays and sets are done by sending additional
2513 * values with a zero-length name...
2516 *bufptr
++ = attr
->value_tag
;
2522 * Write a data length of 0 and flush the buffer...
2528 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2530 DEBUG_puts("1ippWriteIO: Could not write IPP "
2532 ipp_buffer_release(buffer
);
2539 * Then write the collection attribute...
2542 value
->collection
->state
= IPP_IDLE
;
2544 if (ippWriteIO(dst
, cb
, 1, ipp
,
2545 value
->collection
) == IPP_ERROR
)
2547 DEBUG_puts("1ippWriteIO: Unable to write collection value");
2548 ipp_buffer_release(buffer
);
2555 for (i
= 0, value
= attr
->values
;
2556 i
< attr
->num_values
;
2562 * Arrays and sets are done by sending additional
2563 * values with a zero-length name...
2566 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2568 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2570 DEBUG_puts("1ippWriteIO: Could not write IPP "
2572 ipp_buffer_release(buffer
);
2579 *bufptr
++ = attr
->value_tag
;
2585 * An unknown value might some new value that a
2586 * vendor has come up with. It consists of a
2587 * 2-byte length and the bytes in the unknown
2591 n
= value
->unknown
.length
;
2593 if (n
> (IPP_BUF_SIZE
- 2))
2595 DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
2597 ipp_buffer_release(buffer
);
2601 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2603 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2605 DEBUG_puts("1ippWriteIO: Could not write IPP "
2607 ipp_buffer_release(buffer
);
2614 /* Length of unknown value */
2621 memcpy(bufptr
, value
->unknown
.data
, n
);
2629 * Write the data out...
2632 if (bufptr
> buffer
)
2634 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2636 DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
2637 ipp_buffer_release(buffer
);
2641 DEBUG_printf(("2ippWriteIO: wrote %d bytes",
2642 (int)(bufptr
- buffer
)));
2646 * If blocking is disabled, stop here...
2653 if (ipp
->current
== NULL
)
2656 * Done with all of the attributes; add the end-of-attributes
2657 * tag or end-collection attribute...
2662 buffer
[0] = IPP_TAG_END
;
2667 buffer
[0] = IPP_TAG_END_COLLECTION
;
2668 buffer
[1] = 0; /* empty name */
2670 buffer
[3] = 0; /* empty value */
2675 if ((*cb
)(dst
, buffer
, n
) < 0)
2677 DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
2678 ipp_buffer_release(buffer
);
2682 ipp
->state
= IPP_DATA
;
2690 break; /* anti-compiler-warning-code */
2693 ipp_buffer_release(buffer
);
2695 return (ipp
->state
);
2700 * '_ippAddAttr()' - Add a new attribute to the request.
2703 ipp_attribute_t
* /* O - New attribute */
2704 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2705 int num_values
) /* I - Number of values */
2707 ipp_attribute_t
*attr
; /* New attribute */
2710 DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp
, num_values
));
2712 if (!ipp
|| num_values
< 0)
2715 attr
= calloc(sizeof(ipp_attribute_t
) +
2716 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2720 attr
->num_values
= num_values
;
2722 if (ipp
->last
== NULL
)
2725 ipp
->last
->next
= attr
;
2730 DEBUG_printf(("5_ippAddAttr: Returning %p", attr
));
2737 * '_ippFreeAttr()' - Free an attribute.
2741 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2743 int i
; /* Looping var */
2744 ipp_value_t
*value
; /* Current value */
2747 DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr
));
2749 switch (attr
->value_tag
)
2753 case IPP_TAG_KEYWORD
:
2755 case IPP_TAG_URISCHEME
:
2756 case IPP_TAG_CHARSET
:
2757 case IPP_TAG_LANGUAGE
:
2758 case IPP_TAG_MIMETYPE
:
2759 for (i
= 0, value
= attr
->values
;
2760 i
< attr
->num_values
;
2762 _cupsStrFree(value
->string
.text
);
2765 case IPP_TAG_TEXTLANG
:
2766 case IPP_TAG_NAMELANG
:
2767 for (i
= 0, value
= attr
->values
;
2768 i
< attr
->num_values
;
2771 if (value
->string
.charset
&& i
== 0)
2772 _cupsStrFree(value
->string
.charset
);
2773 _cupsStrFree(value
->string
.text
);
2777 case IPP_TAG_INTEGER
:
2779 case IPP_TAG_BOOLEAN
:
2781 case IPP_TAG_RESOLUTION
:
2782 case IPP_TAG_RANGE
:
2785 case IPP_TAG_BEGIN_COLLECTION
:
2786 for (i
= 0, value
= attr
->values
;
2787 i
< attr
->num_values
;
2789 ippDelete(value
->collection
);
2792 case IPP_TAG_STRING
:
2793 for (i
= 0, value
= attr
->values
;
2794 i
< attr
->num_values
;
2796 free(value
->unknown
.data
);
2800 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2802 for (i
= 0, value
= attr
->values
;
2803 i
< attr
->num_values
;
2805 if (value
->unknown
.data
)
2806 free(value
->unknown
.data
);
2812 _cupsStrFree(attr
->name
);
2819 * 'ipp_buffer_get()' - Get a read/write buffer.
2822 static unsigned char * /* O - Buffer */
2823 ipp_buffer_get(void)
2825 _ipp_buffer_t
*buffer
; /* Current buffer */
2826 _cups_globals_t
*cg
= _cupsGlobals();
2830 for (buffer
= cg
->ipp_buffers
; buffer
; buffer
= buffer
->next
)
2837 if ((buffer
= malloc(sizeof(_ipp_buffer_t
))) == NULL
)
2841 buffer
->next
= cg
->ipp_buffers
;
2842 cg
->ipp_buffers
= buffer
;
2849 * 'ipp_buffer_release()' - Release a read/write buffer.
2853 ipp_buffer_release(unsigned char *b
) /* I - Buffer to release */
2855 ((_ipp_buffer_t
*)b
)->used
= 0;
2860 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2863 static size_t /* O - Size of IPP message */
2864 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2865 int collection
) /* I - 1 if a collection, 0 otherwise */
2867 int i
; /* Looping var */
2868 int bytes
; /* Number of bytes */
2869 ipp_attribute_t
*attr
; /* Current attribute */
2870 ipp_tag_t group
; /* Current group */
2871 ipp_value_t
*value
; /* Current value */
2878 * Start with 8 bytes for the IPP message header...
2881 bytes
= collection
? 0 : 8;
2884 * Then add the lengths of each attribute...
2887 group
= IPP_TAG_ZERO
;
2889 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2891 if (attr
->group_tag
!= group
&& !collection
)
2893 group
= attr
->group_tag
;
2894 if (group
== IPP_TAG_ZERO
)
2897 bytes
++; /* Group tag */
2903 DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2904 "bytes=%d", attr
->name
, attr
->num_values
, bytes
));
2906 bytes
+= (int)strlen(attr
->name
); /* Name */
2907 bytes
+= attr
->num_values
; /* Value tag for each value */
2908 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2909 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2912 bytes
+= 5; /* Add membername overhead */
2914 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2916 case IPP_TAG_INTEGER
:
2918 bytes
+= 4 * attr
->num_values
;
2921 case IPP_TAG_BOOLEAN
:
2922 bytes
+= attr
->num_values
;
2927 case IPP_TAG_KEYWORD
:
2929 case IPP_TAG_URISCHEME
:
2930 case IPP_TAG_CHARSET
:
2931 case IPP_TAG_LANGUAGE
:
2932 case IPP_TAG_MIMETYPE
:
2933 for (i
= 0, value
= attr
->values
;
2934 i
< attr
->num_values
;
2936 if (value
->string
.text
!= NULL
)
2937 bytes
+= (int)strlen(value
->string
.text
);
2941 bytes
+= 11 * attr
->num_values
;
2944 case IPP_TAG_RESOLUTION
:
2945 bytes
+= 9 * attr
->num_values
;
2948 case IPP_TAG_RANGE
:
2949 bytes
+= 8 * attr
->num_values
;
2952 case IPP_TAG_TEXTLANG
:
2953 case IPP_TAG_NAMELANG
:
2954 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2956 for (i
= 0, value
= attr
->values
;
2957 i
< attr
->num_values
;
2960 if (value
->string
.charset
!= NULL
)
2961 bytes
+= (int)strlen(value
->string
.charset
);
2963 if (value
->string
.text
!= NULL
)
2964 bytes
+= (int)strlen(value
->string
.text
);
2968 case IPP_TAG_BEGIN_COLLECTION
:
2969 for (i
= 0, value
= attr
->values
;
2970 i
< attr
->num_values
;
2972 bytes
+= (int)ipp_length(value
->collection
, 1);
2976 for (i
= 0, value
= attr
->values
;
2977 i
< attr
->num_values
;
2979 bytes
+= value
->unknown
.length
;
2985 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2986 * for the "end of collection" tag and return...
2994 DEBUG_printf(("8ipp_length: Returning %d bytes", bytes
));
3001 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
3004 static ssize_t
/* O - Number of bytes read */
3005 ipp_read_http(http_t
*http
, /* I - Client connection */
3006 ipp_uchar_t
*buffer
, /* O - Buffer for data */
3007 size_t length
) /* I - Total length */
3009 int tbytes
, /* Total bytes read */
3010 bytes
; /* Bytes read this pass */
3011 char len
[32]; /* Length string */
3014 DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
3015 http
, buffer
, (int)length
));
3018 * Loop until all bytes are read...
3021 for (tbytes
= 0, bytes
= 0;
3022 tbytes
< (int)length
;
3023 tbytes
+= bytes
, buffer
+= bytes
)
3025 DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes
,
3028 if (http
->state
== HTTP_WAITING
)
3031 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
3034 * Do "fast read" from HTTP buffer directly...
3037 if (http
->used
> (int)(length
- tbytes
))
3038 bytes
= (int)(length
- tbytes
);
3043 buffer
[0] = http
->buffer
[0];
3045 memcpy(buffer
, http
->buffer
, bytes
);
3047 http
->used
-= bytes
;
3048 http
->data_remaining
-= bytes
;
3050 if (http
->data_remaining
<= INT_MAX
)
3051 http
->_data_remaining
= (int)http
->data_remaining
;
3053 http
->_data_remaining
= INT_MAX
;
3056 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
3058 if (http
->data_remaining
== 0)
3060 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
3063 * Get the trailing CR LF after the chunk...
3066 if (!httpGets(len
, sizeof(len
), http
))
3070 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
3072 if (http
->state
== HTTP_POST_RECV
)
3075 http
->state
= HTTP_WAITING
;
3082 * Wait a maximum of 1 second for data...
3085 if (!http
->blocking
)
3088 * Wait up to 10 seconds for more data on non-blocking sockets...
3091 if (!httpWait(http
, 10000))
3102 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) < 0)
3107 if (errno
!= EAGAIN
&& errno
!= EINTR
)
3113 else if (bytes
== 0)
3119 * Return the number of bytes read...
3122 if (tbytes
== 0 && bytes
< 0)
3125 DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes
));
3132 * 'ipp_read_file()' - Read IPP data from a file.
3135 static ssize_t
/* O - Number of bytes read */
3136 ipp_read_file(int *fd
, /* I - File descriptor */
3137 ipp_uchar_t
*buffer
, /* O - Read buffer */
3138 size_t length
) /* I - Number of bytes to read */
3141 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
3143 return (read(*fd
, buffer
, length
));
3149 * 'ipp_write_file()' - Write IPP data to a file.
3152 static ssize_t
/* O - Number of bytes written */
3153 ipp_write_file(int *fd
, /* I - File descriptor */
3154 ipp_uchar_t
*buffer
, /* I - Data to write */
3155 size_t length
) /* I - Number of bytes to write */
3158 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
3160 return (write(*fd
, buffer
, length
));
3167 * The following symbol definitions are provided only for KDE
3168 * compatibility during the CUPS 1.2 testing period and will be
3169 * removed in a future release of CUPS. These are PRIVATE APIs
3170 * from CUPS 1.1.x that the KDE developers chose to use...
3173 ipp_attribute_t
* /* O - New attribute */
3174 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
3175 int num_values
) /* I - Number of values */
3177 return (_ippAddAttr(ipp
, num_values
));
3181 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
3185 #endif /* __linux */
3189 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".