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)\n",
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)\n", 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)\n", 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)\n", 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)\n",
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)\n", 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)\n", 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\")\n", 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 values to lowercase and change _ to - as needed...
431 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
433 strlcpy(buffer
, value
, sizeof(buffer
));
436 for (bufptr
= buffer
; *bufptr
; bufptr
++)
440 *bufptr
= tolower(*bufptr
& 255);
444 * Initialize the attribute data...
447 attr
->name
= _cupsStrAlloc(name
);
448 attr
->group_tag
= group
;
449 attr
->value_tag
= type
;
450 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
451 charset
? _cupsStrAlloc(charset
) : NULL
;
452 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
453 value
? _cupsStrAlloc(value
) : NULL
;
460 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
463 ipp_attribute_t
* /* O - New attribute */
465 ipp_t
*ipp
, /* I - IPP message */
466 ipp_tag_t group
, /* I - IPP group */
467 ipp_tag_t type
, /* I - Type of attribute */
468 const char *name
, /* I - Name of attribute */
469 int num_values
, /* I - Number of values */
470 const char *charset
, /* I - Character set */
471 const char * const *values
) /* I - Values */
473 int i
; /* Looping var */
474 ipp_attribute_t
*attr
; /* New attribute */
475 ipp_value_t
*value
; /* Current value */
478 DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
479 "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)\n", ipp
,
480 group
, ippTagString(group
), type
, ippTagString(type
), name
,
481 num_values
, charset
, values
));
483 if (!ipp
|| !name
|| num_values
< 1)
486 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
490 * Initialize the attribute data...
493 attr
->name
= _cupsStrAlloc(name
);
494 attr
->group_tag
= group
;
495 attr
->value_tag
= type
;
497 for (i
= 0, value
= attr
->values
;
502 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
503 charset
? _cupsStrAlloc(charset
) : NULL
;
505 value
->string
.charset
= attr
->values
[0].string
.charset
;
510 * Force language to be English for the POSIX locale...
513 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(values
[i
], "C"))
514 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
517 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)values
[i
] :
518 _cupsStrAlloc(values
[i
]);
527 * 'ippAddRange()' - Add a range of values to an IPP message.
530 ipp_attribute_t
* /* O - New attribute */
531 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
532 ipp_tag_t group
, /* I - IPP group */
533 const char *name
, /* I - Name of attribute */
534 int lower
, /* I - Lower value */
535 int upper
) /* I - Upper value */
537 ipp_attribute_t
*attr
; /* New attribute */
540 DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
541 "upper=%d)\n", ipp
, group
, ippTagString(group
), name
, lower
,
547 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
550 attr
->name
= _cupsStrAlloc(name
);
551 attr
->group_tag
= group
;
552 attr
->value_tag
= IPP_TAG_RANGE
;
553 attr
->values
[0].range
.lower
= lower
;
554 attr
->values
[0].range
.upper
= upper
;
561 * 'ippAddRanges()' - Add ranges of values to an IPP message.
564 ipp_attribute_t
* /* O - New attribute */
565 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
566 ipp_tag_t group
, /* I - IPP group */
567 const char *name
, /* I - Name of attribute */
568 int num_values
, /* I - Number of values */
569 const int *lower
, /* I - Lower values */
570 const int *upper
) /* I - Upper values */
572 int i
; /* Looping var */
573 ipp_attribute_t
*attr
; /* New attribute */
574 ipp_value_t
*value
; /* Current value */
577 DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
578 "num_values=%d, lower=%p, upper=%p)\n", ipp
, group
,
579 ippTagString(group
), name
, num_values
, lower
, upper
));
581 if (!ipp
|| !name
|| num_values
< 1)
584 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
587 attr
->name
= _cupsStrAlloc(name
);
588 attr
->group_tag
= group
;
589 attr
->value_tag
= IPP_TAG_RANGE
;
591 if (lower
!= NULL
&& upper
!= NULL
)
592 for (i
= 0, value
= attr
->values
;
596 value
->range
.lower
= lower
[i
];
597 value
->range
.upper
= upper
[i
];
605 * 'ippAddResolution()' - Add a resolution value to an IPP message.
608 ipp_attribute_t
* /* O - New attribute */
609 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
610 ipp_tag_t group
, /* I - IPP group */
611 const char *name
, /* I - Name of attribute */
612 ipp_res_t units
, /* I - Units for resolution */
613 int xres
, /* I - X resolution */
614 int yres
) /* I - Y resolution */
616 ipp_attribute_t
*attr
; /* New attribute */
619 DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
620 "units=%d, xres=%d, yres=%d)\n", ipp
, group
,
621 ippTagString(group
), name
, units
, xres
, yres
));
626 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
629 attr
->name
= _cupsStrAlloc(name
);
630 attr
->group_tag
= group
;
631 attr
->value_tag
= IPP_TAG_RESOLUTION
;
632 attr
->values
[0].resolution
.xres
= xres
;
633 attr
->values
[0].resolution
.yres
= yres
;
634 attr
->values
[0].resolution
.units
= units
;
641 * 'ippAddResolutions()' - Add resolution values to an IPP message.
644 ipp_attribute_t
* /* O - New attribute */
645 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
646 ipp_tag_t group
, /* I - IPP group */
647 const char *name
, /* I - Name of attribute */
648 int num_values
,/* I - Number of values */
649 ipp_res_t units
, /* I - Units for resolution */
650 const int *xres
, /* I - X resolutions */
651 const int *yres
) /* I - Y resolutions */
653 int i
; /* Looping var */
654 ipp_attribute_t
*attr
; /* New attribute */
655 ipp_value_t
*value
; /* Current value */
658 DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
659 "num_value=%d, units=%d, xres=%p, yres=%p)\n", ipp
, group
,
660 ippTagString(group
), name
, num_values
, units
, xres
, yres
));
662 if (!ipp
|| !name
|| num_values
< 1)
665 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
668 attr
->name
= _cupsStrAlloc(name
);
669 attr
->group_tag
= group
;
670 attr
->value_tag
= IPP_TAG_RESOLUTION
;
672 if (xres
!= NULL
&& yres
!= NULL
)
673 for (i
= 0, value
= attr
->values
;
677 value
->resolution
.xres
= xres
[i
];
678 value
->resolution
.yres
= yres
[i
];
679 value
->resolution
.units
= units
;
687 * 'ippAddSeparator()' - Add a group separator to an IPP message.
690 ipp_attribute_t
* /* O - New attribute */
691 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
693 ipp_attribute_t
*attr
; /* New attribute */
696 DEBUG_printf(("ippAddSeparator(ipp=%p)\n", ipp
));
701 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
704 attr
->group_tag
= IPP_TAG_ZERO
;
705 attr
->value_tag
= IPP_TAG_ZERO
;
712 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
716 time_t /* O - UNIX time value */
717 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
719 struct tm unixdate
; /* UNIX date/time info */
720 time_t t
; /* Computed time */
726 memset(&unixdate
, 0, sizeof(unixdate
));
729 * RFC-1903 date/time format is:
731 * Byte(s) Description
732 * ------- -----------
733 * 0-1 Year (0 to 65535)
737 * 5 Minutes (0 to 59)
738 * 6 Seconds (0 to 60, 60 = "leap second")
739 * 7 Deciseconds (0 to 9)
741 * 9 UTC hours (0 to 11)
742 * 10 UTC minutes (0 to 59)
745 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
746 unixdate
.tm_mon
= date
[2] - 1;
747 unixdate
.tm_mday
= date
[3];
748 unixdate
.tm_hour
= date
[4];
749 unixdate
.tm_min
= date
[5];
750 unixdate
.tm_sec
= date
[6];
752 t
= mktime(&unixdate
);
755 t
+= date
[9] * 3600 + date
[10] * 60;
757 t
-= date
[9] * 3600 + date
[10] * 60;
764 * 'ippDelete()' - Delete an IPP message.
768 ippDelete(ipp_t
*ipp
) /* I - IPP message */
770 ipp_attribute_t
*attr
, /* Current attribute */
771 *next
; /* Next attribute */
774 DEBUG_printf(("ippDelete(ipp=%p)\n", ipp
));
779 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
790 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
792 * @since CUPS 1.1.19/Mac OS X 10.3@
797 ipp_t
*ipp
, /* I - IPP message */
798 ipp_attribute_t
*attr
) /* I - Attribute to delete */
800 ipp_attribute_t
*current
, /* Current attribute */
801 *prev
; /* Previous attribute */
804 DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p)\n", ipp
, attr
));
807 * Find the attribute in the list...
810 for (current
= ipp
->attrs
, prev
= NULL
;
811 current
!= NULL
&& current
!= attr
;
812 prev
= current
, current
= current
->next
);
817 * Found it, remove the attribute from the list...
821 prev
->next
= current
->next
;
823 ipp
->attrs
= current
->next
;
825 if (current
== ipp
->last
)
829 * Free memory used by the attribute...
832 _ippFreeAttr(current
);
838 * 'ippFindAttribute()' - Find a named attribute in a request...
841 ipp_attribute_t
* /* O - Matching attribute */
842 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
843 const char *name
, /* I - Name of attribute */
844 ipp_tag_t type
) /* I - Type of attribute */
846 DEBUG_printf(("ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))\n", ipp
,
847 name
, type
, ippTagString(type
)));
853 * Reset the current pointer...
859 * Search for the attribute...
862 return (ippFindNextAttribute(ipp
, name
, type
));
867 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
870 ipp_attribute_t
* /* O - Matching attribute */
871 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
872 const char *name
, /* I - Name of attribute */
873 ipp_tag_t type
) /* I - Type of attribute */
875 ipp_attribute_t
*attr
; /* Current atttribute */
876 ipp_tag_t value_tag
; /* Value tag */
879 DEBUG_printf(("ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))\n",
880 ipp
, name
, type
, ippTagString(type
)));
887 ipp
->prev
= ipp
->current
;
888 attr
= ipp
->current
->next
;
896 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
898 DEBUG_printf(("ippFindAttribute: attr=%p, name=\"%s\"\n", attr
,
901 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
903 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
904 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
905 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
906 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
922 * 'ippLength()' - Compute the length of an IPP message.
925 size_t /* O - Size of IPP message */
926 ippLength(ipp_t
*ipp
) /* I - IPP message */
928 return (ipp_length(ipp
, 0));
933 * 'ippNew()' - Allocate a new IPP message.
936 ipp_t
* /* O - New IPP message */
939 ipp_t
*temp
; /* New IPP message */
942 DEBUG_puts("ippNew()");
944 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
947 * Default to IPP 1.1...
950 temp
->request
.any
.version
[0] = 1;
951 temp
->request
.any
.version
[1] = 1;
954 DEBUG_printf(("ippNew: %p\n", temp
));
961 * 'ippNewRequest()' - Allocate a new IPP request message.
963 * The new request message is initialized with the attributes-charset and
964 * attributes-natural-language attributes added. The
965 * attributes-natural-language value is derived from the current locale.
967 * @since CUPS 1.2/Mac OS X 10.5@
970 ipp_t
* /* O - IPP request message */
971 ippNewRequest(ipp_op_t op
) /* I - Operation code */
973 ipp_t
*request
; /* IPP request message */
974 cups_lang_t
*language
; /* Current language localization */
977 DEBUG_printf(("ippNewRequest(op=%02x(%s))\n", op
, ippOpString(op
)));
980 * Create a new IPP message...
983 if ((request
= ippNew()) == NULL
)
987 * Set the operation and request ID...
990 request
->request
.op
.operation_id
= op
;
991 request
->request
.op
.request_id
= 1;
994 * Use UTF-8 as the character set...
997 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
998 "attributes-charset", NULL
, "utf-8");
1001 * Get the language from the current locale...
1004 language
= cupsLangDefault();
1006 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1007 "attributes-natural-language", NULL
, language
->language
);
1010 * Return the new request...
1018 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
1021 ipp_state_t
/* O - Current state */
1022 ippRead(http_t
*http
, /* I - HTTP connection */
1023 ipp_t
*ipp
) /* I - IPP data */
1025 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
"\n",
1026 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
1031 DEBUG_printf(("ippRead: http->state=%d, http->used=%d\n", http
->state
,
1034 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
, http
->blocking
, NULL
,
1040 * 'ippReadFile()' - Read data for an IPP message from a file.
1042 * @since CUPS 1.1.19/Mac OS X 10.3@
1045 ipp_state_t
/* O - Current state */
1046 ippReadFile(int fd
, /* I - HTTP data */
1047 ipp_t
*ipp
) /* I - IPP data */
1049 DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)\n", fd
, ipp
));
1051 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1056 * 'ippReadIO()' - Read data for an IPP message.
1058 * @since CUPS 1.2/Mac OS X 10.5@
1061 ipp_state_t
/* O - Current state */
1062 ippReadIO(void *src
, /* I - Data source */
1063 ipp_iocb_t cb
, /* I - Read callback function */
1064 int blocking
, /* I - Use blocking IO? */
1065 ipp_t
*parent
, /* I - Parent request, if any */
1066 ipp_t
*ipp
) /* I - IPP data */
1068 int n
; /* Length of data */
1069 unsigned char *buffer
, /* Data buffer */
1070 string
[IPP_MAX_NAME
],
1071 /* Small string buffer */
1072 *bufptr
; /* Pointer into buffer */
1073 ipp_attribute_t
*attr
; /* Current attribute */
1074 ipp_tag_t tag
; /* Current tag */
1075 ipp_tag_t value_tag
; /* Current value tag */
1076 ipp_value_t
*value
; /* Current value */
1079 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)\n",
1080 src
, cb
, blocking
, parent
, ipp
));
1081 DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp
->state
));
1086 if ((buffer
= ipp_buffer_get()) == NULL
)
1088 DEBUG_puts("ippReadIO: Unable to get read buffer!");
1095 ipp
->state
++; /* Avoid common problem... */
1101 * Get the request header...
1104 if ((*cb
)(src
, buffer
, 8) < 8)
1106 DEBUG_puts("ippReadIO: Unable to read header!");
1107 ipp_buffer_release(buffer
);
1112 * Verify the major version number...
1115 if (buffer
[0] != 1 && buffer
[0] != 2)
1117 DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n",
1118 buffer
[0], buffer
[1]));
1119 ipp_buffer_release(buffer
);
1124 * Then copy the request header over...
1127 ipp
->request
.any
.version
[0] = buffer
[0];
1128 ipp
->request
.any
.version
[1] = buffer
[1];
1129 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1130 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1131 buffer
[6]) << 8) | buffer
[7];
1133 DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1134 DEBUG_printf(("ippReadIO: op_status=%04x\n",
1135 ipp
->request
.any
.op_status
));
1136 DEBUG_printf(("ippReadIO: request_id=%d\n",
1137 ipp
->request
.any
.request_id
));
1140 ipp
->state
= IPP_ATTRIBUTE
;
1141 ipp
->current
= NULL
;
1142 ipp
->curtag
= IPP_TAG_ZERO
;
1143 ipp
->prev
= ipp
->last
;
1146 * If blocking is disabled, stop here...
1152 case IPP_ATTRIBUTE
:
1155 if ((*cb
)(src
, buffer
, 1) < 1)
1157 DEBUG_puts("ippReadIO: Callback returned EOF/error");
1158 ipp_buffer_release(buffer
);
1162 DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
1163 ipp
->current
, ipp
->prev
));
1166 * Read this attribute...
1169 tag
= (ipp_tag_t
)buffer
[0];
1171 if (tag
== IPP_TAG_END
)
1174 * No more attributes left...
1177 DEBUG_puts("ippReadIO: IPP_TAG_END!");
1179 ipp
->state
= IPP_DATA
;
1182 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1185 * Group tag... Set the current group and continue...
1188 if (ipp
->curtag
== tag
)
1189 ipp
->prev
= ippAddSeparator(ipp
);
1190 else if (ipp
->current
)
1191 ipp
->prev
= ipp
->current
;
1194 ipp
->current
= NULL
;
1195 DEBUG_printf(("ippReadIO: group tag=%x(%s), ipp->prev=%p\n", tag
,
1196 ippTagString(tag
), ipp
->prev
));
1200 DEBUG_printf(("ippReadIO: value tag=%x(%s)\n", tag
,
1201 ippTagString(tag
)));
1207 if ((*cb
)(src
, buffer
, 2) < 2)
1209 DEBUG_puts("ippReadIO: unable to read name length!");
1210 ipp_buffer_release(buffer
);
1214 n
= (buffer
[0] << 8) | buffer
[1];
1216 if (n
>= IPP_BUF_SIZE
)
1218 DEBUG_printf(("ippReadIO: bad name length %d!\n", n
));
1219 ipp_buffer_release(buffer
);
1223 DEBUG_printf(("ippReadIO: name length=%d\n", n
));
1225 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1226 tag
!= IPP_TAG_END_COLLECTION
)
1229 * More values for current attribute...
1232 if (ipp
->current
== NULL
)
1234 DEBUG_puts("ippReadIO: Attribute without name and no current");
1235 ipp_buffer_release(buffer
);
1239 attr
= ipp
->current
;
1240 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1243 * Make sure we aren't adding a new value of a different
1247 if (value_tag
== IPP_TAG_ZERO
)
1250 * Setting the value of a collection member...
1253 attr
->value_tag
= tag
;
1255 else if ((value_tag
>= IPP_TAG_TEXTLANG
&&
1256 value_tag
<= IPP_TAG_MIMETYPE
))
1259 * String values can sometimes come across in different
1260 * forms; accept sets of differing values...
1263 if ((tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
) &&
1264 tag
!= IPP_TAG_NOVALUE
)
1266 DEBUG_printf(("ippReadIO: 1setOf value tag %x(%s) != %x(%s)\n",
1267 value_tag
, ippTagString(value_tag
), tag
,
1268 ippTagString(tag
)));
1269 ipp_buffer_release(buffer
);
1273 else if (value_tag
!= tag
)
1275 DEBUG_printf(("ippReadIO: value tag %x(%s) != %x(%s)\n",
1276 value_tag
, ippTagString(value_tag
), tag
,
1277 ippTagString(tag
)));
1278 ipp_buffer_release(buffer
);
1283 * Finally, reallocate the attribute array as needed...
1286 if (attr
->num_values
== 1 ||
1287 (attr
->num_values
> 0 &&
1288 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1290 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1293 DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
1294 attr
->num_values
+ IPP_MAX_VALUES
));
1297 * Reallocate memory...
1300 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1301 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1302 sizeof(ipp_value_t
))) == NULL
)
1304 DEBUG_puts("ippReadIO: Unable to resize attribute");
1305 ipp_buffer_release(buffer
);
1312 * Reset pointers in the list...
1316 ipp
->prev
->next
= temp
;
1320 attr
= ipp
->current
= ipp
->last
= temp
;
1324 else if (tag
== IPP_TAG_MEMBERNAME
)
1327 * Name must be length 0!
1332 DEBUG_puts("ippReadIO: member name not empty!");
1333 ipp_buffer_release(buffer
);
1338 ipp
->prev
= ipp
->current
;
1340 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1342 DEBUG_printf(("ippReadIO: membername, ipp->current=%p, "
1343 "ipp->prev=%p\n", ipp
->current
, ipp
->prev
));
1345 attr
->group_tag
= ipp
->curtag
;
1346 attr
->value_tag
= IPP_TAG_ZERO
;
1347 attr
->num_values
= 0;
1349 else if (tag
!= IPP_TAG_END_COLLECTION
)
1352 * New attribute; read the name and add it...
1355 if ((*cb
)(src
, buffer
, n
) < n
)
1357 DEBUG_puts("ippReadIO: unable to read name!");
1358 ipp_buffer_release(buffer
);
1365 ipp
->prev
= ipp
->current
;
1367 if ((attr
= ipp
->current
= _ippAddAttr(ipp
, 1)) == NULL
)
1369 DEBUG_puts("ippReadIO: unable to allocate attribute!");
1370 ipp_buffer_release(buffer
);
1374 DEBUG_printf(("ippReadIO: name=\"%s\", ipp->current=%p, "
1375 "ipp->prev=%p\n", buffer
, ipp
->current
, ipp
->prev
));
1377 attr
->group_tag
= ipp
->curtag
;
1378 attr
->value_tag
= tag
;
1379 attr
->name
= _cupsStrAlloc((char *)buffer
);
1380 attr
->num_values
= 0;
1385 if (tag
!= IPP_TAG_END_COLLECTION
)
1386 value
= attr
->values
+ attr
->num_values
;
1390 if ((*cb
)(src
, buffer
, 2) < 2)
1392 DEBUG_puts("ippReadIO: unable to read value length!");
1393 ipp_buffer_release(buffer
);
1397 n
= (buffer
[0] << 8) | buffer
[1];
1398 DEBUG_printf(("ippReadIO: value length=%d\n", n
));
1402 case IPP_TAG_INTEGER
:
1406 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1407 ipp_buffer_release(buffer
);
1411 if ((*cb
)(src
, buffer
, 4) < 4)
1413 DEBUG_puts("ippReadIO: Unable to read integer value!");
1414 ipp_buffer_release(buffer
);
1418 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1424 case IPP_TAG_BOOLEAN
:
1427 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1428 ipp_buffer_release(buffer
);
1432 if ((*cb
)(src
, buffer
, 1) < 1)
1434 DEBUG_puts("ippReadIO: Unable to read boolean value!");
1435 ipp_buffer_release(buffer
);
1439 value
->boolean
= buffer
[0];
1442 case IPP_TAG_NOVALUE
:
1443 case IPP_TAG_NOTSETTABLE
:
1444 case IPP_TAG_DELETEATTR
:
1445 case IPP_TAG_ADMINDEFINE
:
1446 if (attr
->value_tag
== IPP_TAG_NOVALUE
)
1451 attr
->value_tag
= IPP_TAG_TEXT
;
1456 case IPP_TAG_KEYWORD
:
1458 case IPP_TAG_URISCHEME
:
1459 case IPP_TAG_CHARSET
:
1460 case IPP_TAG_LANGUAGE
:
1461 case IPP_TAG_MIMETYPE
:
1462 if (n
>= IPP_BUF_SIZE
)
1464 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1465 ipp_buffer_release(buffer
);
1469 if ((*cb
)(src
, buffer
, n
) < n
)
1471 DEBUG_puts("ippReadIO: unable to read name!");
1472 ipp_buffer_release(buffer
);
1477 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1478 DEBUG_printf(("ippReadIO: value=\"%s\"\n",
1479 value
->string
.text
));
1485 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1486 ipp_buffer_release(buffer
);
1490 if ((*cb
)(src
, value
->date
, 11) < 11)
1492 DEBUG_puts("ippReadIO: Unable to date integer value!");
1493 ipp_buffer_release(buffer
);
1498 case IPP_TAG_RESOLUTION
:
1501 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1502 ipp_buffer_release(buffer
);
1506 if ((*cb
)(src
, buffer
, 9) < 9)
1508 DEBUG_puts("ippReadIO: Unable to read resolution value!");
1509 ipp_buffer_release(buffer
);
1513 value
->resolution
.xres
=
1514 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1516 value
->resolution
.yres
=
1517 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1519 value
->resolution
.units
=
1520 (ipp_res_t
)buffer
[8];
1523 case IPP_TAG_RANGE
:
1526 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1527 ipp_buffer_release(buffer
);
1531 if ((*cb
)(src
, buffer
, 8) < 8)
1533 DEBUG_puts("ippReadIO: Unable to read range value!");
1534 ipp_buffer_release(buffer
);
1538 value
->range
.lower
=
1539 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1541 value
->range
.upper
=
1542 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1546 case IPP_TAG_TEXTLANG
:
1547 case IPP_TAG_NAMELANG
:
1548 if (n
>= IPP_BUF_SIZE
|| n
< 4)
1550 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1551 ipp_buffer_release(buffer
);
1555 if ((*cb
)(src
, buffer
, n
) < n
)
1557 DEBUG_puts("ippReadIO: Unable to read string w/language value!");
1558 ipp_buffer_release(buffer
);
1565 * text-with-language and name-with-language are composite
1574 n
= (bufptr
[0] << 8) | bufptr
[1];
1576 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
) ||
1577 n
>= sizeof(string
))
1579 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1580 ipp_buffer_release(buffer
);
1584 memcpy(string
, bufptr
+ 2, n
);
1587 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1590 n
= (bufptr
[0] << 8) | bufptr
[1];
1592 if ((bufptr
+ 2 + n
) >= (buffer
+ IPP_BUF_SIZE
))
1594 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1595 ipp_buffer_release(buffer
);
1599 bufptr
[2 + n
] = '\0';
1600 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1603 case IPP_TAG_BEGIN_COLLECTION
:
1605 * Oh, boy, here comes a collection value, so read it...
1608 value
->collection
= ippNew();
1612 DEBUG_puts("ippReadIO: begCollection tag with value length "
1614 ipp_buffer_release(buffer
);
1618 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1620 DEBUG_puts("ippReadIO: Unable to read collection value!");
1621 ipp_buffer_release(buffer
);
1626 case IPP_TAG_END_COLLECTION
:
1627 ipp_buffer_release(buffer
);
1631 DEBUG_puts("ippReadIO: endCollection tag with value length "
1636 DEBUG_puts("ippReadIO: endCollection tag...");
1637 return (ipp
->state
= IPP_DATA
);
1639 case IPP_TAG_MEMBERNAME
:
1641 * The value the name of the member in the collection, which
1642 * we need to carry over...
1645 if (n
>= IPP_BUF_SIZE
)
1647 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1648 ipp_buffer_release(buffer
);
1652 if ((*cb
)(src
, buffer
, n
) < n
)
1654 DEBUG_puts("ippReadIO: Unable to read member name value!");
1655 ipp_buffer_release(buffer
);
1660 attr
->name
= _cupsStrAlloc((char *)buffer
);
1663 * Since collection members are encoded differently than
1664 * regular attributes, make sure we don't start with an
1668 attr
->num_values
--;
1670 DEBUG_printf(("ippReadIO: member name=\"%s\"\n", attr
->name
));
1673 default : /* Other unsupported values */
1674 if (n
> IPP_MAX_LENGTH
)
1676 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1677 ipp_buffer_release(buffer
);
1683 DEBUG_puts("ippReadIO: NULL value!");
1684 ipp_buffer_release(buffer
);
1688 value
->unknown
.length
= n
;
1691 if ((value
->unknown
.data
= malloc(n
)) == NULL
)
1693 DEBUG_puts("ippReadIO: Unable to allocate value");
1694 ipp_buffer_release(buffer
);
1698 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1700 DEBUG_puts("ippReadIO: Unable to read unsupported value!");
1701 ipp_buffer_release(buffer
);
1706 value
->unknown
.data
= NULL
;
1710 attr
->num_values
++;
1713 * If blocking is disabled, stop here...
1725 break; /* anti-compiler-warning-code */
1728 DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp
->state
));
1729 ipp_buffer_release(buffer
);
1731 return (ipp
->state
);
1736 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1739 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1740 ippTimeToDate(time_t t
) /* I - UNIX time value */
1742 struct tm
*unixdate
; /* UNIX unixdate/time info */
1743 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1744 /* RFC-1903 date/time data */
1748 * RFC-1903 date/time format is:
1750 * Byte(s) Description
1751 * ------- -----------
1752 * 0-1 Year (0 to 65535)
1756 * 5 Minutes (0 to 59)
1757 * 6 Seconds (0 to 60, 60 = "leap second")
1758 * 7 Deciseconds (0 to 9)
1760 * 9 UTC hours (0 to 11)
1761 * 10 UTC minutes (0 to 59)
1764 unixdate
= gmtime(&t
);
1765 unixdate
->tm_year
+= 1900;
1767 date
[0] = unixdate
->tm_year
>> 8;
1768 date
[1] = unixdate
->tm_year
;
1769 date
[2] = unixdate
->tm_mon
+ 1;
1770 date
[3] = unixdate
->tm_mday
;
1771 date
[4] = unixdate
->tm_hour
;
1772 date
[5] = unixdate
->tm_min
;
1773 date
[6] = unixdate
->tm_sec
;
1784 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1787 ipp_state_t
/* O - Current state */
1788 ippWrite(http_t
*http
, /* I - HTTP connection */
1789 ipp_t
*ipp
) /* I - IPP data */
1791 DEBUG_printf(("ippWrite(http=%p, ipp=%p)\n", http
, ipp
));
1796 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
,
1797 http
->blocking
, NULL
, ipp
));
1802 * 'ippWriteFile()' - Write data for an IPP message to a file.
1804 * @since CUPS 1.1.19/Mac OS X 10.3@
1807 ipp_state_t
/* O - Current state */
1808 ippWriteFile(int fd
, /* I - HTTP data */
1809 ipp_t
*ipp
) /* I - IPP data */
1811 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)\n", fd
, ipp
));
1813 ipp
->state
= IPP_IDLE
;
1815 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1820 * 'ippWriteIO()' - Write data for an IPP message.
1822 * @since CUPS 1.2/Mac OS X 10.5@
1825 ipp_state_t
/* O - Current state */
1826 ippWriteIO(void *dst
, /* I - Destination */
1827 ipp_iocb_t cb
, /* I - Write callback function */
1828 int blocking
, /* I - Use blocking IO? */
1829 ipp_t
*parent
, /* I - Parent IPP message */
1830 ipp_t
*ipp
) /* I - IPP data */
1832 int i
; /* Looping var */
1833 int n
; /* Length of data */
1834 unsigned char *buffer
, /* Data buffer */
1835 *bufptr
; /* Pointer into buffer */
1836 ipp_attribute_t
*attr
; /* Current attribute */
1837 ipp_value_t
*value
; /* Current value */
1840 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)\n",
1841 dst
, cb
, blocking
, parent
, ipp
));
1846 if ((buffer
= ipp_buffer_get()) == NULL
)
1848 DEBUG_puts("ippWriteIO: Unable to get write buffer");
1855 ipp
->state
++; /* Avoid common problem... */
1861 * Send the request header:
1864 * Operation/Status Code = 2 bytes
1865 * Request ID = 4 bytes
1871 *bufptr
++ = ipp
->request
.any
.version
[0];
1872 *bufptr
++ = ipp
->request
.any
.version
[1];
1873 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1874 *bufptr
++ = ipp
->request
.any
.op_status
;
1875 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1876 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1877 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1878 *bufptr
++ = ipp
->request
.any
.request_id
;
1880 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1882 DEBUG_puts("ippWriteIO: Could not write IPP header...");
1883 ipp_buffer_release(buffer
);
1889 * Reset the state engine to point to the first attribute
1890 * in the request/response, with no current group.
1893 ipp
->state
= IPP_ATTRIBUTE
;
1894 ipp
->current
= ipp
->attrs
;
1895 ipp
->curtag
= IPP_TAG_ZERO
;
1897 DEBUG_printf(("ippWriteIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1898 DEBUG_printf(("ippWriteIO: op_status=%04x\n",
1899 ipp
->request
.any
.op_status
));
1900 DEBUG_printf(("ippWriteIO: request_id=%d\n",
1901 ipp
->request
.any
.request_id
));
1904 * If blocking is disabled, stop here...
1910 case IPP_ATTRIBUTE
:
1911 while (ipp
->current
!= NULL
)
1914 * Write this attribute...
1918 attr
= ipp
->current
;
1920 ipp
->current
= ipp
->current
->next
;
1922 if (ipp
->curtag
!= attr
->group_tag
&& parent
== NULL
)
1925 * Send a group tag byte...
1928 ipp
->curtag
= attr
->group_tag
;
1930 if (attr
->group_tag
== IPP_TAG_ZERO
)
1933 DEBUG_printf(("ippWriteIO: wrote group tag=%x(%s)\n",
1934 attr
->group_tag
, ippTagString(attr
->group_tag
)));
1935 *bufptr
++ = attr
->group_tag
;
1937 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1941 * Write the attribute tag and name. The current implementation
1942 * does not support the extension value tags above 0x7f, so all
1943 * value tags are 1 byte.
1945 * The attribute name length does not include the trailing nul
1946 * character in the source string.
1948 * Collection values (parent != NULL) are written differently...
1954 * Get the length of the attribute name, and make sure it won't
1955 * overflow the buffer...
1958 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 4))
1960 DEBUG_printf(("ippWriteIO: Attribute name too long (%d)\n", n
));
1961 ipp_buffer_release(buffer
);
1966 * Write the value tag, name length, and name string...
1969 DEBUG_printf(("ippWriteIO: writing value tag=%x(%s)\n",
1970 attr
->value_tag
, ippTagString(attr
->value_tag
)));
1971 DEBUG_printf(("ippWriteIO: writing name=%d,\"%s\"\n", n
,
1974 *bufptr
++ = attr
->value_tag
;
1977 memcpy(bufptr
, attr
->name
, n
);
1983 * Get the length of the attribute name, and make sure it won't
1984 * overflow the buffer...
1987 if ((n
= (int)strlen(attr
->name
)) > (IPP_BUF_SIZE
- 7))
1989 DEBUG_printf(("ippWriteIO: Attribute name too long (%d)\n", n
));
1990 ipp_buffer_release(buffer
);
1995 * Write the member name tag, name length, name string, value tag,
1996 * and empty name for the collection member attribute...
1999 DEBUG_printf(("ippWriteIO: writing value tag=%x(memberName)\n",
2000 IPP_TAG_MEMBERNAME
));
2001 DEBUG_printf(("ippWriteIO: writing name=%d,\"%s\"\n", n
,
2003 DEBUG_printf(("ippWriteIO: writing value tag=%x(%s)\n",
2004 attr
->value_tag
, ippTagString(attr
->value_tag
)));
2005 DEBUG_puts("ippWriteIO: writing name=0,\"\"\n");
2007 *bufptr
++ = IPP_TAG_MEMBERNAME
;
2012 memcpy(bufptr
, attr
->name
, n
);
2015 *bufptr
++ = attr
->value_tag
;
2021 * Now write the attribute value(s)...
2024 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2026 case IPP_TAG_INTEGER
:
2028 for (i
= 0, value
= attr
->values
;
2029 i
< attr
->num_values
;
2032 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 9)
2034 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2036 DEBUG_puts("ippWriteIO: Could not write IPP "
2038 ipp_buffer_release(buffer
);
2048 * Arrays and sets are done by sending additional
2049 * values with a zero-length name...
2052 *bufptr
++ = attr
->value_tag
;
2058 * Integers and enumerations are both 4-byte signed
2059 * (twos-complement) values.
2061 * Put the 2-byte length and 4-byte value into the buffer...
2066 *bufptr
++ = value
->integer
>> 24;
2067 *bufptr
++ = value
->integer
>> 16;
2068 *bufptr
++ = value
->integer
>> 8;
2069 *bufptr
++ = value
->integer
;
2073 case IPP_TAG_BOOLEAN
:
2074 for (i
= 0, value
= attr
->values
;
2075 i
< attr
->num_values
;
2078 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 6)
2080 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2082 DEBUG_puts("ippWriteIO: Could not write IPP "
2084 ipp_buffer_release(buffer
);
2094 * Arrays and sets are done by sending additional
2095 * values with a zero-length name...
2098 *bufptr
++ = attr
->value_tag
;
2104 * Boolean values are 1-byte; 0 = false, 1 = true.
2106 * Put the 2-byte length and 1-byte value into the buffer...
2111 *bufptr
++ = value
->boolean
;
2117 case IPP_TAG_KEYWORD
:
2119 case IPP_TAG_URISCHEME
:
2120 case IPP_TAG_CHARSET
:
2121 case IPP_TAG_LANGUAGE
:
2122 case IPP_TAG_MIMETYPE
:
2123 for (i
= 0, value
= attr
->values
;
2124 i
< attr
->num_values
;
2130 * Arrays and sets are done by sending additional
2131 * values with a zero-length name...
2134 DEBUG_printf(("ippWriteIO: writing value tag=%x(%s)\n",
2136 ippTagString(attr
->value_tag
)));
2137 DEBUG_printf(("ippWriteIO: writing name=0,\"\"\n"));
2139 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2141 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2143 DEBUG_puts("ippWriteIO: Could not write IPP "
2145 ipp_buffer_release(buffer
);
2152 *bufptr
++ = attr
->value_tag
;
2157 if (value
->string
.text
!= NULL
)
2158 n
= (int)strlen(value
->string
.text
);
2162 if (n
> (IPP_BUF_SIZE
- 2))
2164 DEBUG_printf(("ippWriteIO: String too long (%d)\n", n
));
2165 ipp_buffer_release(buffer
);
2169 DEBUG_printf(("ippWriteIO: writing string=%d,\"%s\"\n", n
,
2170 value
->string
.text
));
2172 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2174 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2176 DEBUG_puts("ippWriteIO: Could not write IPP "
2178 ipp_buffer_release(buffer
);
2186 * All simple strings consist of the 2-byte length and
2187 * character data without the trailing nul normally found
2188 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2189 * bytes since the 2-byte length is a signed (twos-complement)
2192 * Put the 2-byte length and string characters in the buffer.
2200 memcpy(bufptr
, value
->string
.text
, n
);
2207 for (i
= 0, value
= attr
->values
;
2208 i
< attr
->num_values
;
2211 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 16)
2213 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2215 DEBUG_puts("ippWriteIO: Could not write IPP "
2217 ipp_buffer_release(buffer
);
2227 * Arrays and sets are done by sending additional
2228 * values with a zero-length name...
2231 *bufptr
++ = attr
->value_tag
;
2237 * Date values consist of a 2-byte length and an
2238 * 11-byte date/time structure defined by RFC 1903.
2240 * Put the 2-byte length and 11-byte date/time
2241 * structure in the buffer.
2246 memcpy(bufptr
, value
->date
, 11);
2251 case IPP_TAG_RESOLUTION
:
2252 for (i
= 0, value
= attr
->values
;
2253 i
< attr
->num_values
;
2256 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 14)
2258 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2260 DEBUG_puts("ippWriteIO: Could not write IPP "
2262 ipp_buffer_release(buffer
);
2272 * Arrays and sets are done by sending additional
2273 * values with a zero-length name...
2276 *bufptr
++ = attr
->value_tag
;
2282 * Resolution values consist of a 2-byte length,
2283 * 4-byte horizontal resolution value, 4-byte vertical
2284 * resolution value, and a 1-byte units value.
2286 * Put the 2-byte length and resolution value data
2292 *bufptr
++ = value
->resolution
.xres
>> 24;
2293 *bufptr
++ = value
->resolution
.xres
>> 16;
2294 *bufptr
++ = value
->resolution
.xres
>> 8;
2295 *bufptr
++ = value
->resolution
.xres
;
2296 *bufptr
++ = value
->resolution
.yres
>> 24;
2297 *bufptr
++ = value
->resolution
.yres
>> 16;
2298 *bufptr
++ = value
->resolution
.yres
>> 8;
2299 *bufptr
++ = value
->resolution
.yres
;
2300 *bufptr
++ = value
->resolution
.units
;
2304 case IPP_TAG_RANGE
:
2305 for (i
= 0, value
= attr
->values
;
2306 i
< attr
->num_values
;
2309 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 13)
2311 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2313 DEBUG_puts("ippWriteIO: Could not write IPP "
2315 ipp_buffer_release(buffer
);
2325 * Arrays and sets are done by sending additional
2326 * values with a zero-length name...
2329 *bufptr
++ = attr
->value_tag
;
2335 * Range values consist of a 2-byte length,
2336 * 4-byte lower value, and 4-byte upper value.
2338 * Put the 2-byte length and range value data
2344 *bufptr
++ = value
->range
.lower
>> 24;
2345 *bufptr
++ = value
->range
.lower
>> 16;
2346 *bufptr
++ = value
->range
.lower
>> 8;
2347 *bufptr
++ = value
->range
.lower
;
2348 *bufptr
++ = value
->range
.upper
>> 24;
2349 *bufptr
++ = value
->range
.upper
>> 16;
2350 *bufptr
++ = value
->range
.upper
>> 8;
2351 *bufptr
++ = value
->range
.upper
;
2355 case IPP_TAG_TEXTLANG
:
2356 case IPP_TAG_NAMELANG
:
2357 for (i
= 0, value
= attr
->values
;
2358 i
< attr
->num_values
;
2364 * Arrays and sets are done by sending additional
2365 * values with a zero-length name...
2368 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2370 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2372 DEBUG_puts("ippWriteIO: Could not write IPP "
2374 ipp_buffer_release(buffer
);
2381 *bufptr
++ = attr
->value_tag
;
2387 * textWithLanguage and nameWithLanguage values consist
2388 * of a 2-byte length for both strings and their
2389 * individual lengths, a 2-byte length for the
2390 * character string, the character string without the
2391 * trailing nul, a 2-byte length for the character
2392 * set string, and the character set string without
2398 if (value
->string
.charset
!= NULL
)
2399 n
+= (int)strlen(value
->string
.charset
);
2401 if (value
->string
.text
!= NULL
)
2402 n
+= (int)strlen(value
->string
.text
);
2404 if (n
> (IPP_BUF_SIZE
- 2))
2406 DEBUG_printf(("ippWriteIO: text/nameWithLanguage value "
2407 "too long (%d)\n", n
));
2408 ipp_buffer_release(buffer
);
2412 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2414 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2416 DEBUG_puts("ippWriteIO: Could not write IPP "
2418 ipp_buffer_release(buffer
);
2425 /* Length of entire value */
2429 /* Length of charset */
2430 if (value
->string
.charset
!= NULL
)
2431 n
= (int)strlen(value
->string
.charset
);
2441 memcpy(bufptr
, value
->string
.charset
, n
);
2445 /* Length of text */
2446 if (value
->string
.text
!= NULL
)
2447 n
= (int)strlen(value
->string
.text
);
2457 memcpy(bufptr
, value
->string
.text
, n
);
2463 case IPP_TAG_BEGIN_COLLECTION
:
2464 for (i
= 0, value
= attr
->values
;
2465 i
< attr
->num_values
;
2469 * Collections are written with the begin-collection
2470 * tag first with a value of 0 length, followed by the
2471 * attributes in the collection, then the end-collection
2475 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 5)
2477 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2479 DEBUG_puts("ippWriteIO: Could not write IPP "
2481 ipp_buffer_release(buffer
);
2491 * Arrays and sets are done by sending additional
2492 * values with a zero-length name...
2495 *bufptr
++ = attr
->value_tag
;
2501 * Write a data length of 0 and flush the buffer...
2507 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2509 DEBUG_puts("ippWriteIO: Could not write IPP "
2511 ipp_buffer_release(buffer
);
2518 * Then write the collection attribute...
2521 value
->collection
->state
= IPP_IDLE
;
2523 if (ippWriteIO(dst
, cb
, 1, ipp
,
2524 value
->collection
) == IPP_ERROR
)
2526 DEBUG_puts("ippWriteIO: Unable to write collection value");
2527 ipp_buffer_release(buffer
);
2534 for (i
= 0, value
= attr
->values
;
2535 i
< attr
->num_values
;
2541 * Arrays and sets are done by sending additional
2542 * values with a zero-length name...
2545 if ((IPP_BUF_SIZE
- (bufptr
- buffer
)) < 3)
2547 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2549 DEBUG_puts("ippWriteIO: Could not write IPP "
2551 ipp_buffer_release(buffer
);
2558 *bufptr
++ = attr
->value_tag
;
2564 * An unknown value might some new value that a
2565 * vendor has come up with. It consists of a
2566 * 2-byte length and the bytes in the unknown
2570 n
= value
->unknown
.length
;
2572 if (n
> (IPP_BUF_SIZE
- 2))
2574 DEBUG_printf(("ippWriteIO: Data length too long (%d)\n",
2576 ipp_buffer_release(buffer
);
2580 if ((int)(IPP_BUF_SIZE
- (bufptr
- buffer
)) < (n
+ 2))
2582 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2584 DEBUG_puts("ippWriteIO: Could not write IPP "
2586 ipp_buffer_release(buffer
);
2593 /* Length of unknown value */
2600 memcpy(bufptr
, value
->unknown
.data
, n
);
2608 * Write the data out...
2611 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2613 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2614 ipp_buffer_release(buffer
);
2618 DEBUG_printf(("ippWriteIO: wrote %d bytes\n",
2619 (int)(bufptr
- buffer
)));
2622 * If blocking is disabled, stop here...
2629 if (ipp
->current
== NULL
)
2632 * Done with all of the attributes; add the end-of-attributes
2633 * tag or end-collection attribute...
2638 buffer
[0] = IPP_TAG_END
;
2643 buffer
[0] = IPP_TAG_END_COLLECTION
;
2644 buffer
[1] = 0; /* empty name */
2646 buffer
[3] = 0; /* empty value */
2651 if ((*cb
)(dst
, buffer
, n
) < 0)
2653 DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
2654 ipp_buffer_release(buffer
);
2658 ipp
->state
= IPP_DATA
;
2666 break; /* anti-compiler-warning-code */
2669 ipp_buffer_release(buffer
);
2671 return (ipp
->state
);
2676 * '_ippAddAttr()' - Add a new attribute to the request.
2679 ipp_attribute_t
* /* O - New attribute */
2680 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2681 int num_values
) /* I - Number of values */
2683 ipp_attribute_t
*attr
; /* New attribute */
2686 DEBUG_printf(("_ippAddAttr(ipp=%p, num_values=%d)\n", ipp
, num_values
));
2688 if (!ipp
|| num_values
< 0)
2691 attr
= calloc(sizeof(ipp_attribute_t
) +
2692 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2696 attr
->num_values
= num_values
;
2698 if (ipp
->last
== NULL
)
2701 ipp
->last
->next
= attr
;
2706 DEBUG_printf(("_ippAddAttr(): %p\n", attr
));
2713 * '_ippFreeAttr()' - Free an attribute.
2717 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2719 int i
; /* Looping var */
2720 ipp_value_t
*value
; /* Current value */
2723 DEBUG_printf(("_ippFreeAttr(attr=%p)\n", attr
));
2725 switch (attr
->value_tag
)
2729 case IPP_TAG_KEYWORD
:
2731 case IPP_TAG_URISCHEME
:
2732 case IPP_TAG_CHARSET
:
2733 case IPP_TAG_LANGUAGE
:
2734 case IPP_TAG_MIMETYPE
:
2735 for (i
= 0, value
= attr
->values
;
2736 i
< attr
->num_values
;
2738 _cupsStrFree(value
->string
.text
);
2741 case IPP_TAG_TEXTLANG
:
2742 case IPP_TAG_NAMELANG
:
2743 for (i
= 0, value
= attr
->values
;
2744 i
< attr
->num_values
;
2747 if (value
->string
.charset
&& i
== 0)
2748 _cupsStrFree(value
->string
.charset
);
2749 _cupsStrFree(value
->string
.text
);
2753 case IPP_TAG_INTEGER
:
2755 case IPP_TAG_BOOLEAN
:
2757 case IPP_TAG_RESOLUTION
:
2758 case IPP_TAG_RANGE
:
2761 case IPP_TAG_BEGIN_COLLECTION
:
2762 for (i
= 0, value
= attr
->values
;
2763 i
< attr
->num_values
;
2765 ippDelete(value
->collection
);
2768 case IPP_TAG_STRING
:
2769 for (i
= 0, value
= attr
->values
;
2770 i
< attr
->num_values
;
2772 free(value
->unknown
.data
);
2776 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2778 for (i
= 0, value
= attr
->values
;
2779 i
< attr
->num_values
;
2781 if (value
->unknown
.data
)
2782 free(value
->unknown
.data
);
2788 _cupsStrFree(attr
->name
);
2795 * 'ipp_buffer_get()' - Get a read/write buffer.
2798 static unsigned char * /* O - Buffer */
2799 ipp_buffer_get(void)
2801 _ipp_buffer_t
*buffer
; /* Current buffer */
2802 _cups_globals_t
*cg
= _cupsGlobals();
2806 for (buffer
= cg
->ipp_buffers
; buffer
; buffer
= buffer
->next
)
2813 if ((buffer
= malloc(sizeof(_ipp_buffer_t
))) == NULL
)
2817 buffer
->next
= cg
->ipp_buffers
;
2818 cg
->ipp_buffers
= buffer
;
2825 * 'ipp_buffer_release()' - Release a read/write buffer.
2829 ipp_buffer_release(unsigned char *b
) /* I - Buffer to release */
2831 ((_ipp_buffer_t
*)b
)->used
= 0;
2836 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2839 static size_t /* O - Size of IPP message */
2840 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2841 int collection
) /* I - 1 if a collection, 0 otherwise */
2843 int i
; /* Looping var */
2844 int bytes
; /* Number of bytes */
2845 ipp_attribute_t
*attr
; /* Current attribute */
2846 ipp_tag_t group
; /* Current group */
2847 ipp_value_t
*value
; /* Current value */
2854 * Start with 8 bytes for the IPP message header...
2857 bytes
= collection
? 0 : 8;
2860 * Then add the lengths of each attribute...
2863 group
= IPP_TAG_ZERO
;
2865 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2867 if (attr
->group_tag
!= group
&& !collection
)
2869 group
= attr
->group_tag
;
2870 if (group
== IPP_TAG_ZERO
)
2873 bytes
++; /* Group tag */
2879 DEBUG_printf(("ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2880 "bytes=%d\n", attr
->name
, attr
->num_values
, bytes
));
2882 bytes
+= (int)strlen(attr
->name
); /* Name */
2883 bytes
+= attr
->num_values
; /* Value tag for each value */
2884 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2885 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2888 bytes
+= 5; /* Add membername overhead */
2890 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2892 case IPP_TAG_INTEGER
:
2894 bytes
+= 4 * attr
->num_values
;
2897 case IPP_TAG_BOOLEAN
:
2898 bytes
+= attr
->num_values
;
2903 case IPP_TAG_KEYWORD
:
2905 case IPP_TAG_URISCHEME
:
2906 case IPP_TAG_CHARSET
:
2907 case IPP_TAG_LANGUAGE
:
2908 case IPP_TAG_MIMETYPE
:
2909 for (i
= 0, value
= attr
->values
;
2910 i
< attr
->num_values
;
2912 if (value
->string
.text
!= NULL
)
2913 bytes
+= (int)strlen(value
->string
.text
);
2917 bytes
+= 11 * attr
->num_values
;
2920 case IPP_TAG_RESOLUTION
:
2921 bytes
+= 9 * attr
->num_values
;
2924 case IPP_TAG_RANGE
:
2925 bytes
+= 8 * attr
->num_values
;
2928 case IPP_TAG_TEXTLANG
:
2929 case IPP_TAG_NAMELANG
:
2930 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2932 for (i
= 0, value
= attr
->values
;
2933 i
< attr
->num_values
;
2936 if (value
->string
.charset
!= NULL
)
2937 bytes
+= (int)strlen(value
->string
.charset
);
2939 if (value
->string
.text
!= NULL
)
2940 bytes
+= (int)strlen(value
->string
.text
);
2944 case IPP_TAG_BEGIN_COLLECTION
:
2945 for (i
= 0, value
= attr
->values
;
2946 i
< attr
->num_values
;
2948 bytes
+= (int)ipp_length(value
->collection
, 1);
2952 for (i
= 0, value
= attr
->values
;
2953 i
< attr
->num_values
;
2955 bytes
+= value
->unknown
.length
;
2961 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2962 * for the "end of collection" tag and return...
2970 DEBUG_printf(("ipp_length: bytes=%d\n", bytes
));
2977 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2980 static ssize_t
/* O - Number of bytes read */
2981 ipp_read_http(http_t
*http
, /* I - Client connection */
2982 ipp_uchar_t
*buffer
, /* O - Buffer for data */
2983 size_t length
) /* I - Total length */
2985 int tbytes
, /* Total bytes read */
2986 bytes
; /* Bytes read this pass */
2987 char len
[32]; /* Length string */
2990 DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
2991 http
, buffer
, (int)length
));
2994 * Loop until all bytes are read...
2997 for (tbytes
= 0, bytes
= 0;
2998 tbytes
< (int)length
;
2999 tbytes
+= bytes
, buffer
+= bytes
)
3001 DEBUG_printf(("ipp_read_http: tbytes=%d, http->state=%d\n", tbytes
,
3004 if (http
->state
== HTTP_WAITING
)
3007 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
3010 * Do "fast read" from HTTP buffer directly...
3013 if (http
->used
> (int)(length
- tbytes
))
3014 bytes
= (int)(length
- tbytes
);
3019 buffer
[0] = http
->buffer
[0];
3021 memcpy(buffer
, http
->buffer
, bytes
);
3023 http
->used
-= bytes
;
3024 http
->data_remaining
-= bytes
;
3026 if (http
->data_remaining
<= INT_MAX
)
3027 http
->_data_remaining
= (int)http
->data_remaining
;
3029 http
->_data_remaining
= INT_MAX
;
3032 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
3034 if (http
->data_remaining
== 0)
3036 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
3039 * Get the trailing CR LF after the chunk...
3042 if (!httpGets(len
, sizeof(len
), http
))
3046 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
3048 if (http
->state
== HTTP_POST_RECV
)
3051 http
->state
= HTTP_WAITING
;
3058 * Wait a maximum of 1 second for data...
3061 if (!http
->blocking
)
3064 * Wait up to 10 seconds for more data on non-blocking sockets...
3067 if (!httpWait(http
, 10000))
3078 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) <= 0)
3084 * Return the number of bytes read...
3087 if (tbytes
== 0 && bytes
< 0)
3090 DEBUG_printf(("ipp_read_http: returning %d bytes...\n", tbytes
));
3097 * 'ipp_read_file()' - Read IPP data from a file.
3100 static ssize_t
/* O - Number of bytes read */
3101 ipp_read_file(int *fd
, /* I - File descriptor */
3102 ipp_uchar_t
*buffer
, /* O - Read buffer */
3103 size_t length
) /* I - Number of bytes to read */
3106 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
3108 return (read(*fd
, buffer
, length
));
3114 * 'ipp_write_file()' - Write IPP data to a file.
3117 static ssize_t
/* O - Number of bytes written */
3118 ipp_write_file(int *fd
, /* I - File descriptor */
3119 ipp_uchar_t
*buffer
, /* I - Data to write */
3120 size_t length
) /* I - Number of bytes to write */
3123 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
3125 return (write(*fd
, buffer
, length
));
3132 * The following symbol definitions are provided only for KDE
3133 * compatibility during the CUPS 1.2 testing period and will be
3134 * removed in a future release of CUPS. These are PRIVATE APIs
3135 * from CUPS 1.1.x that the KDE developers chose to use...
3138 ipp_attribute_t
* /* O - New attribute */
3139 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
3140 int num_values
) /* I - Number of values */
3142 return (_ippAddAttr(ipp
, num_values
));
3146 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
3150 #endif /* __linux */
3154 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".