2 * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
4 * Internet Printing Protocol support functions for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 2007-2009 by Apple Inc.
8 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
16 * This file is subject to the Apple OS-Developed Software exception.
20 * ippAddBoolean() - Add a boolean attribute to an IPP message.
21 * ippAddBooleans() - Add an array of boolean values.
22 * ippAddDate() - Add a date attribute to an IPP message.
23 * ippAddInteger() - Add a integer attribute to an IPP message.
24 * ippAddIntegers() - Add an array of integer values.
25 * ippAddOctetString() - Add an octetString value to an IPP message.
26 * ippAddString() - Add a language-encoded string to an IPP message.
27 * ippAddStrings() - Add language-encoded strings to an IPP message.
28 * ippAddRange() - Add a range of values to an IPP message.
29 * ippAddRanges() - Add ranges of values to an IPP message.
30 * ippAddResolution() - Add a resolution value to an IPP message.
31 * ippAddResolutions() - Add resolution values to an IPP message.
32 * ippAddSeparator() - Add a group separator to an IPP message.
33 * ippDateToTime() - Convert from RFC 1903 Date/Time format to
34 * UNIX time in seconds.
35 * ippDelete() - Delete an IPP message.
36 * ippDeleteAttribute() - Delete a single attribute in an IPP message.
37 * ippFindAttribute() - Find a named attribute in a request...
38 * ippFindNextAttribute() - Find the next named attribute in a request...
39 * ippLength() - Compute the length of an IPP message.
40 * ippNew() - Allocate a new IPP message.
41 * ippNewRequest() - Allocate a new IPP message.
42 * ippRead() - Read data for an IPP message from a HTTP
44 * ippReadFile() - Read data for an IPP message from a file.
45 * ippReadIO() - Read data for an IPP message.
46 * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
47 * ippWrite() - Write data for an IPP message to a HTTP
49 * ippWriteFile() - Write data for an IPP message to a file.
50 * ippWriteIO() - Write data for an IPP message.
51 * _ippAddAttr() - Add a new attribute to the request.
52 * _ippFreeAttr() - Free an attribute.
53 * ipp_length() - Compute the length of an IPP message or
55 * ipp_read_http() - Semi-blocking read on a HTTP connection...
56 * ipp_read_file() - Read IPP data from a file.
57 * ipp_write_file() - Write IPP data to a file.
61 * Include necessary headers...
64 #include "http-private.h"
78 static unsigned char *ipp_buffer_get(void);
79 static void ipp_buffer_release(unsigned char *b
);
80 static size_t ipp_length(ipp_t
*ipp
, int collection
);
81 static ssize_t
ipp_read_http(http_t
*http
, ipp_uchar_t
*buffer
,
83 static ssize_t
ipp_read_file(int *fd
, ipp_uchar_t
*buffer
,
85 static ssize_t
ipp_write_file(int *fd
, ipp_uchar_t
*buffer
,
90 * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
93 ipp_attribute_t
* /* O - New attribute */
94 ippAddBoolean(ipp_t
*ipp
, /* I - IPP message */
95 ipp_tag_t group
, /* I - IPP group */
96 const char *name
, /* I - Name of attribute */
97 char value
) /* I - Value of attribute */
99 ipp_attribute_t
*attr
; /* New attribute */
102 DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)",
103 ipp
, group
, ippTagString(group
), name
, value
));
108 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
111 attr
->name
= _cupsStrAlloc(name
);
112 attr
->group_tag
= group
;
113 attr
->value_tag
= IPP_TAG_BOOLEAN
;
114 attr
->values
[0].boolean
= value
;
121 * 'ippAddBooleans()' - Add an array of boolean values.
124 ipp_attribute_t
* /* O - New attribute */
125 ippAddBooleans(ipp_t
*ipp
, /* I - IPP message */
126 ipp_tag_t group
, /* I - IPP group */
127 const char *name
, /* I - Name of attribute */
128 int num_values
, /* I - Number of values */
129 const char *values
) /* I - Values */
131 int i
; /* Looping var */
132 ipp_attribute_t
*attr
; /* New attribute */
133 ipp_value_t
*value
; /* Current value */
136 DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", "
137 "num_values=%d, values=%p)", ipp
, group
, ippTagString(group
),
138 name
, num_values
, values
));
140 if (!ipp
|| !name
|| num_values
< 1)
143 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
146 attr
->name
= _cupsStrAlloc(name
);
147 attr
->group_tag
= group
;
148 attr
->value_tag
= IPP_TAG_BOOLEAN
;
151 for (i
= 0, value
= attr
->values
;
154 value
->boolean
= values
[i
];
161 * 'ippAddCollection()' - Add a collection value.
163 * @since CUPS 1.1.19/Mac OS X 10.3@
166 ipp_attribute_t
* /* O - New attribute */
167 ippAddCollection(ipp_t
*ipp
, /* I - IPP message */
168 ipp_tag_t group
, /* I - IPP group */
169 const char *name
, /* I - Name of attribute */
170 ipp_t
*value
) /* I - Value */
172 ipp_attribute_t
*attr
; /* New attribute */
175 DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", "
176 "value=%p)", ipp
, group
, ippTagString(group
), name
, value
));
181 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
184 attr
->name
= _cupsStrAlloc(name
);
185 attr
->group_tag
= group
;
186 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
187 attr
->values
[0].collection
= value
;
194 * 'ippAddCollections()' - Add an array of collection values.
196 * @since CUPS 1.1.19/Mac OS X 10.3@
199 ipp_attribute_t
* /* O - New attribute */
201 ipp_t
*ipp
, /* I - IPP message */
202 ipp_tag_t group
, /* I - IPP group */
203 const char *name
, /* I - Name of attribute */
204 int num_values
, /* I - Number of values */
205 const ipp_t
**values
) /* I - Values */
207 int i
; /* Looping var */
208 ipp_attribute_t
*attr
; /* New attribute */
209 ipp_value_t
*value
; /* Current value */
212 DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
213 "num_values=%d, values=%p)", ipp
, group
, ippTagString(group
),
214 name
, num_values
, values
));
216 if (!ipp
|| !name
|| num_values
< 1)
219 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
222 attr
->name
= _cupsStrAlloc(name
);
223 attr
->group_tag
= group
;
224 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
227 for (i
= 0, value
= attr
->values
;
230 value
->collection
= (ipp_t
*)values
[i
];
237 * 'ippAddDate()' - Add a date attribute to an IPP message.
240 ipp_attribute_t
* /* O - New attribute */
241 ippAddDate(ipp_t
*ipp
, /* I - IPP message */
242 ipp_tag_t group
, /* I - IPP group */
243 const char *name
, /* I - Name of attribute */
244 const ipp_uchar_t
*value
) /* I - Value */
246 ipp_attribute_t
*attr
; /* New attribute */
249 DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
250 ipp
, group
, ippTagString(group
), name
, value
));
252 if (!ipp
|| !name
|| !value
)
255 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
258 attr
->name
= _cupsStrAlloc(name
);
259 attr
->group_tag
= group
;
260 attr
->value_tag
= IPP_TAG_DATE
;
261 memcpy(attr
->values
[0].date
, value
, 11);
268 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
271 ipp_attribute_t
* /* O - New attribute */
272 ippAddInteger(ipp_t
*ipp
, /* I - IPP message */
273 ipp_tag_t group
, /* I - IPP group */
274 ipp_tag_t type
, /* I - Type of attribute */
275 const char *name
, /* I - Name of attribute */
276 int value
) /* I - Value of attribute */
278 ipp_attribute_t
*attr
; /* New attribute */
281 DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
282 "name=\"%s\", value=%d)", ipp
, group
, ippTagString(group
),
283 type
, ippTagString(type
), name
, value
));
288 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
291 attr
->name
= _cupsStrAlloc(name
);
292 attr
->group_tag
= group
;
293 attr
->value_tag
= type
;
294 attr
->values
[0].integer
= value
;
301 * 'ippAddIntegers()' - Add an array of integer values.
304 ipp_attribute_t
* /* O - New attribute */
305 ippAddIntegers(ipp_t
*ipp
, /* I - IPP message */
306 ipp_tag_t group
, /* I - IPP group */
307 ipp_tag_t type
, /* I - Type of attribute */
308 const char *name
, /* I - Name of attribute */
309 int num_values
, /* I - Number of values */
310 const int *values
) /* I - Values */
312 int i
; /* Looping var */
313 ipp_attribute_t
*attr
; /* New attribute */
314 ipp_value_t
*value
; /* Current value */
317 DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
318 "name=\"%s\", num_values=%d, values=%p)", ipp
,
319 group
, ippTagString(group
), type
, ippTagString(type
), name
,
320 num_values
, values
));
322 if (!ipp
|| !name
|| num_values
< 1)
325 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
328 attr
->name
= _cupsStrAlloc(name
);
329 attr
->group_tag
= group
;
330 attr
->value_tag
= type
;
333 for (i
= 0, value
= attr
->values
;
336 value
->integer
= values
[i
];
343 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
345 * @since CUPS 1.2/Mac OS X 10.5@
348 ipp_attribute_t
* /* O - New attribute */
349 ippAddOctetString(ipp_t
*ipp
, /* I - IPP message */
350 ipp_tag_t group
, /* I - IPP group */
351 const char *name
, /* I - Name of attribute */
352 const void *data
, /* I - octetString data */
353 int datalen
) /* I - Length of data in bytes */
355 ipp_attribute_t
*attr
; /* New attribute */
358 if (ipp
== NULL
|| name
== NULL
)
361 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
365 * Initialize the attribute data...
368 attr
->name
= _cupsStrAlloc(name
);
369 attr
->group_tag
= group
;
370 attr
->value_tag
= IPP_TAG_STRING
;
371 attr
->values
[0].unknown
.length
= datalen
;
375 if ((attr
->values
[0].unknown
.data
= malloc(datalen
)) == NULL
)
377 ippDeleteAttribute(ipp
, attr
);
381 memcpy(attr
->values
[0].unknown
.data
, data
, datalen
);
385 * Return the new attribute...
393 * 'ippAddString()' - Add a language-encoded string to an IPP message.
396 ipp_attribute_t
* /* O - New attribute */
397 ippAddString(ipp_t
*ipp
, /* I - IPP message */
398 ipp_tag_t group
, /* I - IPP group */
399 ipp_tag_t type
, /* I - Type of attribute */
400 const char *name
, /* I - Name of attribute */
401 const char *charset
, /* I - Character set */
402 const char *value
) /* I - Value */
404 ipp_attribute_t
*attr
; /* New attribute */
405 char buffer
[1024], /* Language/charset value buffer */
406 *bufptr
; /* Pointer into buffer */
409 DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
410 "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp
,
411 group
, ippTagString(group
), type
, ippTagString(type
), name
,
417 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
421 * Force value to be English for the POSIX locale...
424 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(value
, "C"))
428 * Convert language and charset values to lowercase and change _ to - as
432 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
434 strlcpy(buffer
, value
, sizeof(buffer
));
437 for (bufptr
= buffer
; *bufptr
; bufptr
++)
441 *bufptr
= tolower(*bufptr
& 255);
445 * Initialize the attribute data...
448 attr
->name
= _cupsStrAlloc(name
);
449 attr
->group_tag
= group
;
450 attr
->value_tag
= type
;
451 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
452 charset
? _cupsStrAlloc(charset
) : NULL
;
453 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
454 value
? _cupsStrAlloc(value
) : NULL
;
461 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
464 ipp_attribute_t
* /* O - New attribute */
466 ipp_t
*ipp
, /* I - IPP message */
467 ipp_tag_t group
, /* I - IPP group */
468 ipp_tag_t type
, /* I - Type of attribute */
469 const char *name
, /* I - Name of attribute */
470 int num_values
, /* I - Number of values */
471 const char *charset
, /* I - Character set */
472 const char * const *values
) /* I - Values */
474 int i
; /* Looping var */
475 ipp_attribute_t
*attr
; /* New attribute */
476 ipp_value_t
*value
; /* Current value */
477 char buffer
[1024], /* Language/charset value buffer */
478 *bufptr
; /* Pointer into buffer */
481 DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
482 "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp
,
483 group
, ippTagString(group
), type
, ippTagString(type
), name
,
484 num_values
, charset
, values
));
486 if (!ipp
|| !name
|| num_values
< 1)
489 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
493 * Initialize the attribute data...
496 attr
->name
= _cupsStrAlloc(name
);
497 attr
->group_tag
= group
;
498 attr
->value_tag
= type
;
500 for (i
= 0, value
= attr
->values
;
505 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
506 charset
? _cupsStrAlloc(charset
) : NULL
;
508 value
->string
.charset
= attr
->values
[0].string
.charset
;
512 if ((int)type
& IPP_TAG_COPY
)
513 value
->string
.text
= (char *)values
[i
];
514 else if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(values
[i
], "C"))
517 * Force language to be English for the POSIX locale...
520 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
523 else if (type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
)
526 * Convert language values to lowercase and change _ to - as needed...
529 strlcpy(buffer
, values
[i
], sizeof(buffer
));
531 for (bufptr
= buffer
; *bufptr
; bufptr
++)
535 *bufptr
= tolower(*bufptr
& 255);
537 value
->string
.text
= _cupsStrAlloc(buffer
);
540 value
->string
.text
= _cupsStrAlloc(values
[i
]);
550 * 'ippAddRange()' - Add a range of values to an IPP message.
553 ipp_attribute_t
* /* O - New attribute */
554 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
555 ipp_tag_t group
, /* I - IPP group */
556 const char *name
, /* I - Name of attribute */
557 int lower
, /* I - Lower value */
558 int upper
) /* I - Upper value */
560 ipp_attribute_t
*attr
; /* New attribute */
563 DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
564 "upper=%d)", ipp
, group
, ippTagString(group
), name
, lower
,
570 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
573 attr
->name
= _cupsStrAlloc(name
);
574 attr
->group_tag
= group
;
575 attr
->value_tag
= IPP_TAG_RANGE
;
576 attr
->values
[0].range
.lower
= lower
;
577 attr
->values
[0].range
.upper
= upper
;
584 * 'ippAddRanges()' - Add ranges of values to an IPP message.
587 ipp_attribute_t
* /* O - New attribute */
588 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
589 ipp_tag_t group
, /* I - IPP group */
590 const char *name
, /* I - Name of attribute */
591 int num_values
, /* I - Number of values */
592 const int *lower
, /* I - Lower values */
593 const int *upper
) /* I - Upper values */
595 int i
; /* Looping var */
596 ipp_attribute_t
*attr
; /* New attribute */
597 ipp_value_t
*value
; /* Current value */
600 DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
601 "num_values=%d, lower=%p, upper=%p)", ipp
, group
,
602 ippTagString(group
), name
, num_values
, lower
, upper
));
604 if (!ipp
|| !name
|| num_values
< 1)
607 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
610 attr
->name
= _cupsStrAlloc(name
);
611 attr
->group_tag
= group
;
612 attr
->value_tag
= IPP_TAG_RANGE
;
614 if (lower
!= NULL
&& upper
!= NULL
)
615 for (i
= 0, value
= attr
->values
;
619 value
->range
.lower
= lower
[i
];
620 value
->range
.upper
= upper
[i
];
628 * 'ippAddResolution()' - Add a resolution value to an IPP message.
631 ipp_attribute_t
* /* O - New attribute */
632 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
633 ipp_tag_t group
, /* I - IPP group */
634 const char *name
, /* I - Name of attribute */
635 ipp_res_t units
, /* I - Units for resolution */
636 int xres
, /* I - X resolution */
637 int yres
) /* I - Y resolution */
639 ipp_attribute_t
*attr
; /* New attribute */
642 DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
643 "units=%d, xres=%d, yres=%d)", ipp
, group
,
644 ippTagString(group
), name
, units
, xres
, yres
));
649 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
652 attr
->name
= _cupsStrAlloc(name
);
653 attr
->group_tag
= group
;
654 attr
->value_tag
= IPP_TAG_RESOLUTION
;
655 attr
->values
[0].resolution
.xres
= xres
;
656 attr
->values
[0].resolution
.yres
= yres
;
657 attr
->values
[0].resolution
.units
= units
;
664 * 'ippAddResolutions()' - Add resolution values to an IPP message.
667 ipp_attribute_t
* /* O - New attribute */
668 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
669 ipp_tag_t group
, /* I - IPP group */
670 const char *name
, /* I - Name of attribute */
671 int num_values
,/* I - Number of values */
672 ipp_res_t units
, /* I - Units for resolution */
673 const int *xres
, /* I - X resolutions */
674 const int *yres
) /* I - Y resolutions */
676 int i
; /* Looping var */
677 ipp_attribute_t
*attr
; /* New attribute */
678 ipp_value_t
*value
; /* Current value */
681 DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
682 "num_value=%d, units=%d, xres=%p, yres=%p)", ipp
, group
,
683 ippTagString(group
), name
, num_values
, units
, xres
, yres
));
685 if (!ipp
|| !name
|| num_values
< 1)
688 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
691 attr
->name
= _cupsStrAlloc(name
);
692 attr
->group_tag
= group
;
693 attr
->value_tag
= IPP_TAG_RESOLUTION
;
695 if (xres
!= NULL
&& yres
!= NULL
)
696 for (i
= 0, value
= attr
->values
;
700 value
->resolution
.xres
= xres
[i
];
701 value
->resolution
.yres
= yres
[i
];
702 value
->resolution
.units
= units
;
710 * 'ippAddSeparator()' - Add a group separator to an IPP message.
713 ipp_attribute_t
* /* O - New attribute */
714 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
716 ipp_attribute_t
*attr
; /* New attribute */
719 DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp
));
724 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
727 attr
->group_tag
= IPP_TAG_ZERO
;
728 attr
->value_tag
= IPP_TAG_ZERO
;
735 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
739 time_t /* O - UNIX time value */
740 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
742 struct tm unixdate
; /* UNIX date/time info */
743 time_t t
; /* Computed time */
749 memset(&unixdate
, 0, sizeof(unixdate
));
752 * RFC-1903 date/time format is:
754 * Byte(s) Description
755 * ------- -----------
756 * 0-1 Year (0 to 65535)
760 * 5 Minutes (0 to 59)
761 * 6 Seconds (0 to 60, 60 = "leap second")
762 * 7 Deciseconds (0 to 9)
764 * 9 UTC hours (0 to 11)
765 * 10 UTC minutes (0 to 59)
768 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
769 unixdate
.tm_mon
= date
[2] - 1;
770 unixdate
.tm_mday
= date
[3];
771 unixdate
.tm_hour
= date
[4];
772 unixdate
.tm_min
= date
[5];
773 unixdate
.tm_sec
= date
[6];
775 t
= mktime(&unixdate
);
778 t
+= date
[9] * 3600 + date
[10] * 60;
780 t
-= date
[9] * 3600 + date
[10] * 60;
787 * 'ippDelete()' - Delete an IPP message.
791 ippDelete(ipp_t
*ipp
) /* I - IPP message */
793 ipp_attribute_t
*attr
, /* Current attribute */
794 *next
; /* Next attribute */
797 DEBUG_printf(("ippDelete(ipp=%p)", ipp
));
802 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
813 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
815 * @since CUPS 1.1.19/Mac OS X 10.3@
820 ipp_t
*ipp
, /* I - IPP message */
821 ipp_attribute_t
*attr
) /* I - Attribute to delete */
823 ipp_attribute_t
*current
, /* Current attribute */
824 *prev
; /* Previous attribute */
827 DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp
, attr
,
828 attr
? attr
->name
: "(null)"));
831 * Find the attribute in the list...
834 for (current
= ipp
->attrs
, prev
= NULL
;
835 current
!= NULL
&& current
!= attr
;
836 prev
= current
, current
= current
->next
);
841 * Found it, remove the attribute from the list...
845 prev
->next
= current
->next
;
847 ipp
->attrs
= current
->next
;
849 if (current
== ipp
->last
)
853 * Free memory used by the attribute...
856 _ippFreeAttr(current
);
862 * 'ippFindAttribute()' - Find a named attribute in a request...
865 ipp_attribute_t
* /* O - Matching attribute */
866 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
867 const char *name
, /* I - Name of attribute */
868 ipp_tag_t type
) /* I - Type of attribute */
870 DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp
,
871 name
, type
, ippTagString(type
)));
877 * Reset the current pointer...
883 * Search for the attribute...
886 return (ippFindNextAttribute(ipp
, name
, type
));
891 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
894 ipp_attribute_t
* /* O - Matching attribute */
895 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
896 const char *name
, /* I - Name of attribute */
897 ipp_tag_t type
) /* I - Type of attribute */
899 ipp_attribute_t
*attr
; /* Current atttribute */
900 ipp_tag_t value_tag
; /* Value tag */
903 DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
904 ipp
, name
, type
, ippTagString(type
)));
911 ipp
->prev
= ipp
->current
;
912 attr
= ipp
->current
->next
;
920 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
922 DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr
,
925 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
927 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
928 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
929 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
930 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
946 * 'ippLength()' - Compute the length of an IPP message.
949 size_t /* O - Size of IPP message */
950 ippLength(ipp_t
*ipp
) /* I - IPP message */
952 return (ipp_length(ipp
, 0));
957 * 'ippNew()' - Allocate a new IPP message.
960 ipp_t
* /* O - New IPP message */
963 ipp_t
*temp
; /* New IPP message */
966 DEBUG_puts("ippNew()");
968 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
971 * Default to IPP 1.1...
974 temp
->request
.any
.version
[0] = 1;
975 temp
->request
.any
.version
[1] = 1;
978 DEBUG_printf(("1ippNew: Returning %p", temp
));
985 * 'ippNewRequest()' - Allocate a new IPP request message.
987 * The new request message is initialized with the attributes-charset and
988 * attributes-natural-language attributes added. The
989 * attributes-natural-language value is derived from the current locale.
991 * @since CUPS 1.2/Mac OS X 10.5@
994 ipp_t
* /* O - IPP request message */
995 ippNewRequest(ipp_op_t op
) /* I - Operation code */
997 ipp_t
*request
; /* IPP request message */
998 cups_lang_t
*language
; /* Current language localization */
1001 DEBUG_printf(("ippNewRequest(op=%02x(%s))", op
, ippOpString(op
)));
1004 * Create a new IPP message...
1007 if ((request
= ippNew()) == NULL
)
1011 * Set the operation and request ID...
1014 request
->request
.op
.operation_id
= op
;
1015 request
->request
.op
.request_id
= 1;
1018 * Use UTF-8 as the character set...
1021 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1022 "attributes-charset", NULL
, "utf-8");
1025 * Get the language from the current locale...
1028 language
= cupsLangDefault();
1030 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1031 "attributes-natural-language", NULL
, language
->language
);
1034 * Return the new request...
1042 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
1045 ipp_state_t
/* O - Current state */
1046 ippRead(http_t
*http
, /* I - HTTP connection */
1047 ipp_t
*ipp
) /* I - IPP data */
1049 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
,
1050 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
1055 DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http
->state
,
1058 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
, http
->blocking
, NULL
,
1064 * 'ippReadFile()' - Read data for an IPP message from a file.
1066 * @since CUPS 1.1.19/Mac OS X 10.3@
1069 ipp_state_t
/* O - Current state */
1070 ippReadFile(int fd
, /* I - HTTP data */
1071 ipp_t
*ipp
) /* I - IPP data */
1073 DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd
, ipp
));
1075 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1080 * 'ippReadIO()' - Read data for an IPP message.
1082 * @since CUPS 1.2/Mac OS X 10.5@
1085 ipp_state_t
/* O - Current state */
1086 ippReadIO(void *src
, /* I - Data source */
1087 ipp_iocb_t cb
, /* I - Read callback function */
1088 int blocking
, /* I - Use blocking IO? */
1089 ipp_t
*parent
, /* I - Parent request, if any */
1090 ipp_t
*ipp
) /* I - IPP data */
1092 int n
; /* Length of data */
1093 unsigned char *buffer
, /* Data buffer */
1094 string
[IPP_MAX_NAME
],
1095 /* Small string buffer */
1096 *bufptr
; /* Pointer into buffer */
1097 ipp_attribute_t
*attr
; /* Current attribute */
1098 ipp_tag_t tag
; /* Current tag */
1099 ipp_tag_t value_tag
; /* Current value tag */
1100 ipp_value_t
*value
; /* Current value */
1103 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1104 src
, cb
, blocking
, parent
, ipp
));
1105 DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp
->state
));
1110 if ((buffer
= ipp_buffer_get()) == NULL
)
1112 DEBUG_puts("1ippReadIO: Unable to get read buffer!");
1119 ipp
->state
++; /* Avoid common problem... */
1125 * Get the request header...
1128 if ((*cb
)(src
, buffer
, 8) < 8)
1130 DEBUG_puts("1ippReadIO: Unable to read header!");
1131 ipp_buffer_release(buffer
);
1136 * Then copy the request header over...
1139 ipp
->request
.any
.version
[0] = buffer
[0];
1140 ipp
->request
.any
.version
[1] = buffer
[1];
1141 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1142 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1143 buffer
[6]) << 8) | buffer
[7];
1145 DEBUG_printf(("2ippReadIO: version=%d.%d", buffer
[0], buffer
[1]));
1146 DEBUG_printf(("2ippReadIO: op_status=%04x",
1147 ipp
->request
.any
.op_status
));
1148 DEBUG_printf(("2ippReadIO: request_id=%d",
1149 ipp
->request
.any
.request_id
));
1152 ipp
->state
= IPP_ATTRIBUTE
;
1153 ipp
->current
= NULL
;
1154 ipp
->curtag
= IPP_TAG_ZERO
;
1155 ipp
->prev
= ipp
->last
;
1158 * If blocking is disabled, stop here...
1164 case IPP_ATTRIBUTE
:
1167 if ((*cb
)(src
, buffer
, 1) < 1)
1169 DEBUG_puts("1ippReadIO: Callback returned EOF/error");
1170 ipp_buffer_release(buffer
);
1174 DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
1175 ipp
->current
, ipp
->prev
));
1178 * Read this attribute...
1181 tag
= (ipp_tag_t
)buffer
[0];
1183 if (tag
== IPP_TAG_END
)
1186 * No more attributes left...
1189 DEBUG_puts("2ippReadIO: IPP_TAG_END!");
1191 ipp
->state
= IPP_DATA
;
1194 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1197 * Group tag... Set the current group and continue...
1200 if (ipp
->curtag
== tag
)
1201 ipp
->prev
= ippAddSeparator(ipp
);
1202 else if (ipp
->current
)
1203 ipp
->prev
= ipp
->current
;
1206 ipp
->current
= NULL
;
1207 DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag
,
1208 ippTagString(tag
), ipp
->prev
));
1212 DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag
,
1213 ippTagString(tag
)));
1219 if ((*cb
)(src
, buffer
, 2) < 2)
1221 DEBUG_puts("1ippReadIO: unable to read name length!");
1222 ipp_buffer_release(buffer
);
1226 n
= (buffer
[0] << 8) | buffer
[1];
1228 if (n
>= IPP_BUF_SIZE
)
1230 DEBUG_printf(("1ippReadIO: bad name length %d!", n
));
1231 ipp_buffer_release(buffer
);
1235 DEBUG_printf(("2ippReadIO: name length=%d", n
));
1237 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1238 tag
!= IPP_TAG_END_COLLECTION
)
1241 * More values for current attribute...
1244 if (ipp
->current
== NULL
)
1246 DEBUG_puts("1ippReadIO: Attribute without name and no current");
1247 ipp_buffer_release(buffer
);
1251 attr
= ipp
->current
;
1252 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1255 * Make sure we aren't adding a new value of a different
1259 if (value_tag
== IPP_TAG_ZERO
)
1262 * Setting the value of a collection member...
1265 attr
->value_tag
= tag
;
1267 else if ((value_tag
>= IPP_TAG_TEXTLANG
&&
1268 value_tag
<= IPP_TAG_MIMETYPE
))
1271 * String values can sometimes come across in different
1272 * forms; accept sets of differing values...
1275 if ((tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
) &&
1276 tag
!= IPP_TAG_NOVALUE
)
1278 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1279 value_tag
, ippTagString(value_tag
), tag
,
1280 ippTagString(tag
)));
1281 ipp_buffer_release(buffer
);
1285 else if (value_tag
!= tag
)
1287 DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
1288 value_tag
, ippTagString(value_tag
), tag
,
1289 ippTagString(tag
)));
1290 ipp_buffer_release(buffer
);
1295 * Finally, reallocate the attribute array as needed...
1298 if (attr
->num_values
== 1 ||
1299 (attr
->num_values
> 0 &&
1300 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1302 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1305 DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
1306 attr
->num_values
+ IPP_MAX_VALUES
));
1309 * Reallocate memory...
1312 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1313 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1314 sizeof(ipp_value_t
))) == NULL
)
1316 DEBUG_puts("1ippReadIO: Unable to resize attribute");
1317 ipp_buffer_release(buffer
);
1324 * Reset pointers in the list...
1328 ipp
->prev
->next
= temp
;
1332 attr
= ipp
->current
= ipp
->last
= temp
;
1336 else if (tag
== IPP_TAG_MEMBERNAME
)
1339 * Name must be length 0!
1344 DEBUG_puts("1ippReadIO: member name not empty!");
1345 ipp_buffer_release(buffer
);
1350 ipp
->prev
= ipp
->current
;
1352 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1354 DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
1355 "ipp->prev=%p", ipp
->current
, ipp
->prev
));
1357 attr
->group_tag
= ipp
->curtag
;
1358 attr
->value_tag
= IPP_TAG_ZERO
;
1359 attr
->num_values
= 0;
1361 else if (tag
!= IPP_TAG_END_COLLECTION
)
1364 * New attribute; read the name and add it...
1367 if ((*cb
)(src
, buffer
, n
) < n
)
1369 DEBUG_puts("1ippReadIO: unable to read name!");
1370 ipp_buffer_release(buffer
);
1377 ipp
->prev
= ipp
->current
;
1379 if ((attr
= ipp
->current
= _ippAddAttr(ipp
, 1)) == NULL
)
1381 DEBUG_puts("1ippReadIO: unable to allocate attribute!");
1382 ipp_buffer_release(buffer
);
1386 DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
1387 "ipp->prev=%p", buffer
, ipp
->current
, ipp
->prev
));
1389 attr
->group_tag
= ipp
->curtag
;
1390 attr
->value_tag
= tag
;
1391 attr
->name
= _cupsStrAlloc((char *)buffer
);
1392 attr
->num_values
= 0;
1397 if (tag
!= IPP_TAG_END_COLLECTION
)
1398 value
= attr
->values
+ attr
->num_values
;
1402 if ((*cb
)(src
, buffer
, 2) < 2)
1404 DEBUG_puts("1ippReadIO: unable to read value length!");
1405 ipp_buffer_release(buffer
);
1409 n
= (buffer
[0] << 8) | buffer
[1];
1410 DEBUG_printf(("2ippReadIO: value length=%d", n
));
1414 case IPP_TAG_INTEGER
:
1418 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1419 ipp_buffer_release(buffer
);
1423 if ((*cb
)(src
, buffer
, 4) < 4)
1425 DEBUG_puts("1ippReadIO: Unable to read integer value!");
1426 ipp_buffer_release(buffer
);
1430 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1436 case IPP_TAG_BOOLEAN
:
1439 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1440 ipp_buffer_release(buffer
);
1444 if ((*cb
)(src
, buffer
, 1) < 1)
1446 DEBUG_puts("1ippReadIO: Unable to read boolean value!");
1447 ipp_buffer_release(buffer
);
1451 value
->boolean
= buffer
[0];
1454 case IPP_TAG_NOVALUE
:
1455 case IPP_TAG_NOTSETTABLE
:
1456 case IPP_TAG_DELETEATTR
:
1457 case IPP_TAG_ADMINDEFINE
:
1459 * These value types are not supposed to have values, however
1460 * some vendors (Brother) do not implement IPP correctly and so
1461 * we need to map non-empty values to text...
1464 if (attr
->value_tag
== tag
)
1469 attr
->value_tag
= IPP_TAG_TEXT
;
1474 case IPP_TAG_KEYWORD
:
1476 case IPP_TAG_URISCHEME
:
1477 case IPP_TAG_CHARSET
:
1478 case IPP_TAG_LANGUAGE
:
1479 case IPP_TAG_MIMETYPE
:
1480 if (n
>= IPP_BUF_SIZE
)
1482 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1483 ipp_buffer_release(buffer
);
1487 if ((*cb
)(src
, buffer
, n
) < n
)
1489 DEBUG_puts("1ippReadIO: unable to read name!");
1490 ipp_buffer_release(buffer
);
1495 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1496 DEBUG_printf(("2ippReadIO: value=\"%s\"", value
->string
.text
));
1502 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1503 ipp_buffer_release(buffer
);
1507 if ((*cb
)(src
, value
->date
, 11) < 11)
1509 DEBUG_puts("1ippReadIO: Unable to read date value!");
1510 ipp_buffer_release(buffer
);
1515 case IPP_TAG_RESOLUTION
:
1518 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1519 ipp_buffer_release(buffer
);
1523 if ((*cb
)(src
, buffer
, 9) < 9)
1525 DEBUG_puts("1ippReadIO: Unable to read resolution value!");
1526 ipp_buffer_release(buffer
);
1530 value
->resolution
.xres
=
1531 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1533 value
->resolution
.yres
=
1534 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1536 value
->resolution
.units
=
1537 (ipp_res_t
)buffer
[8];
1540 case IPP_TAG_RANGE
:
1543 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1544 ipp_buffer_release(buffer
);
1548 if ((*cb
)(src
, buffer
, 8) < 8)
1550 DEBUG_puts("1ippReadIO: Unable to read range value!");
1551 ipp_buffer_release(buffer
);
1555 value
->range
.lower
=
1556 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1558 value
->range
.upper
=
1559 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1563 case IPP_TAG_TEXTLANG
:
1564 case IPP_TAG_NAMELANG
:
1565 if (n
>= IPP_BUF_SIZE
|| n
< 4)
1567 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1568 ipp_buffer_release(buffer
);
1572 if ((*cb
)(src
, buffer
, n
) < n
)
1574 DEBUG_puts("1ippReadIO: Unable to read string w/language "
1576 ipp_buffer_release(buffer
);
1583 * text-with-language and name-with-language are composite
1592 n
= (bufptr
[0] << 8) | bufptr
[1];
1594 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
) ||
1595 n
>= sizeof(string
))
1597 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1598 ipp_buffer_release(buffer
);
1602 memcpy(string
, bufptr
+ 2, n
);
1605 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1608 n
= (bufptr
[0] << 8) | bufptr
[1];
1610 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
))
1612 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1613 ipp_buffer_release(buffer
);
1617 bufptr
[2 + n
] = '\0';
1618 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1621 case IPP_TAG_BEGIN_COLLECTION
:
1623 * Oh, boy, here comes a collection value, so read it...
1626 value
->collection
= ippNew();
1630 DEBUG_puts("1ippReadIO: begCollection tag with value length "
1632 ipp_buffer_release(buffer
);
1636 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1638 DEBUG_puts("1ippReadIO: Unable to read collection value!");
1639 ipp_buffer_release(buffer
);
1644 case IPP_TAG_END_COLLECTION
:
1645 ipp_buffer_release(buffer
);
1649 DEBUG_puts("1ippReadIO: endCollection tag with value length "
1654 DEBUG_puts("1ippReadIO: endCollection tag...");
1655 return (ipp
->state
= IPP_DATA
);
1657 case IPP_TAG_MEMBERNAME
:
1659 * The value the name of the member in the collection, which
1660 * we need to carry over...
1663 if (n
>= IPP_BUF_SIZE
)
1665 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1666 ipp_buffer_release(buffer
);
1670 if ((*cb
)(src
, buffer
, n
) < n
)
1672 DEBUG_puts("1ippReadIO: Unable to read member name value!");
1673 ipp_buffer_release(buffer
);
1678 attr
->name
= _cupsStrAlloc((char *)buffer
);
1681 * Since collection members are encoded differently than
1682 * regular attributes, make sure we don't start with an
1686 attr
->num_values
--;
1688 DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr
->name
));
1691 default : /* Other unsupported values */
1692 if (n
> IPP_MAX_LENGTH
)
1694 DEBUG_printf(("1ippReadIO: bad value length %d!", n
));
1695 ipp_buffer_release(buffer
);
1701 DEBUG_puts("1ippReadIO: NULL value!");
1702 ipp_buffer_release(buffer
);
1706 value
->unknown
.length
= n
;
1709 if ((value
->unknown
.data
= malloc(n
)) == NULL
)
1711 DEBUG_puts("1ippReadIO: Unable to allocate value");
1712 ipp_buffer_release(buffer
);
1716 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1718 DEBUG_puts("1ippReadIO: Unable to read unsupported value!");
1719 ipp_buffer_release(buffer
);
1724 value
->unknown
.data
= NULL
;
1728 attr
->num_values
++;
1731 * If blocking is disabled, stop here...
1743 break; /* anti-compiler-warning-code */
1746 DEBUG_printf(("1ippReadIO: returning ipp->state=%d!", ipp
->state
));
1747 ipp_buffer_release(buffer
);
1749 return (ipp
->state
);
1754 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1757 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1758 ippTimeToDate(time_t t
) /* I - UNIX time value */
1760 struct tm
*unixdate
; /* UNIX unixdate/time info */
1761 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1762 /* RFC-1903 date/time data */
1766 * RFC-1903 date/time format is:
1768 * Byte(s) Description
1769 * ------- -----------
1770 * 0-1 Year (0 to 65535)
1774 * 5 Minutes (0 to 59)
1775 * 6 Seconds (0 to 60, 60 = "leap second")
1776 * 7 Deciseconds (0 to 9)
1778 * 9 UTC hours (0 to 11)
1779 * 10 UTC minutes (0 to 59)
1782 unixdate
= gmtime(&t
);
1783 unixdate
->tm_year
+= 1900;
1785 date
[0] = unixdate
->tm_year
>> 8;
1786 date
[1] = unixdate
->tm_year
;
1787 date
[2] = unixdate
->tm_mon
+ 1;
1788 date
[3] = unixdate
->tm_mday
;
1789 date
[4] = unixdate
->tm_hour
;
1790 date
[5] = unixdate
->tm_min
;
1791 date
[6] = unixdate
->tm_sec
;
1802 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1805 ipp_state_t
/* O - Current state */
1806 ippWrite(http_t
*http
, /* I - HTTP connection */
1807 ipp_t
*ipp
) /* I - IPP data */
1809 DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http
, ipp
));
1814 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
, http
->blocking
, NULL
, ipp
));
1819 * 'ippWriteFile()' - Write data for an IPP message to a file.
1821 * @since CUPS 1.1.19/Mac OS X 10.3@
1824 ipp_state_t
/* O - Current state */
1825 ippWriteFile(int fd
, /* I - HTTP data */
1826 ipp_t
*ipp
) /* I - IPP data */
1828 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd
, ipp
));
1830 ipp
->state
= IPP_IDLE
;
1832 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1837 * 'ippWriteIO()' - Write data for an IPP message.
1839 * @since CUPS 1.2/Mac OS X 10.5@
1842 ipp_state_t
/* O - Current state */
1843 ippWriteIO(void *dst
, /* I - Destination */
1844 ipp_iocb_t cb
, /* I - Write callback function */
1845 int blocking
, /* I - Use blocking IO? */
1846 ipp_t
*parent
, /* I - Parent IPP message */
1847 ipp_t
*ipp
) /* I - IPP data */
1849 int i
; /* Looping var */
1850 int n
; /* Length of data */
1851 unsigned char *buffer
, /* Data buffer */
1852 *bufptr
; /* Pointer into buffer */
1853 ipp_attribute_t
*attr
; /* Current attribute */
1854 ipp_value_t
*value
; /* Current value */
1857 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1858 dst
, cb
, blocking
, parent
, ipp
));
1863 if ((buffer
= ipp_buffer_get()) == NULL
)
1865 DEBUG_puts("1ippWriteIO: Unable to get write buffer");
1872 ipp
->state
++; /* Avoid common problem... */
1878 * Send the request header:
1881 * Operation/Status Code = 2 bytes
1882 * Request ID = 4 bytes
1888 *bufptr
++ = ipp
->request
.any
.version
[0];
1889 *bufptr
++ = ipp
->request
.any
.version
[1];
1890 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1891 *bufptr
++ = ipp
->request
.any
.op_status
;
1892 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1893 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1894 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1895 *bufptr
++ = ipp
->request
.any
.request_id
;
1897 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1899 DEBUG_puts("1ippWriteIO: Could not write IPP header...");
1900 ipp_buffer_release(buffer
);
1906 * Reset the state engine to point to the first attribute
1907 * in the request/response, with no current group.
1910 ipp
->state
= IPP_ATTRIBUTE
;
1911 ipp
->current
= ipp
->attrs
;
1912 ipp
->curtag
= IPP_TAG_ZERO
;
1914 DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer
[0], buffer
[1]));
1915 DEBUG_printf(("2ippWriteIO: op_status=%04x",
1916 ipp
->request
.any
.op_status
));
1917 DEBUG_printf(("2ippWriteIO: request_id=%d",
1918 ipp
->request
.any
.request_id
));
1921 * If blocking is disabled, stop here...
1927 case IPP_ATTRIBUTE
:
1928 while (ipp
->current
!= NULL
)
1931 * Write this attribute...
1935 attr
= ipp
->current
;
1937 ipp
->current
= ipp
->current
->next
;
1939 if (ipp
->curtag
!= attr
->group_tag
&& parent
== NULL
)
1942 * Send a group tag byte...
1945 ipp
->curtag
= attr
->group_tag
;
1947 if (attr
->group_tag
== IPP_TAG_ZERO
)
1950 DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
1951 attr
->group_tag
, ippTagString(attr
->group_tag
)));
1952 *bufptr
++ = attr
->group_tag
;
1954 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1958 * Write the attribute tag and name. The current implementation
1959 * does not support the extension value tags above 0x7f, so all
1960 * value tags are 1 byte.
1962 * The attribute name length does not include the trailing nul
1963 * character in the source string.
1965 * Collection values (parent != NULL) are written differently...
1971 * Get the length of the attribute name, and make sure it won't
1972 * overflow the buffer...
1975 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 4))
1977 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
1978 ipp_buffer_release(buffer
);
1983 * Write the value tag, name length, and name string...
1986 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
1987 attr
->value_tag
, ippTagString(attr
->value_tag
)));
1988 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
1991 *bufptr
++ = attr
->value_tag
;
1994 memcpy(bufptr
, attr
->name
, n
);
2000 * Get the length of the attribute name, and make sure it won't
2001 * overflow the buffer...
2004 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 7))
2006 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n
));
2007 ipp_buffer_release(buffer
);
2012 * Write the member name tag, name length, name string, value tag,
2013 * and empty name for the collection member attribute...
2016 DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
2017 IPP_TAG_MEMBERNAME
));
2018 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n
,
2020 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2021 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2022 DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
2024 *bufptr
++ = IPP_TAG_MEMBERNAME
;
2029 memcpy(bufptr
, attr
->name
, n
);
2032 *bufptr
++ = attr
->value_tag
;
2038 * Now write the attribute value(s)...
2041 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2043 case IPP_TAG_INTEGER
:
2045 for (i
= 0, value
= attr
->values
;
2046 i
< attr
->num_values
;
2049 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 9)
2051 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2053 DEBUG_puts("1ippWriteIO: Could not write IPP "
2055 ipp_buffer_release(buffer
);
2065 * Arrays and sets are done by sending additional
2066 * values with a zero-length name...
2069 *bufptr
++ = attr
->value_tag
;
2075 * Integers and enumerations are both 4-byte signed
2076 * (twos-complement) values.
2078 * Put the 2-byte length and 4-byte value into the buffer...
2083 *bufptr
++ = value
->integer
>> 24;
2084 *bufptr
++ = value
->integer
>> 16;
2085 *bufptr
++ = value
->integer
>> 8;
2086 *bufptr
++ = value
->integer
;
2090 case IPP_TAG_BOOLEAN
:
2091 for (i
= 0, value
= attr
->values
;
2092 i
< attr
->num_values
;
2095 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 6)
2097 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2099 DEBUG_puts("1ippWriteIO: Could not write IPP "
2101 ipp_buffer_release(buffer
);
2111 * Arrays and sets are done by sending additional
2112 * values with a zero-length name...
2115 *bufptr
++ = attr
->value_tag
;
2121 * Boolean values are 1-byte; 0 = false, 1 = true.
2123 * Put the 2-byte length and 1-byte value into the buffer...
2128 *bufptr
++ = value
->boolean
;
2134 case IPP_TAG_KEYWORD
:
2136 case IPP_TAG_URISCHEME
:
2137 case IPP_TAG_CHARSET
:
2138 case IPP_TAG_LANGUAGE
:
2139 case IPP_TAG_MIMETYPE
:
2140 for (i
= 0, value
= attr
->values
;
2141 i
< attr
->num_values
;
2147 * Arrays and sets are done by sending additional
2148 * values with a zero-length name...
2151 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2153 ippTagString(attr
->value_tag
)));
2154 DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
2156 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2158 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2160 DEBUG_puts("1ippWriteIO: Could not write IPP "
2162 ipp_buffer_release(buffer
);
2169 *bufptr
++ = attr
->value_tag
;
2174 if (value
->string
.text
!= NULL
)
2175 n
= (int)strlen(value
->string
.text
);
2179 if (n
> (IPP_BUF_SIZE
- 2))
2181 DEBUG_printf(("1ippWriteIO: String too long (%d)", n
));
2182 ipp_buffer_release(buffer
);
2186 DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n
,
2187 value
->string
.text
));
2189 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2191 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2193 DEBUG_puts("1ippWriteIO: Could not write IPP "
2195 ipp_buffer_release(buffer
);
2203 * All simple strings consist of the 2-byte length and
2204 * character data without the trailing nul normally found
2205 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2206 * bytes since the 2-byte length is a signed (twos-complement)
2209 * Put the 2-byte length and string characters in the buffer.
2217 memcpy(bufptr
, value
->string
.text
, n
);
2224 for (i
= 0, value
= attr
->values
;
2225 i
< attr
->num_values
;
2228 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 16)
2230 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2232 DEBUG_puts("1ippWriteIO: Could not write IPP "
2234 ipp_buffer_release(buffer
);
2244 * Arrays and sets are done by sending additional
2245 * values with a zero-length name...
2248 *bufptr
++ = attr
->value_tag
;
2254 * Date values consist of a 2-byte length and an
2255 * 11-byte date/time structure defined by RFC 1903.
2257 * Put the 2-byte length and 11-byte date/time
2258 * structure in the buffer.
2263 memcpy(bufptr
, value
->date
, 11);
2268 case IPP_TAG_RESOLUTION
:
2269 for (i
= 0, value
= attr
->values
;
2270 i
< attr
->num_values
;
2273 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 14)
2275 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2277 DEBUG_puts("1ippWriteIO: Could not write IPP "
2279 ipp_buffer_release(buffer
);
2289 * Arrays and sets are done by sending additional
2290 * values with a zero-length name...
2293 *bufptr
++ = attr
->value_tag
;
2299 * Resolution values consist of a 2-byte length,
2300 * 4-byte horizontal resolution value, 4-byte vertical
2301 * resolution value, and a 1-byte units value.
2303 * Put the 2-byte length and resolution value data
2309 *bufptr
++ = value
->resolution
.xres
>> 24;
2310 *bufptr
++ = value
->resolution
.xres
>> 16;
2311 *bufptr
++ = value
->resolution
.xres
>> 8;
2312 *bufptr
++ = value
->resolution
.xres
;
2313 *bufptr
++ = value
->resolution
.yres
>> 24;
2314 *bufptr
++ = value
->resolution
.yres
>> 16;
2315 *bufptr
++ = value
->resolution
.yres
>> 8;
2316 *bufptr
++ = value
->resolution
.yres
;
2317 *bufptr
++ = value
->resolution
.units
;
2321 case IPP_TAG_RANGE
:
2322 for (i
= 0, value
= attr
->values
;
2323 i
< attr
->num_values
;
2326 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 13)
2328 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2330 DEBUG_puts("1ippWriteIO: Could not write IPP "
2332 ipp_buffer_release(buffer
);
2342 * Arrays and sets are done by sending additional
2343 * values with a zero-length name...
2346 *bufptr
++ = attr
->value_tag
;
2352 * Range values consist of a 2-byte length,
2353 * 4-byte lower value, and 4-byte upper value.
2355 * Put the 2-byte length and range value data
2361 *bufptr
++ = value
->range
.lower
>> 24;
2362 *bufptr
++ = value
->range
.lower
>> 16;
2363 *bufptr
++ = value
->range
.lower
>> 8;
2364 *bufptr
++ = value
->range
.lower
;
2365 *bufptr
++ = value
->range
.upper
>> 24;
2366 *bufptr
++ = value
->range
.upper
>> 16;
2367 *bufptr
++ = value
->range
.upper
>> 8;
2368 *bufptr
++ = value
->range
.upper
;
2372 case IPP_TAG_TEXTLANG
:
2373 case IPP_TAG_NAMELANG
:
2374 for (i
= 0, value
= attr
->values
;
2375 i
< attr
->num_values
;
2381 * Arrays and sets are done by sending additional
2382 * values with a zero-length name...
2385 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2387 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2389 DEBUG_puts("1ippWriteIO: Could not write IPP "
2391 ipp_buffer_release(buffer
);
2398 *bufptr
++ = attr
->value_tag
;
2404 * textWithLanguage and nameWithLanguage values consist
2405 * of a 2-byte length for both strings and their
2406 * individual lengths, a 2-byte length for the
2407 * character string, the character string without the
2408 * trailing nul, a 2-byte length for the character
2409 * set string, and the character set string without
2415 if (value
->string
.charset
!= NULL
)
2416 n
+= (int)strlen(value
->string
.charset
);
2418 if (value
->string
.text
!= NULL
)
2419 n
+= (int)strlen(value
->string
.text
);
2421 if (n
> (IPP_BUF_SIZE
- 2))
2423 DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
2424 "too long (%d)", n
));
2425 ipp_buffer_release(buffer
);
2429 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2431 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2433 DEBUG_puts("1ippWriteIO: Could not write IPP "
2435 ipp_buffer_release(buffer
);
2442 /* Length of entire value */
2446 /* Length of charset */
2447 if (value
->string
.charset
!= NULL
)
2448 n
= (int)strlen(value
->string
.charset
);
2458 memcpy(bufptr
, value
->string
.charset
, n
);
2462 /* Length of text */
2463 if (value
->string
.text
!= NULL
)
2464 n
= (int)strlen(value
->string
.text
);
2474 memcpy(bufptr
, value
->string
.text
, n
);
2480 case IPP_TAG_BEGIN_COLLECTION
:
2481 for (i
= 0, value
= attr
->values
;
2482 i
< attr
->num_values
;
2486 * Collections are written with the begin-collection
2487 * tag first with a value of 0 length, followed by the
2488 * attributes in the collection, then the end-collection
2492 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 5)
2494 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2496 DEBUG_puts("1ippWriteIO: Could not write IPP "
2498 ipp_buffer_release(buffer
);
2508 * Arrays and sets are done by sending additional
2509 * values with a zero-length name...
2512 *bufptr
++ = attr
->value_tag
;
2518 * Write a data length of 0 and flush the buffer...
2524 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2526 DEBUG_puts("1ippWriteIO: Could not write IPP "
2528 ipp_buffer_release(buffer
);
2535 * Then write the collection attribute...
2538 value
->collection
->state
= IPP_IDLE
;
2540 if (ippWriteIO(dst
, cb
, 1, ipp
,
2541 value
->collection
) == IPP_ERROR
)
2543 DEBUG_puts("1ippWriteIO: Unable to write collection value");
2544 ipp_buffer_release(buffer
);
2551 for (i
= 0, value
= attr
->values
;
2552 i
< attr
->num_values
;
2558 * Arrays and sets are done by sending additional
2559 * values with a zero-length name...
2562 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2564 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2566 DEBUG_puts("1ippWriteIO: Could not write IPP "
2568 ipp_buffer_release(buffer
);
2575 *bufptr
++ = attr
->value_tag
;
2581 * An unknown value might some new value that a
2582 * vendor has come up with. It consists of a
2583 * 2-byte length and the bytes in the unknown
2587 n
= value
->unknown
.length
;
2589 if (n
> (IPP_BUF_SIZE
- 2))
2591 DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
2593 ipp_buffer_release(buffer
);
2597 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2599 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2601 DEBUG_puts("1ippWriteIO: Could not write IPP "
2603 ipp_buffer_release(buffer
);
2610 /* Length of unknown value */
2617 memcpy(bufptr
, value
->unknown
.data
, n
);
2625 * Write the data out...
2628 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2630 DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
2631 ipp_buffer_release(buffer
);
2635 DEBUG_printf(("2ippWriteIO: wrote %d bytes",
2636 (int)(bufptr
- buffer
)));
2639 * If blocking is disabled, stop here...
2646 if (ipp
->current
== NULL
)
2649 * Done with all of the attributes; add the end-of-attributes
2650 * tag or end-collection attribute...
2655 buffer
[0] = IPP_TAG_END
;
2660 buffer
[0] = IPP_TAG_END_COLLECTION
;
2661 buffer
[1] = 0; /* empty name */
2663 buffer
[3] = 0; /* empty value */
2668 if ((*cb
)(dst
, buffer
, n
) < 0)
2670 DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
2671 ipp_buffer_release(buffer
);
2675 ipp
->state
= IPP_DATA
;
2683 break; /* anti-compiler-warning-code */
2686 ipp_buffer_release(buffer
);
2688 return (ipp
->state
);
2693 * '_ippAddAttr()' - Add a new attribute to the request.
2696 ipp_attribute_t
* /* O - New attribute */
2697 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2698 int num_values
) /* I - Number of values */
2700 ipp_attribute_t
*attr
; /* New attribute */
2703 DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp
, num_values
));
2705 if (!ipp
|| num_values
< 0)
2708 attr
= calloc(sizeof(ipp_attribute_t
) +
2709 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2713 attr
->num_values
= num_values
;
2715 if (ipp
->last
== NULL
)
2718 ipp
->last
->next
= attr
;
2723 DEBUG_printf(("5_ippAddAttr: Returning %p", attr
));
2730 * '_ippFreeAttr()' - Free an attribute.
2734 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2736 int i
; /* Looping var */
2737 ipp_value_t
*value
; /* Current value */
2740 DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr
));
2742 switch (attr
->value_tag
)
2746 case IPP_TAG_KEYWORD
:
2748 case IPP_TAG_URISCHEME
:
2749 case IPP_TAG_CHARSET
:
2750 case IPP_TAG_LANGUAGE
:
2751 case IPP_TAG_MIMETYPE
:
2752 for (i
= 0, value
= attr
->values
;
2753 i
< attr
->num_values
;
2755 _cupsStrFree(value
->string
.text
);
2758 case IPP_TAG_TEXTLANG
:
2759 case IPP_TAG_NAMELANG
:
2760 for (i
= 0, value
= attr
->values
;
2761 i
< attr
->num_values
;
2764 if (value
->string
.charset
&& i
== 0)
2765 _cupsStrFree(value
->string
.charset
);
2766 _cupsStrFree(value
->string
.text
);
2770 case IPP_TAG_INTEGER
:
2772 case IPP_TAG_BOOLEAN
:
2774 case IPP_TAG_RESOLUTION
:
2775 case IPP_TAG_RANGE
:
2778 case IPP_TAG_BEGIN_COLLECTION
:
2779 for (i
= 0, value
= attr
->values
;
2780 i
< attr
->num_values
;
2782 ippDelete(value
->collection
);
2785 case IPP_TAG_STRING
:
2786 for (i
= 0, value
= attr
->values
;
2787 i
< attr
->num_values
;
2789 free(value
->unknown
.data
);
2793 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2795 for (i
= 0, value
= attr
->values
;
2796 i
< attr
->num_values
;
2798 if (value
->unknown
.data
)
2799 free(value
->unknown
.data
);
2805 _cupsStrFree(attr
->name
);
2812 * 'ipp_buffer_get()' - Get a read/write buffer.
2815 static unsigned char * /* O - Buffer */
2816 ipp_buffer_get(void)
2818 _ipp_buffer_t
*buffer
; /* Current buffer */
2819 _cups_globals_t
*cg
= _cupsGlobals();
2823 for (buffer
= cg
->ipp_buffers
; buffer
; buffer
= buffer
->next
)
2830 if ((buffer
= malloc(sizeof(_ipp_buffer_t
))) == NULL
)
2834 buffer
->next
= cg
->ipp_buffers
;
2835 cg
->ipp_buffers
= buffer
;
2842 * 'ipp_buffer_release()' - Release a read/write buffer.
2846 ipp_buffer_release(unsigned char *b
) /* I - Buffer to release */
2848 ((_ipp_buffer_t
*)b
)->used
= 0;
2853 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2856 static size_t /* O - Size of IPP message */
2857 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2858 int collection
) /* I - 1 if a collection, 0 otherwise */
2860 int i
; /* Looping var */
2861 int bytes
; /* Number of bytes */
2862 ipp_attribute_t
*attr
; /* Current attribute */
2863 ipp_tag_t group
; /* Current group */
2864 ipp_value_t
*value
; /* Current value */
2871 * Start with 8 bytes for the IPP message header...
2874 bytes
= collection
? 0 : 8;
2877 * Then add the lengths of each attribute...
2880 group
= IPP_TAG_ZERO
;
2882 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2884 if (attr
->group_tag
!= group
&& !collection
)
2886 group
= attr
->group_tag
;
2887 if (group
== IPP_TAG_ZERO
)
2890 bytes
++; /* Group tag */
2896 DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2897 "bytes=%d", attr
->name
, attr
->num_values
, bytes
));
2899 bytes
+= (int)strlen(attr
->name
); /* Name */
2900 bytes
+= attr
->num_values
; /* Value tag for each value */
2901 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2902 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2905 bytes
+= 5; /* Add membername overhead */
2907 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2909 case IPP_TAG_INTEGER
:
2911 bytes
+= 4 * attr
->num_values
;
2914 case IPP_TAG_BOOLEAN
:
2915 bytes
+= attr
->num_values
;
2920 case IPP_TAG_KEYWORD
:
2922 case IPP_TAG_URISCHEME
:
2923 case IPP_TAG_CHARSET
:
2924 case IPP_TAG_LANGUAGE
:
2925 case IPP_TAG_MIMETYPE
:
2926 for (i
= 0, value
= attr
->values
;
2927 i
< attr
->num_values
;
2929 if (value
->string
.text
!= NULL
)
2930 bytes
+= (int)strlen(value
->string
.text
);
2934 bytes
+= 11 * attr
->num_values
;
2937 case IPP_TAG_RESOLUTION
:
2938 bytes
+= 9 * attr
->num_values
;
2941 case IPP_TAG_RANGE
:
2942 bytes
+= 8 * attr
->num_values
;
2945 case IPP_TAG_TEXTLANG
:
2946 case IPP_TAG_NAMELANG
:
2947 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2949 for (i
= 0, value
= attr
->values
;
2950 i
< attr
->num_values
;
2953 if (value
->string
.charset
!= NULL
)
2954 bytes
+= (int)strlen(value
->string
.charset
);
2956 if (value
->string
.text
!= NULL
)
2957 bytes
+= (int)strlen(value
->string
.text
);
2961 case IPP_TAG_BEGIN_COLLECTION
:
2962 for (i
= 0, value
= attr
->values
;
2963 i
< attr
->num_values
;
2965 bytes
+= (int)ipp_length(value
->collection
, 1);
2969 for (i
= 0, value
= attr
->values
;
2970 i
< attr
->num_values
;
2972 bytes
+= value
->unknown
.length
;
2978 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2979 * for the "end of collection" tag and return...
2987 DEBUG_printf(("8ipp_length: Returning %d bytes", bytes
));
2994 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2997 static ssize_t
/* O - Number of bytes read */
2998 ipp_read_http(http_t
*http
, /* I - Client connection */
2999 ipp_uchar_t
*buffer
, /* O - Buffer for data */
3000 size_t length
) /* I - Total length */
3002 int tbytes
, /* Total bytes read */
3003 bytes
; /* Bytes read this pass */
3004 char len
[32]; /* Length string */
3007 DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
3008 http
, buffer
, (int)length
));
3011 * Loop until all bytes are read...
3014 for (tbytes
= 0, bytes
= 0;
3015 tbytes
< (int)length
;
3016 tbytes
+= bytes
, buffer
+= bytes
)
3018 DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes
,
3021 if (http
->state
== HTTP_WAITING
)
3024 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
3027 * Do "fast read" from HTTP buffer directly...
3030 if (http
->used
> (int)(length
- tbytes
))
3031 bytes
= (int)(length
- tbytes
);
3036 buffer
[0] = http
->buffer
[0];
3038 memcpy(buffer
, http
->buffer
, bytes
);
3040 http
->used
-= bytes
;
3041 http
->data_remaining
-= bytes
;
3043 if (http
->data_remaining
<= INT_MAX
)
3044 http
->_data_remaining
= (int)http
->data_remaining
;
3046 http
->_data_remaining
= INT_MAX
;
3049 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
3051 if (http
->data_remaining
== 0)
3053 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
3056 * Get the trailing CR LF after the chunk...
3059 if (!httpGets(len
, sizeof(len
), http
))
3063 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
3065 if (http
->state
== HTTP_POST_RECV
)
3068 http
->state
= HTTP_WAITING
;
3075 * Wait a maximum of 1 second for data...
3078 if (!http
->blocking
)
3081 * Wait up to 10 seconds for more data on non-blocking sockets...
3084 if (!httpWait(http
, 10000))
3095 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) < 0)
3100 if (errno
!= EAGAIN
&& errno
!= EINTR
)
3106 else if (bytes
== 0)
3112 * Return the number of bytes read...
3115 if (tbytes
== 0 && bytes
< 0)
3118 DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes
));
3125 * 'ipp_read_file()' - Read IPP data from a file.
3128 static ssize_t
/* O - Number of bytes read */
3129 ipp_read_file(int *fd
, /* I - File descriptor */
3130 ipp_uchar_t
*buffer
, /* O - Read buffer */
3131 size_t length
) /* I - Number of bytes to read */
3134 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
3136 return (read(*fd
, buffer
, length
));
3142 * 'ipp_write_file()' - Write IPP data to a file.
3145 static ssize_t
/* O - Number of bytes written */
3146 ipp_write_file(int *fd
, /* I - File descriptor */
3147 ipp_uchar_t
*buffer
, /* I - Data to write */
3148 size_t length
) /* I - Number of bytes to write */
3151 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
3153 return (write(*fd
, buffer
, length
));
3160 * The following symbol definitions are provided only for KDE
3161 * compatibility during the CUPS 1.2 testing period and will be
3162 * removed in a future release of CUPS. These are PRIVATE APIs
3163 * from CUPS 1.1.x that the KDE developers chose to use...
3166 ipp_attribute_t
* /* O - New attribute */
3167 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
3168 int num_values
) /* I - Number of values */
3170 return (_ippAddAttr(ipp
, num_values
));
3174 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
3178 #endif /* __linux */
3182 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".