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 DEBUG_printf(("1ippReadIO: bad name length %d!", n
));
1238 ipp_buffer_release(buffer
);
1242 DEBUG_printf(("2ippReadIO: name length=%d", n
));
1244 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1245 tag
!= IPP_TAG_END_COLLECTION
)
1248 * More values for current attribute...
1251 if (ipp
->current
== NULL
)
1253 DEBUG_puts("1ippReadIO: Attribute without name and no current");
1254 ipp_buffer_release(buffer
);
1258 attr
= ipp
->current
;
1259 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1262 * Make sure we aren't adding a new value of a different
1266 if (value_tag
== IPP_TAG_ZERO
)
1269 * Setting the value of a collection member...
1272 attr
->value_tag
= tag
;
1274 else if (value_tag
== IPP_TAG_TEXTLANG
||
1275 value_tag
== IPP_TAG_NAMELANG
||
1276 (value_tag
>= IPP_TAG_TEXT
&&
1277 value_tag
<= IPP_TAG_MIMETYPE
))
1280 * String values can sometimes come across in different
1281 * forms; accept sets of differing values...
1284 if (tag
!= IPP_TAG_TEXTLANG
&& tag
!= IPP_TAG_NAMELANG
&&
1285 (tag
< IPP_TAG_TEXT
|| tag
> IPP_TAG_MIMETYPE
) &&
1286 tag
!= IPP_TAG_NOVALUE
)
1288 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1289 value_tag
, ippTagString(value_tag
), tag
,
1290 ippTagString(tag
)));
1291 ipp_buffer_release(buffer
);
1295 else if (value_tag
!= tag
)
1297 DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
1298 value_tag
, ippTagString(value_tag
), tag
,
1299 ippTagString(tag
)));
1300 ipp_buffer_release(buffer
);
1305 * Finally, reallocate the attribute array as needed...
1308 if (attr
->num_values
== 1 ||
1309 (attr
->num_values
> 0 &&
1310 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1312 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1315 DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
1316 attr
->num_values
+ IPP_MAX_VALUES
));
1319 * Reallocate memory...
1322 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1323 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1324 sizeof(ipp_value_t
))) == NULL
)
1326 DEBUG_puts("1ippReadIO: Unable to resize attribute");
1327 ipp_buffer_release(buffer
);
1334 * Reset pointers in the list...
1338 ipp
->prev
->next
= temp
;
1342 attr
= ipp
->current
= ipp
->last
= temp
;
1346 else if (tag
== IPP_TAG_MEMBERNAME
)
1349 * Name must be length 0!
1354 DEBUG_puts("1ippReadIO: member name not empty!");
1355 ipp_buffer_release(buffer
);
1360 ipp
->prev
= ipp
->current
;
1362 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1364 DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
1365 "ipp->prev=%p", ipp
->current
, ipp
->prev
));
1367 attr
->group_tag
= ipp
->curtag
;
1368 attr
->value_tag
= IPP_TAG_ZERO
;
1369 attr
->num_values
= 0;
1371 else if (tag
!= IPP_TAG_END_COLLECTION
)
1374 * New attribute; read the name and add it...
1377 if ((*cb
)(src
, buffer
, n
) < n
)
1379 DEBUG_puts("1ippReadIO: unable to read name!");
1380 ipp_buffer_release(buffer
);
1387 ipp
->prev
= ipp
->current
;
1389 if ((attr
= ipp
->current
= _ippAddAttr(ipp
, 1)) == NULL
)
1391 DEBUG_puts("1ippReadIO: unable to allocate attribute!");
1392 ipp_buffer_release(buffer
);
1396 DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
1397 "ipp->prev=%p", buffer
, ipp
->current
, ipp
->prev
));
1399 attr
->group_tag
= ipp
->curtag
;
1400 attr
->value_tag
= tag
;
1401 attr
->name
= _cupsStrAlloc((char *)buffer
);
1402 attr
->num_values
= 0;
1407 if (tag
!= IPP_TAG_END_COLLECTION
)
1408 value
= attr
->values
+ attr
->num_values
;
1412 if ((*cb
)(src
, buffer
, 2) < 2)
1414 DEBUG_puts("1ippReadIO: unable to read value length!");
1415 ipp_buffer_release(buffer
);
1419 n
= (buffer
[0] << 8) | buffer
[1];
1420 DEBUG_printf(("2ippReadIO: value length=%d", n
));
1424 case IPP_TAG_INTEGER
:
1428 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1429 ipp_buffer_release(buffer
);
1433 if ((*cb
)(src
, buffer
, 4) < 4)
1435 DEBUG_puts("1ippReadIO: Unable to read integer value!");
1436 ipp_buffer_release(buffer
);
1440 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1446 case IPP_TAG_BOOLEAN
:
1449 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1450 ipp_buffer_release(buffer
);
1454 if ((*cb
)(src
, buffer
, 1) < 1)
1456 DEBUG_puts("1ippReadIO: Unable to read boolean value!");
1457 ipp_buffer_release(buffer
);
1461 value
->boolean
= buffer
[0];
1464 case IPP_TAG_NOVALUE
:
1465 case IPP_TAG_NOTSETTABLE
:
1466 case IPP_TAG_DELETEATTR
:
1467 case IPP_TAG_ADMINDEFINE
:
1469 * These value types are not supposed to have values, however
1470 * some vendors (Brother) do not implement IPP correctly and so
1471 * we need to map non-empty values to text...
1474 if (attr
->value_tag
== tag
)
1479 attr
->value_tag
= IPP_TAG_TEXT
;
1484 case IPP_TAG_KEYWORD
:
1486 case IPP_TAG_URISCHEME
:
1487 case IPP_TAG_CHARSET
:
1488 case IPP_TAG_LANGUAGE
:
1489 case IPP_TAG_MIMETYPE
:
1490 if (n
>= IPP_BUF_SIZE
)
1492 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1493 ipp_buffer_release(buffer
);
1497 if ((*cb
)(src
, buffer
, n
) < n
)
1499 DEBUG_puts("1ippReadIO: unable to read name!");
1500 ipp_buffer_release(buffer
);
1505 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1506 DEBUG_printf(("2ippReadIO: value=\"%s\"", value
->string
.text
));
1512 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1513 ipp_buffer_release(buffer
);
1517 if ((*cb
)(src
, value
->date
, 11) < 11)
1519 DEBUG_puts("1ippReadIO: Unable to read date value!");
1520 ipp_buffer_release(buffer
);
1525 case IPP_TAG_RESOLUTION
:
1528 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1529 ipp_buffer_release(buffer
);
1533 if ((*cb
)(src
, buffer
, 9) < 9)
1535 DEBUG_puts("1ippReadIO: Unable to read resolution value!");
1536 ipp_buffer_release(buffer
);
1540 value
->resolution
.xres
=
1541 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1543 value
->resolution
.yres
=
1544 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1546 value
->resolution
.units
=
1547 (ipp_res_t
)buffer
[8];
1550 case IPP_TAG_RANGE
:
1553 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1554 ipp_buffer_release(buffer
);
1558 if ((*cb
)(src
, buffer
, 8) < 8)
1560 DEBUG_puts("1ippReadIO: Unable to read range value!");
1561 ipp_buffer_release(buffer
);
1565 value
->range
.lower
=
1566 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1568 value
->range
.upper
=
1569 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1573 case IPP_TAG_TEXTLANG
:
1574 case IPP_TAG_NAMELANG
:
1575 if (n
>= IPP_BUF_SIZE
|| n
< 4)
1577 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1578 ipp_buffer_release(buffer
);
1582 if ((*cb
)(src
, buffer
, n
) < n
)
1584 DEBUG_puts("1ippReadIO: Unable to read string w/language "
1586 ipp_buffer_release(buffer
);
1593 * text-with-language and name-with-language are composite
1602 n
= (bufptr
[0] << 8) | bufptr
[1];
1604 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
) ||
1605 n
>= sizeof(string
))
1607 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1608 ipp_buffer_release(buffer
);
1612 memcpy(string
, bufptr
+ 2, n
);
1615 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1618 n
= (bufptr
[0] << 8) | bufptr
[1];
1620 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
))
1622 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1623 ipp_buffer_release(buffer
);
1627 bufptr
[2 + n
] = '\0';
1628 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1631 case IPP_TAG_BEGIN_COLLECTION
:
1633 * Oh, boy, here comes a collection value, so read it...
1636 value
->collection
= ippNew();
1640 DEBUG_puts("1ippReadIO: begCollection tag with value length "
1642 ipp_buffer_release(buffer
);
1646 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1648 DEBUG_puts("1ippReadIO: Unable to read collection value!");
1649 ipp_buffer_release(buffer
);
1654 case IPP_TAG_END_COLLECTION
:
1655 ipp_buffer_release(buffer
);
1659 DEBUG_puts("1ippReadIO: endCollection tag with value length "
1664 DEBUG_puts("1ippReadIO: endCollection tag...");
1665 return (ipp
->state
= IPP_DATA
);
1667 case IPP_TAG_MEMBERNAME
:
1669 * The value the name of the member in the collection, which
1670 * we need to carry over...
1673 if (n
>= IPP_BUF_SIZE
)
1675 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1676 ipp_buffer_release(buffer
);
1680 if ((*cb
)(src
, buffer
, n
) < n
)
1682 DEBUG_puts("1ippReadIO: Unable to read member name value!");
1683 ipp_buffer_release(buffer
);
1688 attr
->name
= _cupsStrAlloc((char *)buffer
);
1691 * Since collection members are encoded differently than
1692 * regular attributes, make sure we don't start with an
1696 attr
->num_values
--;
1698 DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr
->name
));
1701 default : /* Other unsupported values */
1702 if (n
> IPP_MAX_LENGTH
)
1704 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1705 ipp_buffer_release(buffer
);
1711 DEBUG_puts("1ippReadIO: NULL value!");
1712 ipp_buffer_release(buffer
);
1716 value
->unknown
.length
= n
;
1719 if ((value
->unknown
.data
= malloc(n
)) == NULL
)
1721 DEBUG_puts("1ippReadIO: Unable to allocate value");
1722 ipp_buffer_release(buffer
);
1726 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1728 DEBUG_puts("1ippReadIO: Unable to read unsupported value!");
1729 ipp_buffer_release(buffer
);
1734 value
->unknown
.data
= NULL
;
1738 attr
->num_values
++;
1741 * If blocking is disabled, stop here...
1753 break; /* anti-compiler-warning-code */
1756 DEBUG_printf(("1ippReadIO: returning ipp->state=%d!", ipp
->state
));
1757 ipp_buffer_release(buffer
);
1759 return (ipp
->state
);
1764 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1767 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1768 ippTimeToDate(time_t t
) /* I - UNIX time value */
1770 struct tm
*unixdate
; /* UNIX unixdate/time info */
1771 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1772 /* RFC-1903 date/time data */
1776 * RFC-1903 date/time format is:
1778 * Byte(s) Description
1779 * ------- -----------
1780 * 0-1 Year (0 to 65535)
1784 * 5 Minutes (0 to 59)
1785 * 6 Seconds (0 to 60, 60 = "leap second")
1786 * 7 Deciseconds (0 to 9)
1788 * 9 UTC hours (0 to 11)
1789 * 10 UTC minutes (0 to 59)
1792 unixdate
= gmtime(&t
);
1793 unixdate
->tm_year
+= 1900;
1795 date
[0] = unixdate
->tm_year
>> 8;
1796 date
[1] = unixdate
->tm_year
;
1797 date
[2] = unixdate
->tm_mon
+ 1;
1798 date
[3] = unixdate
->tm_mday
;
1799 date
[4] = unixdate
->tm_hour
;
1800 date
[5] = unixdate
->tm_min
;
1801 date
[6] = unixdate
->tm_sec
;
1812 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1815 ipp_state_t
/* O - Current state */
1816 ippWrite(http_t
*http
, /* I - HTTP connection */
1817 ipp_t
*ipp
) /* I - IPP data */
1819 DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http
, ipp
));
1824 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
, http
->blocking
, NULL
, ipp
));
1829 * 'ippWriteFile()' - Write data for an IPP message to a file.
1831 * @since CUPS 1.1.19/Mac OS X 10.3@
1834 ipp_state_t
/* O - Current state */
1835 ippWriteFile(int fd
, /* I - HTTP data */
1836 ipp_t
*ipp
) /* I - IPP data */
1838 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd
, ipp
));
1840 ipp
->state
= IPP_IDLE
;
1842 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1847 * 'ippWriteIO()' - Write data for an IPP message.
1849 * @since CUPS 1.2/Mac OS X 10.5@
1852 ipp_state_t
/* O - Current state */
1853 ippWriteIO(void *dst
, /* I - Destination */
1854 ipp_iocb_t cb
, /* I - Write callback function */
1855 int blocking
, /* I - Use blocking IO? */
1856 ipp_t
*parent
, /* I - Parent IPP message */
1857 ipp_t
*ipp
) /* I - IPP data */
1859 int i
; /* Looping var */
1860 int n
; /* Length of data */
1861 unsigned char *buffer
, /* Data buffer */
1862 *bufptr
; /* Pointer into buffer */
1863 ipp_attribute_t
*attr
; /* Current attribute */
1864 ipp_value_t
*value
; /* Current value */
1867 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1868 dst
, cb
, blocking
, parent
, ipp
));
1873 if ((buffer
= ipp_buffer_get()) == NULL
)
1875 DEBUG_puts("1ippWriteIO: Unable to get write buffer");
1882 ipp
->state
++; /* Avoid common problem... */
1888 * Send the request header:
1891 * Operation/Status Code = 2 bytes
1892 * Request ID = 4 bytes
1898 *bufptr
++ = ipp
->request
.any
.version
[0];
1899 *bufptr
++ = ipp
->request
.any
.version
[1];
1900 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1901 *bufptr
++ = ipp
->request
.any
.op_status
;
1902 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1903 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1904 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1905 *bufptr
++ = ipp
->request
.any
.request_id
;
1907 DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer
[0], buffer
[1]));
1908 DEBUG_printf(("2ippWriteIO: op_status=%04x",
1909 ipp
->request
.any
.op_status
));
1910 DEBUG_printf(("2ippWriteIO: request_id=%d",
1911 ipp
->request
.any
.request_id
));
1913 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1915 DEBUG_puts("1ippWriteIO: Could not write IPP header...");
1916 ipp_buffer_release(buffer
);
1922 * Reset the state engine to point to the first attribute
1923 * in the request/response, with no current group.
1926 ipp
->state
= IPP_ATTRIBUTE
;
1927 ipp
->current
= ipp
->attrs
;
1928 ipp
->curtag
= IPP_TAG_ZERO
;
1930 DEBUG_printf(("1ippWriteIO: ipp->current=%p", ipp
->current
));
1933 * If blocking is disabled, stop here...
1939 case IPP_ATTRIBUTE
:
1940 while (ipp
->current
!= NULL
)
1943 * Write this attribute...
1947 attr
= ipp
->current
;
1949 ipp
->current
= ipp
->current
->next
;
1953 if (ipp
->curtag
!= attr
->group_tag
)
1956 * Send a group tag byte...
1959 ipp
->curtag
= attr
->group_tag
;
1961 if (attr
->group_tag
== IPP_TAG_ZERO
)
1964 DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
1965 attr
->group_tag
, ippTagString(attr
->group_tag
)));
1966 *bufptr
++ = attr
->group_tag
;
1968 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1972 DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr
->name
,
1973 attr
->num_values
> 1 ? "1setOf " : "",
1974 ippTagString(attr
->value_tag
)));
1977 * Write the attribute tag and name. The current implementation
1978 * does not support the extension value tags above 0x7f, so all
1979 * value tags are 1 byte.
1981 * The attribute name length does not include the trailing nul
1982 * character in the source string.
1984 * Collection values (parent != NULL) are written differently...
1990 * Get the length of the attribute name, and make sure it won't
1991 * overflow the buffer...
1994 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 4))
1996 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
1997 ipp_buffer_release(buffer
);
2002 * Write the value tag, name length, and name string...
2005 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2006 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2007 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2010 *bufptr
++ = attr
->value_tag
;
2013 memcpy(bufptr
, attr
->name
, n
);
2019 * Get the length of the attribute name, and make sure it won't
2020 * overflow the buffer...
2023 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 7))
2025 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
2026 ipp_buffer_release(buffer
);
2031 * Write the member name tag, name length, name string, value tag,
2032 * and empty name for the collection member attribute...
2035 DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
2036 IPP_TAG_MEMBERNAME
));
2037 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2039 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2040 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2041 DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
2043 *bufptr
++ = IPP_TAG_MEMBERNAME
;
2048 memcpy(bufptr
, attr
->name
, n
);
2051 *bufptr
++ = attr
->value_tag
;
2057 * Now write the attribute value(s)...
2060 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2062 case IPP_TAG_INTEGER
:
2064 for (i
= 0, value
= attr
->values
;
2065 i
< attr
->num_values
;
2068 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 9)
2070 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2072 DEBUG_puts("1ippWriteIO: Could not write IPP "
2074 ipp_buffer_release(buffer
);
2084 * Arrays and sets are done by sending additional
2085 * values with a zero-length name...
2088 *bufptr
++ = attr
->value_tag
;
2094 * Integers and enumerations are both 4-byte signed
2095 * (twos-complement) values.
2097 * Put the 2-byte length and 4-byte value into the buffer...
2102 *bufptr
++ = value
->integer
>> 24;
2103 *bufptr
++ = value
->integer
>> 16;
2104 *bufptr
++ = value
->integer
>> 8;
2105 *bufptr
++ = value
->integer
;
2109 case IPP_TAG_BOOLEAN
:
2110 for (i
= 0, value
= attr
->values
;
2111 i
< attr
->num_values
;
2114 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 6)
2116 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2118 DEBUG_puts("1ippWriteIO: Could not write IPP "
2120 ipp_buffer_release(buffer
);
2130 * Arrays and sets are done by sending additional
2131 * values with a zero-length name...
2134 *bufptr
++ = attr
->value_tag
;
2140 * Boolean values are 1-byte; 0 = false, 1 = true.
2142 * Put the 2-byte length and 1-byte value into the buffer...
2147 *bufptr
++ = value
->boolean
;
2153 case IPP_TAG_KEYWORD
:
2155 case IPP_TAG_URISCHEME
:
2156 case IPP_TAG_CHARSET
:
2157 case IPP_TAG_LANGUAGE
:
2158 case IPP_TAG_MIMETYPE
:
2159 for (i
= 0, value
= attr
->values
;
2160 i
< attr
->num_values
;
2166 * Arrays and sets are done by sending additional
2167 * values with a zero-length name...
2170 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2172 ippTagString(attr
->value_tag
)));
2173 DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
2175 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2177 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2179 DEBUG_puts("1ippWriteIO: Could not write IPP "
2181 ipp_buffer_release(buffer
);
2188 *bufptr
++ = attr
->value_tag
;
2193 if (value
->string
.text
!= NULL
)
2194 n
= (int)strlen(value
->string
.text
);
2198 if (n
> (IPP_BUF_SIZE
- 2))
2200 DEBUG_printf(("1ippWriteIO: String too long (%d)", n
));
2201 ipp_buffer_release(buffer
);
2205 DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n
,
2206 value
->string
.text
));
2208 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2210 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2212 DEBUG_puts("1ippWriteIO: Could not write IPP "
2214 ipp_buffer_release(buffer
);
2222 * All simple strings consist of the 2-byte length and
2223 * character data without the trailing nul normally found
2224 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2225 * bytes since the 2-byte length is a signed (twos-complement)
2228 * Put the 2-byte length and string characters in the buffer.
2236 memcpy(bufptr
, value
->string
.text
, n
);
2243 for (i
= 0, value
= attr
->values
;
2244 i
< attr
->num_values
;
2247 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 16)
2249 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2251 DEBUG_puts("1ippWriteIO: Could not write IPP "
2253 ipp_buffer_release(buffer
);
2263 * Arrays and sets are done by sending additional
2264 * values with a zero-length name...
2267 *bufptr
++ = attr
->value_tag
;
2273 * Date values consist of a 2-byte length and an
2274 * 11-byte date/time structure defined by RFC 1903.
2276 * Put the 2-byte length and 11-byte date/time
2277 * structure in the buffer.
2282 memcpy(bufptr
, value
->date
, 11);
2287 case IPP_TAG_RESOLUTION
:
2288 for (i
= 0, value
= attr
->values
;
2289 i
< attr
->num_values
;
2292 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 14)
2294 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2296 DEBUG_puts("1ippWriteIO: Could not write IPP "
2298 ipp_buffer_release(buffer
);
2308 * Arrays and sets are done by sending additional
2309 * values with a zero-length name...
2312 *bufptr
++ = attr
->value_tag
;
2318 * Resolution values consist of a 2-byte length,
2319 * 4-byte horizontal resolution value, 4-byte vertical
2320 * resolution value, and a 1-byte units value.
2322 * Put the 2-byte length and resolution value data
2328 *bufptr
++ = value
->resolution
.xres
>> 24;
2329 *bufptr
++ = value
->resolution
.xres
>> 16;
2330 *bufptr
++ = value
->resolution
.xres
>> 8;
2331 *bufptr
++ = value
->resolution
.xres
;
2332 *bufptr
++ = value
->resolution
.yres
>> 24;
2333 *bufptr
++ = value
->resolution
.yres
>> 16;
2334 *bufptr
++ = value
->resolution
.yres
>> 8;
2335 *bufptr
++ = value
->resolution
.yres
;
2336 *bufptr
++ = value
->resolution
.units
;
2340 case IPP_TAG_RANGE
:
2341 for (i
= 0, value
= attr
->values
;
2342 i
< attr
->num_values
;
2345 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 13)
2347 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2349 DEBUG_puts("1ippWriteIO: Could not write IPP "
2351 ipp_buffer_release(buffer
);
2361 * Arrays and sets are done by sending additional
2362 * values with a zero-length name...
2365 *bufptr
++ = attr
->value_tag
;
2371 * Range values consist of a 2-byte length,
2372 * 4-byte lower value, and 4-byte upper value.
2374 * Put the 2-byte length and range value data
2380 *bufptr
++ = value
->range
.lower
>> 24;
2381 *bufptr
++ = value
->range
.lower
>> 16;
2382 *bufptr
++ = value
->range
.lower
>> 8;
2383 *bufptr
++ = value
->range
.lower
;
2384 *bufptr
++ = value
->range
.upper
>> 24;
2385 *bufptr
++ = value
->range
.upper
>> 16;
2386 *bufptr
++ = value
->range
.upper
>> 8;
2387 *bufptr
++ = value
->range
.upper
;
2391 case IPP_TAG_TEXTLANG
:
2392 case IPP_TAG_NAMELANG
:
2393 for (i
= 0, value
= attr
->values
;
2394 i
< attr
->num_values
;
2400 * Arrays and sets are done by sending additional
2401 * values with a zero-length name...
2404 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2406 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2408 DEBUG_puts("1ippWriteIO: Could not write IPP "
2410 ipp_buffer_release(buffer
);
2417 *bufptr
++ = attr
->value_tag
;
2423 * textWithLanguage and nameWithLanguage values consist
2424 * of a 2-byte length for both strings and their
2425 * individual lengths, a 2-byte length for the
2426 * character string, the character string without the
2427 * trailing nul, a 2-byte length for the character
2428 * set string, and the character set string without
2434 if (value
->string
.charset
!= NULL
)
2435 n
+= (int)strlen(value
->string
.charset
);
2437 if (value
->string
.text
!= NULL
)
2438 n
+= (int)strlen(value
->string
.text
);
2440 if (n
> (IPP_BUF_SIZE
- 2))
2442 DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
2443 "too long (%d)", n
));
2444 ipp_buffer_release(buffer
);
2448 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2450 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2452 DEBUG_puts("1ippWriteIO: Could not write IPP "
2454 ipp_buffer_release(buffer
);
2461 /* Length of entire value */
2465 /* Length of charset */
2466 if (value
->string
.charset
!= NULL
)
2467 n
= (int)strlen(value
->string
.charset
);
2477 memcpy(bufptr
, value
->string
.charset
, n
);
2481 /* Length of text */
2482 if (value
->string
.text
!= NULL
)
2483 n
= (int)strlen(value
->string
.text
);
2493 memcpy(bufptr
, value
->string
.text
, n
);
2499 case IPP_TAG_BEGIN_COLLECTION
:
2500 for (i
= 0, value
= attr
->values
;
2501 i
< attr
->num_values
;
2505 * Collections are written with the begin-collection
2506 * tag first with a value of 0 length, followed by the
2507 * attributes in the collection, then the end-collection
2511 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 5)
2513 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2515 DEBUG_puts("1ippWriteIO: Could not write IPP "
2517 ipp_buffer_release(buffer
);
2527 * Arrays and sets are done by sending additional
2528 * values with a zero-length name...
2531 *bufptr
++ = attr
->value_tag
;
2537 * Write a data length of 0 and flush the buffer...
2543 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2545 DEBUG_puts("1ippWriteIO: Could not write IPP "
2547 ipp_buffer_release(buffer
);
2554 * Then write the collection attribute...
2557 value
->collection
->state
= IPP_IDLE
;
2559 if (ippWriteIO(dst
, cb
, 1, ipp
,
2560 value
->collection
) == IPP_ERROR
)
2562 DEBUG_puts("1ippWriteIO: Unable to write collection value");
2563 ipp_buffer_release(buffer
);
2570 for (i
= 0, value
= attr
->values
;
2571 i
< attr
->num_values
;
2577 * Arrays and sets are done by sending additional
2578 * values with a zero-length name...
2581 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2583 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2585 DEBUG_puts("1ippWriteIO: Could not write IPP "
2587 ipp_buffer_release(buffer
);
2594 *bufptr
++ = attr
->value_tag
;
2600 * An unknown value might some new value that a
2601 * vendor has come up with. It consists of a
2602 * 2-byte length and the bytes in the unknown
2606 n
= value
->unknown
.length
;
2608 if (n
> (IPP_BUF_SIZE
- 2))
2610 DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
2612 ipp_buffer_release(buffer
);
2616 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2618 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2620 DEBUG_puts("1ippWriteIO: Could not write IPP "
2622 ipp_buffer_release(buffer
);
2629 /* Length of unknown value */
2636 memcpy(bufptr
, value
->unknown
.data
, n
);
2644 * Write the data out...
2647 if (bufptr
> buffer
)
2649 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2651 DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
2652 ipp_buffer_release(buffer
);
2656 DEBUG_printf(("2ippWriteIO: wrote %d bytes",
2657 (int)(bufptr
- buffer
)));
2661 * If blocking is disabled, stop here...
2668 if (ipp
->current
== NULL
)
2671 * Done with all of the attributes; add the end-of-attributes
2672 * tag or end-collection attribute...
2677 buffer
[0] = IPP_TAG_END
;
2682 buffer
[0] = IPP_TAG_END_COLLECTION
;
2683 buffer
[1] = 0; /* empty name */
2685 buffer
[3] = 0; /* empty value */
2690 if ((*cb
)(dst
, buffer
, n
) < 0)
2692 DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
2693 ipp_buffer_release(buffer
);
2697 ipp
->state
= IPP_DATA
;
2705 break; /* anti-compiler-warning-code */
2708 ipp_buffer_release(buffer
);
2710 return (ipp
->state
);
2715 * '_ippAddAttr()' - Add a new attribute to the request.
2718 ipp_attribute_t
* /* O - New attribute */
2719 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2720 int num_values
) /* I - Number of values */
2722 ipp_attribute_t
*attr
; /* New attribute */
2725 DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp
, num_values
));
2727 if (!ipp
|| num_values
< 0)
2730 attr
= calloc(sizeof(ipp_attribute_t
) +
2731 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2735 attr
->num_values
= num_values
;
2737 if (ipp
->last
== NULL
)
2740 ipp
->last
->next
= attr
;
2745 DEBUG_printf(("5_ippAddAttr: Returning %p", attr
));
2752 * '_ippFreeAttr()' - Free an attribute.
2756 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2758 int i
; /* Looping var */
2759 ipp_value_t
*value
; /* Current value */
2762 DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr
));
2764 switch (attr
->value_tag
)
2768 case IPP_TAG_RESERVED_STRING
:
2769 case IPP_TAG_KEYWORD
:
2771 case IPP_TAG_URISCHEME
:
2772 case IPP_TAG_CHARSET
:
2773 case IPP_TAG_LANGUAGE
:
2774 case IPP_TAG_MIMETYPE
:
2775 for (i
= 0, value
= attr
->values
;
2776 i
< attr
->num_values
;
2778 _cupsStrFree(value
->string
.text
);
2781 case IPP_TAG_TEXTLANG
:
2782 case IPP_TAG_NAMELANG
:
2783 for (i
= 0, value
= attr
->values
;
2784 i
< attr
->num_values
;
2787 if (value
->string
.charset
&& i
== 0)
2788 _cupsStrFree(value
->string
.charset
);
2789 _cupsStrFree(value
->string
.text
);
2793 case IPP_TAG_INTEGER
:
2795 case IPP_TAG_BOOLEAN
:
2797 case IPP_TAG_RESOLUTION
:
2798 case IPP_TAG_RANGE
:
2801 case IPP_TAG_BEGIN_COLLECTION
:
2802 for (i
= 0, value
= attr
->values
;
2803 i
< attr
->num_values
;
2805 ippDelete(value
->collection
);
2808 case IPP_TAG_STRING
:
2809 for (i
= 0, value
= attr
->values
;
2810 i
< attr
->num_values
;
2812 free(value
->unknown
.data
);
2816 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2818 for (i
= 0, value
= attr
->values
;
2819 i
< attr
->num_values
;
2821 if (value
->unknown
.data
)
2822 free(value
->unknown
.data
);
2828 _cupsStrFree(attr
->name
);
2835 * 'ipp_buffer_get()' - Get a read/write buffer.
2838 static unsigned char * /* O - Buffer */
2839 ipp_buffer_get(void)
2841 _ipp_buffer_t
*buffer
; /* Current buffer */
2842 _cups_globals_t
*cg
= _cupsGlobals();
2846 for (buffer
= cg
->ipp_buffers
; buffer
; buffer
= buffer
->next
)
2853 if ((buffer
= malloc(sizeof(_ipp_buffer_t
))) == NULL
)
2857 buffer
->next
= cg
->ipp_buffers
;
2858 cg
->ipp_buffers
= buffer
;
2865 * 'ipp_buffer_release()' - Release a read/write buffer.
2869 ipp_buffer_release(unsigned char *b
) /* I - Buffer to release */
2871 ((_ipp_buffer_t
*)b
)->used
= 0;
2876 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2879 static size_t /* O - Size of IPP message */
2880 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2881 int collection
) /* I - 1 if a collection, 0 otherwise */
2883 int i
; /* Looping var */
2884 int bytes
; /* Number of bytes */
2885 ipp_attribute_t
*attr
; /* Current attribute */
2886 ipp_tag_t group
; /* Current group */
2887 ipp_value_t
*value
; /* Current value */
2894 * Start with 8 bytes for the IPP message header...
2897 bytes
= collection
? 0 : 8;
2900 * Then add the lengths of each attribute...
2903 group
= IPP_TAG_ZERO
;
2905 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2907 if (attr
->group_tag
!= group
&& !collection
)
2909 group
= attr
->group_tag
;
2910 if (group
== IPP_TAG_ZERO
)
2913 bytes
++; /* Group tag */
2919 DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2920 "bytes=%d", attr
->name
, attr
->num_values
, bytes
));
2922 bytes
+= (int)strlen(attr
->name
); /* Name */
2923 bytes
+= attr
->num_values
; /* Value tag for each value */
2924 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2925 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2928 bytes
+= 5; /* Add membername overhead */
2930 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2932 case IPP_TAG_INTEGER
:
2934 bytes
+= 4 * attr
->num_values
;
2937 case IPP_TAG_BOOLEAN
:
2938 bytes
+= attr
->num_values
;
2943 case IPP_TAG_KEYWORD
:
2945 case IPP_TAG_URISCHEME
:
2946 case IPP_TAG_CHARSET
:
2947 case IPP_TAG_LANGUAGE
:
2948 case IPP_TAG_MIMETYPE
:
2949 for (i
= 0, value
= attr
->values
;
2950 i
< attr
->num_values
;
2952 if (value
->string
.text
!= NULL
)
2953 bytes
+= (int)strlen(value
->string
.text
);
2957 bytes
+= 11 * attr
->num_values
;
2960 case IPP_TAG_RESOLUTION
:
2961 bytes
+= 9 * attr
->num_values
;
2964 case IPP_TAG_RANGE
:
2965 bytes
+= 8 * attr
->num_values
;
2968 case IPP_TAG_TEXTLANG
:
2969 case IPP_TAG_NAMELANG
:
2970 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2972 for (i
= 0, value
= attr
->values
;
2973 i
< attr
->num_values
;
2976 if (value
->string
.charset
!= NULL
)
2977 bytes
+= (int)strlen(value
->string
.charset
);
2979 if (value
->string
.text
!= NULL
)
2980 bytes
+= (int)strlen(value
->string
.text
);
2984 case IPP_TAG_BEGIN_COLLECTION
:
2985 for (i
= 0, value
= attr
->values
;
2986 i
< attr
->num_values
;
2988 bytes
+= (int)ipp_length(value
->collection
, 1);
2992 for (i
= 0, value
= attr
->values
;
2993 i
< attr
->num_values
;
2995 bytes
+= value
->unknown
.length
;
3001 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
3002 * for the "end of collection" tag and return...
3010 DEBUG_printf(("8ipp_length: Returning %d bytes", bytes
));
3017 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
3020 static ssize_t
/* O - Number of bytes read */
3021 ipp_read_http(http_t
*http
, /* I - Client connection */
3022 ipp_uchar_t
*buffer
, /* O - Buffer for data */
3023 size_t length
) /* I - Total length */
3025 int tbytes
, /* Total bytes read */
3026 bytes
; /* Bytes read this pass */
3027 char len
[32]; /* Length string */
3030 DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
3031 http
, buffer
, (int)length
));
3034 * Loop until all bytes are read...
3037 for (tbytes
= 0, bytes
= 0;
3038 tbytes
< (int)length
;
3039 tbytes
+= bytes
, buffer
+= bytes
)
3041 DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes
,
3044 if (http
->state
== HTTP_WAITING
)
3047 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
3050 * Do "fast read" from HTTP buffer directly...
3053 if (http
->used
> (int)(length
- tbytes
))
3054 bytes
= (int)(length
- tbytes
);
3059 buffer
[0] = http
->buffer
[0];
3061 memcpy(buffer
, http
->buffer
, bytes
);
3063 http
->used
-= bytes
;
3064 http
->data_remaining
-= bytes
;
3066 if (http
->data_remaining
<= INT_MAX
)
3067 http
->_data_remaining
= (int)http
->data_remaining
;
3069 http
->_data_remaining
= INT_MAX
;
3072 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
3074 if (http
->data_remaining
== 0)
3076 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
3079 * Get the trailing CR LF after the chunk...
3082 if (!httpGets(len
, sizeof(len
), http
))
3086 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
3088 if (http
->state
== HTTP_POST_RECV
)
3091 http
->state
= HTTP_WAITING
;
3098 * Wait a maximum of 1 second for data...
3101 if (!http
->blocking
)
3104 * Wait up to 10 seconds for more data on non-blocking sockets...
3107 if (!httpWait(http
, 10000))
3118 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) < 0)
3123 if (errno
!= EAGAIN
&& errno
!= EINTR
)
3129 else if (bytes
== 0)
3135 * Return the number of bytes read...
3138 if (tbytes
== 0 && bytes
< 0)
3141 DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes
));
3148 * 'ipp_read_file()' - Read IPP data from a file.
3151 static ssize_t
/* O - Number of bytes read */
3152 ipp_read_file(int *fd
, /* I - File descriptor */
3153 ipp_uchar_t
*buffer
, /* O - Read buffer */
3154 size_t length
) /* I - Number of bytes to read */
3157 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
3159 return (read(*fd
, buffer
, length
));
3165 * 'ipp_write_file()' - Write IPP data to a file.
3168 static ssize_t
/* O - Number of bytes written */
3169 ipp_write_file(int *fd
, /* I - File descriptor */
3170 ipp_uchar_t
*buffer
, /* I - Data to write */
3171 size_t length
) /* I - Number of bytes to write */
3174 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
3176 return (write(*fd
, buffer
, length
));
3183 * The following symbol definitions are provided only for KDE
3184 * compatibility during the CUPS 1.2 testing period and will be
3185 * removed in a future release of CUPS. These are PRIVATE APIs
3186 * from CUPS 1.1.x that the KDE developers chose to use...
3189 ipp_attribute_t
* /* O - New attribute */
3190 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
3191 int num_values
) /* I - Number of values */
3193 return (_ippAddAttr(ipp
, num_values
));
3197 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
3201 #endif /* __linux */
3205 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".