2 * "$Id: ipp.c 6649 2007-07-11 21:46:42Z mike $"
4 * Internet Printing Protocol support functions for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 2007 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 size_t ipp_length(ipp_t
*ipp
, int collection
);
79 static ssize_t
ipp_read_http(http_t
*http
, ipp_uchar_t
*buffer
,
81 static ssize_t
ipp_read_file(int *fd
, ipp_uchar_t
*buffer
,
83 static ssize_t
ipp_write_file(int *fd
, ipp_uchar_t
*buffer
,
88 * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
91 ipp_attribute_t
* /* O - New attribute */
92 ippAddBoolean(ipp_t
*ipp
, /* I - IPP message */
93 ipp_tag_t group
, /* I - IPP group */
94 const char *name
, /* I - Name of attribute */
95 char value
) /* I - Value of attribute */
97 ipp_attribute_t
*attr
; /* New attribute */
100 DEBUG_printf(("ippAddBoolean(%p, %02x, \'%s\', %d)\n", ipp
, group
, name
, value
));
102 if (ipp
== NULL
|| name
== NULL
)
105 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
108 attr
->name
= _cupsStrAlloc(name
);
109 attr
->group_tag
= group
;
110 attr
->value_tag
= IPP_TAG_BOOLEAN
;
111 attr
->values
[0].boolean
= value
;
118 * 'ippAddBooleans()' - Add an array of boolean values.
121 ipp_attribute_t
* /* O - New attribute */
122 ippAddBooleans(ipp_t
*ipp
, /* I - IPP message */
123 ipp_tag_t group
, /* I - IPP group */
124 const char *name
, /* I - Name of attribute */
125 int num_values
, /* I - Number of values */
126 const char *values
) /* I - Values */
128 int i
; /* Looping var */
129 ipp_attribute_t
*attr
; /* New attribute */
130 ipp_value_t
*value
; /* Current value */
133 DEBUG_printf(("ippAddBooleans(%p, %02x, \'%s\', %d, %p)\n", ipp
,
134 group
, name
, num_values
, values
));
136 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
139 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
142 attr
->name
= _cupsStrAlloc(name
);
143 attr
->group_tag
= group
;
144 attr
->value_tag
= IPP_TAG_BOOLEAN
;
147 for (i
= 0, value
= attr
->values
;
150 value
->boolean
= values
[i
];
157 * 'ippAddCollection()' - Add a collection value.
159 * @since CUPS 1.1.19@
162 ipp_attribute_t
* /* O - New attribute */
163 ippAddCollection(ipp_t
*ipp
, /* I - IPP message */
164 ipp_tag_t group
, /* I - IPP group */
165 const char *name
, /* I - Name of attribute */
166 ipp_t
*value
) /* I - Value */
168 ipp_attribute_t
*attr
; /* New attribute */
171 DEBUG_printf(("ippAddCollection(%p, %02x, \'%s\', %p)\n", ipp
, group
, name
,
174 if (ipp
== NULL
|| name
== NULL
)
177 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
180 attr
->name
= _cupsStrAlloc(name
);
181 attr
->group_tag
= group
;
182 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
183 attr
->values
[0].collection
= value
;
190 * 'ippAddCollections()' - Add an array of collection values.
192 * @since CUPS 1.1.19@
195 ipp_attribute_t
* /* O - New attribute */
197 ipp_t
*ipp
, /* I - IPP message */
198 ipp_tag_t group
, /* I - IPP group */
199 const char *name
, /* I - Name of attribute */
200 int num_values
, /* I - Number of values */
201 const ipp_t
**values
) /* I - Values */
203 int i
; /* Looping var */
204 ipp_attribute_t
*attr
; /* New attribute */
205 ipp_value_t
*value
; /* Current value */
208 DEBUG_printf(("ippAddCollections(%p, %02x, \'%s\', %d, %p)\n", ipp
,
209 group
, name
, num_values
, values
));
211 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
214 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
217 attr
->name
= _cupsStrAlloc(name
);
218 attr
->group_tag
= group
;
219 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
222 for (i
= 0, value
= attr
->values
;
225 value
->collection
= (ipp_t
*)values
[i
];
232 * 'ippAddDate()' - Add a date attribute to an IPP message.
235 ipp_attribute_t
* /* O - New attribute */
236 ippAddDate(ipp_t
*ipp
, /* I - IPP message */
237 ipp_tag_t group
, /* I - IPP group */
238 const char *name
, /* I - Name of attribute */
239 const ipp_uchar_t
*value
) /* I - Value */
241 ipp_attribute_t
*attr
; /* New attribute */
244 DEBUG_printf(("ippAddDate(%p, %02x, \'%s\', %p)\n", ipp
, group
, name
,
247 if (ipp
== NULL
|| name
== NULL
|| value
== NULL
)
250 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
253 attr
->name
= _cupsStrAlloc(name
);
254 attr
->group_tag
= group
;
255 attr
->value_tag
= IPP_TAG_DATE
;
256 memcpy(attr
->values
[0].date
, value
, 11);
263 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
266 ipp_attribute_t
* /* O - New attribute */
267 ippAddInteger(ipp_t
*ipp
, /* I - IPP message */
268 ipp_tag_t group
, /* I - IPP group */
269 ipp_tag_t type
, /* I - Type of attribute */
270 const char *name
, /* I - Name of attribute */
271 int value
) /* I - Value of attribute */
273 ipp_attribute_t
*attr
; /* New attribute */
276 DEBUG_printf(("ippAddInteger(%p, %d, \'%s\', %d)\n", ipp
, group
, name
,
279 if (ipp
== NULL
|| name
== NULL
)
282 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
285 attr
->name
= _cupsStrAlloc(name
);
286 attr
->group_tag
= group
;
287 attr
->value_tag
= type
;
288 attr
->values
[0].integer
= value
;
295 * 'ippAddIntegers()' - Add an array of integer values.
298 ipp_attribute_t
* /* O - New attribute */
299 ippAddIntegers(ipp_t
*ipp
, /* I - IPP message */
300 ipp_tag_t group
, /* I - IPP group */
301 ipp_tag_t type
, /* I - Type of attribute */
302 const char *name
, /* I - Name of attribute */
303 int num_values
, /* I - Number of values */
304 const int *values
) /* I - Values */
306 int i
; /* Looping var */
307 ipp_attribute_t
*attr
; /* New attribute */
308 ipp_value_t
*value
; /* Current value */
311 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
314 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
317 attr
->name
= _cupsStrAlloc(name
);
318 attr
->group_tag
= group
;
319 attr
->value_tag
= type
;
322 for (i
= 0, value
= attr
->values
;
325 value
->integer
= values
[i
];
332 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
337 ipp_attribute_t
* /* O - New attribute */
338 ippAddOctetString(ipp_t
*ipp
, /* I - IPP message */
339 ipp_tag_t group
, /* I - IPP group */
340 const char *name
, /* I - Name of attribute */
341 const void *data
, /* I - octetString data */
342 int datalen
) /* I - Length of data in bytes */
344 ipp_attribute_t
*attr
; /* New attribute */
347 if (ipp
== NULL
|| name
== NULL
)
350 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
354 * Initialize the attribute data...
357 attr
->name
= _cupsStrAlloc(name
);
358 attr
->group_tag
= group
;
359 attr
->value_tag
= IPP_TAG_STRING
;
360 attr
->values
[0].unknown
.length
= datalen
;
364 attr
->values
[0].unknown
.data
= malloc(datalen
);
365 memcpy(attr
->values
[0].unknown
.data
, data
, datalen
);
369 * Return the new attribute...
377 * 'ippAddString()' - Add a language-encoded string to an IPP message.
380 ipp_attribute_t
* /* O - New attribute */
381 ippAddString(ipp_t
*ipp
, /* I - IPP message */
382 ipp_tag_t group
, /* I - IPP group */
383 ipp_tag_t type
, /* I - Type of attribute */
384 const char *name
, /* I - Name of attribute */
385 const char *charset
, /* I - Character set */
386 const char *value
) /* I - Value */
388 ipp_attribute_t
*attr
; /* New attribute */
389 char buffer
[1024], /* Language/charset value buffer */
390 *bufptr
; /* Pointer into buffer */
393 if (ipp
== NULL
|| name
== NULL
)
396 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
400 * Force value to be English for the POSIX locale...
403 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(value
, "C"))
407 * Convert language values to lowercase and change _ to - as needed...
410 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
412 strlcpy(buffer
, value
, sizeof(buffer
));
415 for (bufptr
= buffer
; *bufptr
; bufptr
++)
419 *bufptr
= tolower(*bufptr
& 255);
423 * Initialize the attribute data...
426 attr
->name
= _cupsStrAlloc(name
);
427 attr
->group_tag
= group
;
428 attr
->value_tag
= type
;
429 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
430 charset
? _cupsStrAlloc(charset
) : NULL
;
431 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
432 value
? _cupsStrAlloc(value
) : NULL
;
439 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
442 ipp_attribute_t
* /* O - New attribute */
444 ipp_t
*ipp
, /* I - IPP message */
445 ipp_tag_t group
, /* I - IPP group */
446 ipp_tag_t type
, /* I - Type of attribute */
447 const char *name
, /* I - Name of attribute */
448 int num_values
, /* I - Number of values */
449 const char *charset
, /* I - Character set */
450 const char * const *values
) /* I - Values */
452 int i
; /* Looping var */
453 ipp_attribute_t
*attr
; /* New attribute */
454 ipp_value_t
*value
; /* Current value */
457 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
460 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
464 * Initialize the attribute data...
467 attr
->name
= _cupsStrAlloc(name
);
468 attr
->group_tag
= group
;
469 attr
->value_tag
= type
;
471 for (i
= 0, value
= attr
->values
;
476 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
477 charset
? _cupsStrAlloc(charset
) : NULL
;
479 value
->string
.charset
= attr
->values
[0].string
.charset
;
484 * Force language to be English for the POSIX locale...
487 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(values
[i
], "C"))
488 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
491 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)values
[i
] :
492 _cupsStrAlloc(values
[i
]);
501 * 'ippAddRange()' - Add a range of values to an IPP message.
504 ipp_attribute_t
* /* O - New attribute */
505 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
506 ipp_tag_t group
, /* I - IPP group */
507 const char *name
, /* I - Name of attribute */
508 int lower
, /* I - Lower value */
509 int upper
) /* I - Upper value */
511 ipp_attribute_t
*attr
; /* New attribute */
514 if (ipp
== NULL
|| name
== NULL
)
517 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
520 attr
->name
= _cupsStrAlloc(name
);
521 attr
->group_tag
= group
;
522 attr
->value_tag
= IPP_TAG_RANGE
;
523 attr
->values
[0].range
.lower
= lower
;
524 attr
->values
[0].range
.upper
= upper
;
531 * 'ippAddRanges()' - Add ranges of values to an IPP message.
534 ipp_attribute_t
* /* O - New attribute */
535 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
536 ipp_tag_t group
, /* I - IPP group */
537 const char *name
, /* I - Name of attribute */
538 int num_values
, /* I - Number of values */
539 const int *lower
, /* I - Lower values */
540 const int *upper
) /* I - Upper values */
542 int i
; /* Looping var */
543 ipp_attribute_t
*attr
; /* New attribute */
544 ipp_value_t
*value
; /* Current value */
547 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
550 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
553 attr
->name
= _cupsStrAlloc(name
);
554 attr
->group_tag
= group
;
555 attr
->value_tag
= IPP_TAG_RANGE
;
557 if (lower
!= NULL
&& upper
!= NULL
)
558 for (i
= 0, value
= attr
->values
;
562 value
->range
.lower
= lower
[i
];
563 value
->range
.upper
= upper
[i
];
571 * 'ippAddResolution()' - Add a resolution value to an IPP message.
574 ipp_attribute_t
* /* O - New attribute */
575 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
576 ipp_tag_t group
, /* I - IPP group */
577 const char *name
, /* I - Name of attribute */
578 ipp_res_t units
, /* I - Units for resolution */
579 int xres
, /* I - X resolution */
580 int yres
) /* I - Y resolution */
582 ipp_attribute_t
*attr
; /* New attribute */
585 if (ipp
== NULL
|| name
== NULL
)
588 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
591 attr
->name
= _cupsStrAlloc(name
);
592 attr
->group_tag
= group
;
593 attr
->value_tag
= IPP_TAG_RESOLUTION
;
594 attr
->values
[0].resolution
.xres
= xres
;
595 attr
->values
[0].resolution
.yres
= yres
;
596 attr
->values
[0].resolution
.units
= units
;
603 * 'ippAddResolutions()' - Add resolution values to an IPP message.
606 ipp_attribute_t
* /* O - New attribute */
607 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
608 ipp_tag_t group
, /* I - IPP group */
609 const char *name
, /* I - Name of attribute */
610 int num_values
,/* I - Number of values */
611 ipp_res_t units
, /* I - Units for resolution */
612 const int *xres
, /* I - X resolutions */
613 const int *yres
) /* I - Y resolutions */
615 int i
; /* Looping var */
616 ipp_attribute_t
*attr
; /* New attribute */
617 ipp_value_t
*value
; /* Current value */
620 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
623 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
626 attr
->name
= _cupsStrAlloc(name
);
627 attr
->group_tag
= group
;
628 attr
->value_tag
= IPP_TAG_RESOLUTION
;
630 if (xres
!= NULL
&& yres
!= NULL
)
631 for (i
= 0, value
= attr
->values
;
635 value
->resolution
.xres
= xres
[i
];
636 value
->resolution
.yres
= yres
[i
];
637 value
->resolution
.units
= units
;
645 * 'ippAddSeparator()' - Add a group separator to an IPP message.
648 ipp_attribute_t
* /* O - New attribute */
649 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
651 ipp_attribute_t
*attr
; /* New attribute */
654 DEBUG_printf(("ippAddSeparator(%p)\n", ipp
));
659 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
662 attr
->group_tag
= IPP_TAG_ZERO
;
663 attr
->value_tag
= IPP_TAG_ZERO
;
670 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
674 time_t /* O - UNIX time value */
675 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
677 struct tm unixdate
; /* UNIX date/time info */
678 time_t t
; /* Computed time */
681 memset(&unixdate
, 0, sizeof(unixdate
));
684 * RFC-1903 date/time format is:
686 * Byte(s) Description
687 * ------- -----------
688 * 0-1 Year (0 to 65535)
692 * 5 Minutes (0 to 59)
693 * 6 Seconds (0 to 60, 60 = "leap second")
694 * 7 Deciseconds (0 to 9)
696 * 9 UTC hours (0 to 11)
697 * 10 UTC minutes (0 to 59)
700 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
701 unixdate
.tm_mon
= date
[2] - 1;
702 unixdate
.tm_mday
= date
[3];
703 unixdate
.tm_hour
= date
[4];
704 unixdate
.tm_min
= date
[5];
705 unixdate
.tm_sec
= date
[6];
707 t
= mktime(&unixdate
);
710 t
+= date
[9] * 3600 + date
[10] * 60;
712 t
-= date
[9] * 3600 + date
[10] * 60;
719 * 'ippDelete()' - Delete an IPP message.
723 ippDelete(ipp_t
*ipp
) /* I - IPP message */
725 ipp_attribute_t
*attr
, /* Current attribute */
726 *next
; /* Next attribute */
729 DEBUG_printf(("ippDelete(): %p\n", ipp
));
734 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
745 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
747 * @since CUPS 1.1.19@
752 ipp_t
*ipp
, /* I - IPP message */
753 ipp_attribute_t
*attr
) /* I - Attribute to delete */
755 ipp_attribute_t
*current
, /* Current attribute */
756 *prev
; /* Previous attribute */
760 * Find the attribute in the list...
763 for (current
= ipp
->attrs
, prev
= NULL
;
764 current
!= NULL
&& current
!= attr
;
765 prev
= current
, current
= current
->next
);
770 * Found it, remove the attribute from the list...
774 prev
->next
= current
->next
;
776 ipp
->attrs
= current
->next
;
778 if (current
== ipp
->last
)
782 * Free memory used by the attribute...
785 _ippFreeAttr(current
);
791 * 'ippFindAttribute()' - Find a named attribute in a request...
794 ipp_attribute_t
* /* O - Matching attribute */
795 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
796 const char *name
, /* I - Name of attribute */
797 ipp_tag_t type
) /* I - Type of attribute */
799 DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp
, name
));
801 if (ipp
== NULL
|| name
== NULL
)
805 * Reset the current pointer...
811 * Search for the attribute...
814 return (ippFindNextAttribute(ipp
, name
, type
));
819 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
822 ipp_attribute_t
* /* O - Matching attribute */
823 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
824 const char *name
, /* I - Name of attribute */
825 ipp_tag_t type
) /* I - Type of attribute */
827 ipp_attribute_t
*attr
; /* Current atttribute */
828 ipp_tag_t value_tag
; /* Value tag */
831 DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp
, name
));
833 if (ipp
== NULL
|| name
== NULL
)
838 ipp
->prev
= ipp
->current
;
839 attr
= ipp
->current
->next
;
847 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
849 DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr
,
852 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
854 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
855 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
856 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
857 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
873 * 'ippLength()' - Compute the length of an IPP message.
876 size_t /* O - Size of IPP message */
877 ippLength(ipp_t
*ipp
) /* I - IPP message */
879 return (ipp_length(ipp
, 0));
884 * 'ippNew()' - Allocate a new IPP message.
887 ipp_t
* /* O - New IPP message */
890 ipp_t
*temp
; /* New IPP message */
893 DEBUG_puts("ippNew()");
895 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
898 * Default to IPP 1.1...
901 temp
->request
.any
.version
[0] = 1;
902 temp
->request
.any
.version
[1] = 1;
905 DEBUG_printf(("ippNew: %p\n", temp
));
912 * 'ippNewRequest()' - Allocate a new IPP request message.
914 * The new request message is initialized with the attributes-charset and
915 * attributes-natural-language attributes added. The
916 * attributes-natural-language value is derived from the current locale.
921 ipp_t
* /* O - IPP request message */
922 ippNewRequest(ipp_op_t op
) /* I - Operation code */
924 ipp_t
*request
; /* IPP request message */
925 cups_lang_t
*language
; /* Current language localization */
929 * Create a new IPP message...
932 if ((request
= ippNew()) == NULL
)
936 * Set the operation and request ID...
939 request
->request
.op
.operation_id
= op
;
940 request
->request
.op
.request_id
= 1;
943 * Use UTF-8 as the character set...
946 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
947 "attributes-charset", NULL
, "utf-8");
950 * Get the language from the current locale...
953 language
= cupsLangDefault();
955 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
956 "attributes-natural-language", NULL
, language
->language
);
959 * Return the new request...
967 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
970 ipp_state_t
/* O - Current state */
971 ippRead(http_t
*http
, /* I - HTTP connection */
972 ipp_t
*ipp
) /* I - IPP data */
974 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
"\n",
975 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
980 DEBUG_printf(("http->state = %d\n", http
->state
));
982 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
,
983 http
->blocking
|| http
->used
!= 0, NULL
, ipp
));
988 * 'ippReadFile()' - Read data for an IPP message from a file.
990 * @since CUPS 1.1.19@
993 ipp_state_t
/* O - Current state */
994 ippReadFile(int fd
, /* I - HTTP data */
995 ipp_t
*ipp
) /* I - IPP data */
997 DEBUG_printf(("ippReadFile(%d, %p)\n", fd
, ipp
));
999 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1004 * 'ippReadIO()' - Read data for an IPP message.
1009 ipp_state_t
/* O - Current state */
1010 ippReadIO(void *src
, /* I - Data source */
1011 ipp_iocb_t cb
, /* I - Read callback function */
1012 int blocking
, /* I - Use blocking IO? */
1013 ipp_t
*parent
, /* I - Parent request, if any */
1014 ipp_t
*ipp
) /* I - IPP data */
1016 int n
; /* Length of data */
1017 unsigned char buffer
[IPP_MAX_LENGTH
],
1019 string
[IPP_MAX_NAME
],
1020 /* Small string buffer */
1021 *bufptr
; /* Pointer into buffer */
1022 ipp_attribute_t
*attr
; /* Current attribute */
1023 ipp_tag_t tag
; /* Current tag */
1024 ipp_tag_t value_tag
; /* Current value tag */
1025 ipp_value_t
*value
; /* Current value */
1028 DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src
, cb
, blocking
,
1030 DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp
->state
));
1032 if (src
== NULL
|| ipp
== NULL
)
1038 ipp
->state
++; /* Avoid common problem... */
1044 * Get the request header...
1047 if ((n
= (*cb
)(src
, buffer
, 8)) < 8)
1049 DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n
));
1054 * Verify the major version number...
1059 DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer
[0],
1065 * Then copy the request header over...
1068 ipp
->request
.any
.version
[0] = buffer
[0];
1069 ipp
->request
.any
.version
[1] = buffer
[1];
1070 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1071 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1072 buffer
[6]) << 8) | buffer
[7];
1074 DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1075 DEBUG_printf(("ippReadIO: op_status=%04x\n",
1076 ipp
->request
.any
.op_status
));
1077 DEBUG_printf(("ippReadIO: request_id=%d\n",
1078 ipp
->request
.any
.request_id
));
1081 ipp
->state
= IPP_ATTRIBUTE
;
1082 ipp
->current
= NULL
;
1083 ipp
->curtag
= IPP_TAG_ZERO
;
1084 ipp
->prev
= ipp
->last
;
1087 * If blocking is disabled, stop here...
1093 case IPP_ATTRIBUTE
:
1096 if ((*cb
)(src
, buffer
, 1) < 1)
1099 DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
1100 ipp
->current
, ipp
->prev
));
1103 * Read this attribute...
1106 tag
= (ipp_tag_t
)buffer
[0];
1108 if (tag
== IPP_TAG_END
)
1111 * No more attributes left...
1114 DEBUG_puts("ippReadIO: IPP_TAG_END!");
1116 ipp
->state
= IPP_DATA
;
1119 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1122 * Group tag... Set the current group and continue...
1125 if (ipp
->curtag
== tag
)
1126 ipp
->prev
= ippAddSeparator(ipp
);
1127 else if (ipp
->current
)
1128 ipp
->prev
= ipp
->current
;
1131 ipp
->current
= NULL
;
1132 DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag
,
1137 DEBUG_printf(("ippReadIO: value tag = %x\n", tag
));
1143 if ((*cb
)(src
, buffer
, 2) < 2)
1145 DEBUG_puts("ippReadIO: unable to read name length!");
1149 n
= (buffer
[0] << 8) | buffer
[1];
1151 if (n
> (sizeof(buffer
) - 1))
1153 DEBUG_printf(("ippReadIO: bad name length %d!\n", n
));
1157 DEBUG_printf(("ippReadIO: name length = %d\n", n
));
1159 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1160 tag
!= IPP_TAG_END_COLLECTION
)
1163 * More values for current attribute...
1166 if (ipp
->current
== NULL
)
1169 attr
= ipp
->current
;
1170 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1173 * Make sure we aren't adding a new value of a different
1177 if (value_tag
== IPP_TAG_ZERO
)
1180 * Setting the value of a collection member...
1183 attr
->value_tag
= tag
;
1185 else if (value_tag
== IPP_TAG_STRING
||
1186 (value_tag
>= IPP_TAG_TEXTLANG
&&
1187 value_tag
<= IPP_TAG_MIMETYPE
))
1190 * String values can sometimes come across in different
1191 * forms; accept sets of differing values...
1194 if (tag
!= IPP_TAG_STRING
&&
1195 (tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
))
1198 else if (value_tag
!= tag
)
1202 * Finally, reallocate the attribute array as needed...
1205 if (attr
->num_values
== 1 ||
1206 (attr
->num_values
> 0 &&
1207 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1209 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1212 DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
1213 attr
->num_values
+ IPP_MAX_VALUES
));
1216 * Reallocate memory...
1219 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1220 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1221 sizeof(ipp_value_t
))) == NULL
)
1227 * Reset pointers in the list...
1231 ipp
->prev
->next
= temp
;
1235 attr
= ipp
->current
= ipp
->last
= temp
;
1239 else if (tag
== IPP_TAG_MEMBERNAME
)
1242 * Name must be length 0!
1247 DEBUG_puts("ippReadIO: member name not empty!");
1252 ipp
->prev
= ipp
->current
;
1254 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1256 DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
1257 ipp
->current
, ipp
->prev
));
1259 attr
->group_tag
= ipp
->curtag
;
1260 attr
->value_tag
= IPP_TAG_ZERO
;
1261 attr
->num_values
= 0;
1263 else if (tag
!= IPP_TAG_END_COLLECTION
)
1266 * New attribute; read the name and add it...
1269 if ((*cb
)(src
, buffer
, n
) < n
)
1271 DEBUG_puts("ippReadIO: unable to read name!");
1278 ipp
->prev
= ipp
->current
;
1280 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1282 DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n",
1283 buffer
, ipp
->current
, ipp
->prev
));
1285 attr
->group_tag
= ipp
->curtag
;
1286 attr
->value_tag
= tag
;
1287 attr
->name
= _cupsStrAlloc((char *)buffer
);
1288 attr
->num_values
= 0;
1293 if (tag
!= IPP_TAG_END_COLLECTION
)
1294 value
= attr
->values
+ attr
->num_values
;
1298 if ((*cb
)(src
, buffer
, 2) < 2)
1300 DEBUG_puts("ippReadIO: unable to read value length!");
1304 n
= (buffer
[0] << 8) | buffer
[1];
1305 DEBUG_printf(("ippReadIO: value length = %d\n", n
));
1309 case IPP_TAG_INTEGER
:
1313 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1317 if ((*cb
)(src
, buffer
, 4) < 4)
1319 DEBUG_puts("ippReadIO: Unable to read integer value!");
1323 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1328 case IPP_TAG_BOOLEAN
:
1331 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1335 if ((*cb
)(src
, buffer
, 1) < 1)
1337 DEBUG_puts("ippReadIO: Unable to read boolean value!");
1341 value
->boolean
= buffer
[0];
1345 case IPP_TAG_KEYWORD
:
1346 case IPP_TAG_STRING
:
1348 case IPP_TAG_URISCHEME
:
1349 case IPP_TAG_CHARSET
:
1350 case IPP_TAG_LANGUAGE
:
1351 case IPP_TAG_MIMETYPE
:
1352 if (n
>= sizeof(buffer
))
1354 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1358 if ((*cb
)(src
, buffer
, n
) < n
)
1360 DEBUG_puts("ippReadIO: unable to read name!");
1365 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1366 DEBUG_printf(("ippReadIO: value = \'%s\'\n",
1367 value
->string
.text
));
1372 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1376 if ((*cb
)(src
, value
->date
, 11) < 11)
1378 DEBUG_puts("ippReadIO: Unable to date integer value!");
1382 case IPP_TAG_RESOLUTION
:
1385 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1389 if ((*cb
)(src
, buffer
, 9) < 9)
1391 DEBUG_puts("ippReadIO: Unable to read resolution value!");
1395 value
->resolution
.xres
=
1396 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1398 value
->resolution
.yres
=
1399 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1401 value
->resolution
.units
=
1402 (ipp_res_t
)buffer
[8];
1404 case IPP_TAG_RANGE
:
1407 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1411 if ((*cb
)(src
, buffer
, 8) < 8)
1413 DEBUG_puts("ippReadIO: Unable to read range value!");
1417 value
->range
.lower
=
1418 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1420 value
->range
.upper
=
1421 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1424 case IPP_TAG_TEXTLANG
:
1425 case IPP_TAG_NAMELANG
:
1426 if (n
>= sizeof(buffer
) || n
< 4)
1428 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1432 if ((*cb
)(src
, buffer
, n
) < n
)
1434 DEBUG_puts("ippReadIO: Unable to read string w/language value!");
1441 * text-with-language and name-with-language are composite
1450 n
= (bufptr
[0] << 8) | bufptr
[1];
1452 if ((bufptr
+ 2 + n
) >= (buffer
+ sizeof(buffer
)) ||
1453 n
>= sizeof(string
))
1455 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1459 memcpy(string
, bufptr
+ 2, n
);
1462 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1465 n
= (bufptr
[0] << 8) | bufptr
[1];
1467 if ((bufptr
+ 2 + n
) >= (buffer
+ sizeof(buffer
)))
1469 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1473 bufptr
[2 + n
] = '\0';
1474 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1477 case IPP_TAG_BEGIN_COLLECTION
:
1479 * Oh, boy, here comes a collection value, so read it...
1482 value
->collection
= ippNew();
1486 DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
1490 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1492 DEBUG_puts("ippReadIO: Unable to read collection value!");
1497 case IPP_TAG_END_COLLECTION
:
1500 DEBUG_puts("ippReadIO: endCollection tag with value length > 0!");
1504 DEBUG_puts("ippReadIO: endCollection tag...");
1506 return (ipp
->state
= IPP_DATA
);
1508 case IPP_TAG_MEMBERNAME
:
1510 * The value the name of the member in the collection, which
1511 * we need to carry over...
1514 if (n
>= sizeof(buffer
))
1516 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1520 if ((*cb
)(src
, buffer
, n
) < n
)
1522 DEBUG_puts("ippReadIO: Unable to read member name value!");
1527 attr
->name
= _cupsStrAlloc((char *)buffer
);
1530 * Since collection members are encoded differently than
1531 * regular attributes, make sure we don't start with an
1535 attr
->num_values
--;
1537 DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr
->name
));
1540 default : /* Other unsupported values */
1541 if (n
> sizeof(buffer
))
1543 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1547 value
->unknown
.length
= n
;
1550 value
->unknown
.data
= malloc(n
);
1551 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1553 DEBUG_puts("ippReadIO: Unable to read unsupported value!");
1558 value
->unknown
.data
= NULL
;
1562 attr
->num_values
++;
1565 * If blocking is disabled, stop here...
1577 break; /* anti-compiler-warning-code */
1580 DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp
->state
));
1582 return (ipp
->state
);
1587 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1590 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1591 ippTimeToDate(time_t t
) /* I - UNIX time value */
1593 struct tm
*unixdate
; /* UNIX unixdate/time info */
1594 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1595 /* RFC-1903 date/time data */
1599 * RFC-1903 date/time format is:
1601 * Byte(s) Description
1602 * ------- -----------
1603 * 0-1 Year (0 to 65535)
1607 * 5 Minutes (0 to 59)
1608 * 6 Seconds (0 to 60, 60 = "leap second")
1609 * 7 Deciseconds (0 to 9)
1611 * 9 UTC hours (0 to 11)
1612 * 10 UTC minutes (0 to 59)
1615 unixdate
= gmtime(&t
);
1616 unixdate
->tm_year
+= 1900;
1618 date
[0] = unixdate
->tm_year
>> 8;
1619 date
[1] = unixdate
->tm_year
;
1620 date
[2] = unixdate
->tm_mon
+ 1;
1621 date
[3] = unixdate
->tm_mday
;
1622 date
[4] = unixdate
->tm_hour
;
1623 date
[5] = unixdate
->tm_min
;
1624 date
[6] = unixdate
->tm_sec
;
1635 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1638 ipp_state_t
/* O - Current state */
1639 ippWrite(http_t
*http
, /* I - HTTP connection */
1640 ipp_t
*ipp
) /* I - IPP data */
1642 DEBUG_printf(("ippWrite(%p, %p)\n", http
, ipp
));
1647 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
,
1648 http
->blocking
, NULL
, ipp
));
1653 * 'ippWriteFile()' - Write data for an IPP message to a file.
1655 * @since CUPS 1.1.19@
1658 ipp_state_t
/* O - Current state */
1659 ippWriteFile(int fd
, /* I - HTTP data */
1660 ipp_t
*ipp
) /* I - IPP data */
1662 DEBUG_printf(("ippWriteFile(%d, %p)\n", fd
, ipp
));
1664 ipp
->state
= IPP_IDLE
;
1666 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1671 * 'ippWriteIO()' - Write data for an IPP message.
1676 ipp_state_t
/* O - Current state */
1677 ippWriteIO(void *dst
, /* I - Destination */
1678 ipp_iocb_t cb
, /* I - Write callback function */
1679 int blocking
, /* I - Use blocking IO? */
1680 ipp_t
*parent
, /* I - Parent IPP message */
1681 ipp_t
*ipp
) /* I - IPP data */
1683 int i
; /* Looping var */
1684 int n
; /* Length of data */
1685 unsigned char buffer
[IPP_MAX_LENGTH
+ 2],
1686 /* Data buffer + length bytes */
1687 *bufptr
; /* Pointer into buffer */
1688 ipp_attribute_t
*attr
; /* Current attribute */
1689 ipp_value_t
*value
; /* Current value */
1692 DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst
, cb
, blocking
,
1695 if (dst
== NULL
|| ipp
== NULL
)
1701 ipp
->state
++; /* Avoid common problem... */
1707 * Send the request header:
1710 * Operation/Status Code = 2 bytes
1711 * Request ID = 4 bytes
1717 *bufptr
++ = ipp
->request
.any
.version
[0];
1718 *bufptr
++ = ipp
->request
.any
.version
[1];
1719 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1720 *bufptr
++ = ipp
->request
.any
.op_status
;
1721 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1722 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1723 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1724 *bufptr
++ = ipp
->request
.any
.request_id
;
1726 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1728 DEBUG_puts("ippWriteIO: Could not write IPP header...");
1734 * Reset the state engine to point to the first attribute
1735 * in the request/response, with no current group.
1738 ipp
->state
= IPP_ATTRIBUTE
;
1739 ipp
->current
= ipp
->attrs
;
1740 ipp
->curtag
= IPP_TAG_ZERO
;
1742 DEBUG_printf(("ippWriteIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1743 DEBUG_printf(("ippWriteIO: op_status=%04x\n", ipp
->request
.any
.op_status
));
1744 DEBUG_printf(("ippWriteIO: request_id=%d\n", ipp
->request
.any
.request_id
));
1747 * If blocking is disabled, stop here...
1753 case IPP_ATTRIBUTE
:
1754 while (ipp
->current
!= NULL
)
1757 * Write this attribute...
1761 attr
= ipp
->current
;
1763 ipp
->current
= ipp
->current
->next
;
1765 if (ipp
->curtag
!= attr
->group_tag
&& parent
== NULL
)
1768 * Send a group tag byte...
1771 ipp
->curtag
= attr
->group_tag
;
1773 if (attr
->group_tag
== IPP_TAG_ZERO
)
1776 DEBUG_printf(("ippWriteIO: wrote group tag = %x\n", attr
->group_tag
));
1777 *bufptr
++ = attr
->group_tag
;
1779 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1783 * Write the attribute tag and name. The current implementation
1784 * does not support the extension value tags above 0x7f, so all
1785 * value tags are 1 byte.
1787 * The attribute name length does not include the trailing nul
1788 * character in the source string.
1790 * Collection values (parent != NULL) are written differently...
1796 * Get the length of the attribute name, and make sure it won't
1797 * overflow the buffer...
1800 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 4))
1804 * Write the value tag, name length, and name string...
1807 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr
->value_tag
));
1808 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n
, attr
->name
));
1810 *bufptr
++ = attr
->value_tag
;
1813 memcpy(bufptr
, attr
->name
, n
);
1819 * Get the length of the attribute name, and make sure it won't
1820 * overflow the buffer...
1823 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 7))
1827 * Write the member name tag, name length, name string, value tag,
1828 * and empty name for the collection member attribute...
1831 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1832 IPP_TAG_MEMBERNAME
));
1833 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n
, attr
->name
));
1834 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr
->value_tag
));
1835 DEBUG_puts("ippWriteIO: writing name = 0, \'\'\n");
1837 *bufptr
++ = IPP_TAG_MEMBERNAME
;
1842 memcpy(bufptr
, attr
->name
, n
);
1845 *bufptr
++ = attr
->value_tag
;
1851 * Now write the attribute value(s)...
1854 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
1856 case IPP_TAG_INTEGER
:
1858 for (i
= 0, value
= attr
->values
;
1859 i
< attr
->num_values
;
1862 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 9)
1864 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1866 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1876 * Arrays and sets are done by sending additional
1877 * values with a zero-length name...
1880 *bufptr
++ = attr
->value_tag
;
1886 * Integers and enumerations are both 4-byte signed
1887 * (twos-complement) values.
1889 * Put the 2-byte length and 4-byte value into the buffer...
1894 *bufptr
++ = value
->integer
>> 24;
1895 *bufptr
++ = value
->integer
>> 16;
1896 *bufptr
++ = value
->integer
>> 8;
1897 *bufptr
++ = value
->integer
;
1901 case IPP_TAG_BOOLEAN
:
1902 for (i
= 0, value
= attr
->values
;
1903 i
< attr
->num_values
;
1906 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 6)
1908 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1910 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1920 * Arrays and sets are done by sending additional
1921 * values with a zero-length name...
1924 *bufptr
++ = attr
->value_tag
;
1930 * Boolean values are 1-byte; 0 = false, 1 = true.
1932 * Put the 2-byte length and 1-byte value into the buffer...
1937 *bufptr
++ = value
->boolean
;
1943 case IPP_TAG_KEYWORD
:
1944 case IPP_TAG_STRING
:
1946 case IPP_TAG_URISCHEME
:
1947 case IPP_TAG_CHARSET
:
1948 case IPP_TAG_LANGUAGE
:
1949 case IPP_TAG_MIMETYPE
:
1950 for (i
= 0, value
= attr
->values
;
1951 i
< attr
->num_values
;
1957 * Arrays and sets are done by sending additional
1958 * values with a zero-length name...
1961 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1963 DEBUG_printf(("ippWriteIO: writing name = 0, \'\'\n"));
1965 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
1967 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1969 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1976 *bufptr
++ = attr
->value_tag
;
1981 if (value
->string
.text
!= NULL
)
1982 n
= (int)strlen(value
->string
.text
);
1986 if (n
> (sizeof(buffer
) - 2))
1989 DEBUG_printf(("ippWriteIO: writing string = %d, \'%s\'\n", n
,
1990 value
->string
.text
));
1992 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
1994 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1996 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2004 * All simple strings consist of the 2-byte length and
2005 * character data without the trailing nul normally found
2006 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2007 * bytes since the 2-byte length is a signed (twos-complement)
2010 * Put the 2-byte length and string characters in the buffer.
2018 memcpy(bufptr
, value
->string
.text
, n
);
2025 for (i
= 0, value
= attr
->values
;
2026 i
< attr
->num_values
;
2029 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 16)
2031 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2033 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2043 * Arrays and sets are done by sending additional
2044 * values with a zero-length name...
2047 *bufptr
++ = attr
->value_tag
;
2053 * Date values consist of a 2-byte length and an
2054 * 11-byte date/time structure defined by RFC 1903.
2056 * Put the 2-byte length and 11-byte date/time
2057 * structure in the buffer.
2062 memcpy(bufptr
, value
->date
, 11);
2067 case IPP_TAG_RESOLUTION
:
2068 for (i
= 0, value
= attr
->values
;
2069 i
< attr
->num_values
;
2072 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 14)
2074 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2076 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2086 * Arrays and sets are done by sending additional
2087 * values with a zero-length name...
2090 *bufptr
++ = attr
->value_tag
;
2096 * Resolution values consist of a 2-byte length,
2097 * 4-byte horizontal resolution value, 4-byte vertical
2098 * resolution value, and a 1-byte units value.
2100 * Put the 2-byte length and resolution value data
2106 *bufptr
++ = value
->resolution
.xres
>> 24;
2107 *bufptr
++ = value
->resolution
.xres
>> 16;
2108 *bufptr
++ = value
->resolution
.xres
>> 8;
2109 *bufptr
++ = value
->resolution
.xres
;
2110 *bufptr
++ = value
->resolution
.yres
>> 24;
2111 *bufptr
++ = value
->resolution
.yres
>> 16;
2112 *bufptr
++ = value
->resolution
.yres
>> 8;
2113 *bufptr
++ = value
->resolution
.yres
;
2114 *bufptr
++ = value
->resolution
.units
;
2118 case IPP_TAG_RANGE
:
2119 for (i
= 0, value
= attr
->values
;
2120 i
< attr
->num_values
;
2123 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 13)
2125 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2127 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2137 * Arrays and sets are done by sending additional
2138 * values with a zero-length name...
2141 *bufptr
++ = attr
->value_tag
;
2147 * Range values consist of a 2-byte length,
2148 * 4-byte lower value, and 4-byte upper value.
2150 * Put the 2-byte length and range value data
2156 *bufptr
++ = value
->range
.lower
>> 24;
2157 *bufptr
++ = value
->range
.lower
>> 16;
2158 *bufptr
++ = value
->range
.lower
>> 8;
2159 *bufptr
++ = value
->range
.lower
;
2160 *bufptr
++ = value
->range
.upper
>> 24;
2161 *bufptr
++ = value
->range
.upper
>> 16;
2162 *bufptr
++ = value
->range
.upper
>> 8;
2163 *bufptr
++ = value
->range
.upper
;
2167 case IPP_TAG_TEXTLANG
:
2168 case IPP_TAG_NAMELANG
:
2169 for (i
= 0, value
= attr
->values
;
2170 i
< attr
->num_values
;
2176 * Arrays and sets are done by sending additional
2177 * values with a zero-length name...
2180 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2182 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2184 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2191 *bufptr
++ = attr
->value_tag
;
2197 * textWithLanguage and nameWithLanguage values consist
2198 * of a 2-byte length for both strings and their
2199 * individual lengths, a 2-byte length for the
2200 * character string, the character string without the
2201 * trailing nul, a 2-byte length for the character
2202 * set string, and the character set string without
2208 if (value
->string
.charset
!= NULL
)
2209 n
+= (int)strlen(value
->string
.charset
);
2211 if (value
->string
.text
!= NULL
)
2212 n
+= (int)strlen(value
->string
.text
);
2214 if (n
> (sizeof(buffer
) - 2))
2217 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2219 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2221 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2228 /* Length of entire value */
2232 /* Length of charset */
2233 if (value
->string
.charset
!= NULL
)
2234 n
= (int)strlen(value
->string
.charset
);
2244 memcpy(bufptr
, value
->string
.charset
, n
);
2248 /* Length of text */
2249 if (value
->string
.text
!= NULL
)
2250 n
= (int)strlen(value
->string
.text
);
2260 memcpy(bufptr
, value
->string
.text
, n
);
2266 case IPP_TAG_BEGIN_COLLECTION
:
2267 for (i
= 0, value
= attr
->values
;
2268 i
< attr
->num_values
;
2272 * Collections are written with the begin-collection
2273 * tag first with a value of 0 length, followed by the
2274 * attributes in the collection, then the end-collection
2278 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 5)
2280 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2282 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2292 * Arrays and sets are done by sending additional
2293 * values with a zero-length name...
2296 *bufptr
++ = attr
->value_tag
;
2302 * Write a data length of 0 and flush the buffer...
2308 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2310 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2317 * Then write the collection attribute...
2320 value
->collection
->state
= IPP_IDLE
;
2322 if (ippWriteIO(dst
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
2328 for (i
= 0, value
= attr
->values
;
2329 i
< attr
->num_values
;
2335 * Arrays and sets are done by sending additional
2336 * values with a zero-length name...
2339 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2341 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2343 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2350 *bufptr
++ = attr
->value_tag
;
2356 * An unknown value might some new value that a
2357 * vendor has come up with. It consists of a
2358 * 2-byte length and the bytes in the unknown
2362 n
= value
->unknown
.length
;
2364 if (n
> (sizeof(buffer
) - 2))
2367 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2369 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2371 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2378 /* Length of unknown value */
2385 memcpy(bufptr
, value
->unknown
.data
, n
);
2393 * Write the data out...
2396 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2398 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2402 DEBUG_printf(("ippWriteIO: wrote %d bytes\n", bufptr
- buffer
));
2405 * If blocking is disabled, stop here...
2412 if (ipp
->current
== NULL
)
2415 * Done with all of the attributes; add the end-of-attributes
2416 * tag or end-collection attribute...
2421 buffer
[0] = IPP_TAG_END
;
2426 buffer
[0] = IPP_TAG_END_COLLECTION
;
2427 buffer
[1] = 0; /* empty name */
2429 buffer
[3] = 0; /* empty value */
2434 if ((*cb
)(dst
, buffer
, n
) < 0)
2436 DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
2440 ipp
->state
= IPP_DATA
;
2448 break; /* anti-compiler-warning-code */
2451 return (ipp
->state
);
2456 * '_ippAddAttr()' - Add a new attribute to the request.
2459 ipp_attribute_t
* /* O - New attribute */
2460 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2461 int num_values
) /* I - Number of values */
2463 ipp_attribute_t
*attr
; /* New attribute */
2466 DEBUG_printf(("_ippAddAttr(%p, %d)\n", ipp
, num_values
));
2468 if (ipp
== NULL
|| num_values
< 0)
2471 attr
= calloc(sizeof(ipp_attribute_t
) +
2472 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2476 attr
->num_values
= num_values
;
2478 if (ipp
->last
== NULL
)
2481 ipp
->last
->next
= attr
;
2486 DEBUG_printf(("_ippAddAttr(): %p\n", attr
));
2493 * '_ippFreeAttr()' - Free an attribute.
2497 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2499 int i
; /* Looping var */
2500 ipp_value_t
*value
; /* Current value */
2503 DEBUG_printf(("_ippFreeAttr(): %p\n", attr
));
2505 switch (attr
->value_tag
)
2509 case IPP_TAG_KEYWORD
:
2510 case IPP_TAG_STRING
:
2512 case IPP_TAG_URISCHEME
:
2513 case IPP_TAG_CHARSET
:
2514 case IPP_TAG_LANGUAGE
:
2515 case IPP_TAG_MIMETYPE
:
2516 for (i
= 0, value
= attr
->values
;
2517 i
< attr
->num_values
;
2519 _cupsStrFree(value
->string
.text
);
2522 case IPP_TAG_TEXTLANG
:
2523 case IPP_TAG_NAMELANG
:
2524 for (i
= 0, value
= attr
->values
;
2525 i
< attr
->num_values
;
2528 if (value
->string
.charset
&& i
== 0)
2529 _cupsStrFree(value
->string
.charset
);
2530 _cupsStrFree(value
->string
.text
);
2534 case IPP_TAG_INTEGER
:
2536 case IPP_TAG_BOOLEAN
:
2538 case IPP_TAG_RESOLUTION
:
2539 case IPP_TAG_RANGE
:
2542 case IPP_TAG_BEGIN_COLLECTION
:
2543 for (i
= 0, value
= attr
->values
;
2544 i
< attr
->num_values
;
2546 ippDelete(value
->collection
);
2550 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2552 for (i
= 0, value
= attr
->values
;
2553 i
< attr
->num_values
;
2555 if (value
->unknown
.data
)
2556 free(value
->unknown
.data
);
2562 _cupsStrFree(attr
->name
);
2569 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2572 static size_t /* O - Size of IPP message */
2573 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2574 int collection
) /* I - 1 if a collection, 0 otherwise */
2576 int i
; /* Looping var */
2577 int bytes
; /* Number of bytes */
2578 ipp_attribute_t
*attr
; /* Current attribute */
2579 ipp_tag_t group
; /* Current group */
2580 ipp_value_t
*value
; /* Current value */
2587 * Start with 8 bytes for the IPP message header...
2590 bytes
= collection
? 0 : 8;
2593 * Then add the lengths of each attribute...
2596 group
= IPP_TAG_ZERO
;
2598 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2600 if (attr
->group_tag
!= group
&& !collection
)
2602 group
= attr
->group_tag
;
2603 if (group
== IPP_TAG_ZERO
)
2606 bytes
++; /* Group tag */
2612 DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n",
2613 attr
->name
, attr
->num_values
, bytes
));
2615 bytes
+= (int)strlen(attr
->name
); /* Name */
2616 bytes
+= attr
->num_values
; /* Value tag for each value */
2617 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2618 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2621 bytes
+= 5; /* Add membername overhead */
2623 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2625 case IPP_TAG_INTEGER
:
2627 bytes
+= 4 * attr
->num_values
;
2630 case IPP_TAG_BOOLEAN
:
2631 bytes
+= attr
->num_values
;
2636 case IPP_TAG_KEYWORD
:
2637 case IPP_TAG_STRING
:
2639 case IPP_TAG_URISCHEME
:
2640 case IPP_TAG_CHARSET
:
2641 case IPP_TAG_LANGUAGE
:
2642 case IPP_TAG_MIMETYPE
:
2643 for (i
= 0, value
= attr
->values
;
2644 i
< attr
->num_values
;
2646 if (value
->string
.text
!= NULL
)
2647 bytes
+= (int)strlen(value
->string
.text
);
2651 bytes
+= 11 * attr
->num_values
;
2654 case IPP_TAG_RESOLUTION
:
2655 bytes
+= 9 * attr
->num_values
;
2658 case IPP_TAG_RANGE
:
2659 bytes
+= 8 * attr
->num_values
;
2662 case IPP_TAG_TEXTLANG
:
2663 case IPP_TAG_NAMELANG
:
2664 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2666 for (i
= 0, value
= attr
->values
;
2667 i
< attr
->num_values
;
2670 if (value
->string
.charset
!= NULL
)
2671 bytes
+= (int)strlen(value
->string
.charset
);
2673 if (value
->string
.text
!= NULL
)
2674 bytes
+= (int)strlen(value
->string
.text
);
2678 case IPP_TAG_BEGIN_COLLECTION
:
2679 for (i
= 0, value
= attr
->values
;
2680 i
< attr
->num_values
;
2682 bytes
+= (int)ipp_length(value
->collection
, 1);
2686 for (i
= 0, value
= attr
->values
;
2687 i
< attr
->num_values
;
2689 bytes
+= value
->unknown
.length
;
2695 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2696 * for the "end of collection" tag and return...
2704 DEBUG_printf(("bytes = %d\n", bytes
));
2711 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2714 static ssize_t
/* O - Number of bytes read */
2715 ipp_read_http(http_t
*http
, /* I - Client connection */
2716 ipp_uchar_t
*buffer
, /* O - Buffer for data */
2717 size_t length
) /* I - Total length */
2719 int tbytes
, /* Total bytes read */
2720 bytes
; /* Bytes read this pass */
2721 char len
[32]; /* Length string */
2724 DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
2725 http
, buffer
, length
));
2728 * Loop until all bytes are read...
2731 for (tbytes
= 0, bytes
= 0; tbytes
< (int)length
; tbytes
+= bytes
, buffer
+= bytes
)
2733 DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes
, http
->state
));
2735 if (http
->state
== HTTP_WAITING
)
2738 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
2741 * Do "fast read" from HTTP buffer directly...
2744 if (http
->used
> (int)(length
- tbytes
))
2745 bytes
= (int)(length
- tbytes
);
2750 buffer
[0] = http
->buffer
[0];
2752 memcpy(buffer
, http
->buffer
, bytes
);
2754 http
->used
-= bytes
;
2755 http
->data_remaining
-= bytes
;
2757 if (http
->data_remaining
<= INT_MAX
)
2758 http
->_data_remaining
= (int)http
->data_remaining
;
2760 http
->_data_remaining
= INT_MAX
;
2763 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
2765 if (http
->data_remaining
== 0)
2767 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
2770 * Get the trailing CR LF after the chunk...
2773 if (!httpGets(len
, sizeof(len
), http
))
2777 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
2779 if (http
->state
== HTTP_POST_RECV
)
2782 http
->state
= HTTP_WAITING
;
2789 * Wait a maximum of 1 second for data...
2792 if (!http
->blocking
)
2795 * Wait up to 10 seconds for more data on non-blocking sockets...
2798 if (!httpWait(http
, 10000))
2809 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) <= 0)
2815 * Return the number of bytes read...
2818 if (tbytes
== 0 && bytes
< 0)
2821 DEBUG_printf(("returning %d bytes...\n", tbytes
));
2828 * 'ipp_read_file()' - Read IPP data from a file.
2831 static ssize_t
/* O - Number of bytes read */
2832 ipp_read_file(int *fd
, /* I - File descriptor */
2833 ipp_uchar_t
*buffer
, /* O - Read buffer */
2834 size_t length
) /* I - Number of bytes to read */
2837 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
2839 return (read(*fd
, buffer
, length
));
2845 * 'ipp_write_file()' - Write IPP data to a file.
2848 static ssize_t
/* O - Number of bytes written */
2849 ipp_write_file(int *fd
, /* I - File descriptor */
2850 ipp_uchar_t
*buffer
, /* I - Data to write */
2851 size_t length
) /* I - Number of bytes to write */
2854 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
2856 return (write(*fd
, buffer
, length
));
2863 * The following symbol definitions are provided only for KDE
2864 * compatibility during the CUPS 1.2 testing period and will be
2865 * removed in a future release of CUPS. These are PRIVATE APIs
2866 * from CUPS 1.1.x that the KDE developers chose to use...
2869 ipp_attribute_t
* /* O - New attribute */
2870 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
2871 int num_values
) /* I - Number of values */
2873 return (_ippAddAttr(ipp
, num_values
));
2877 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2881 #endif /* __linux */
2885 * End of "$Id: ipp.c 6649 2007-07-11 21:46:42Z mike $".