2 * "$Id: ipp.c 6230 2007-02-05 20:08:47Z mike $"
4 * Internet Printing Protocol support functions for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Easy Software Products and are protected by Federal
11 * copyright law. Distribution and use rights are outlined in the file
12 * "LICENSE.txt" which should have been included with this file. If this
13 * file is missing or damaged please contact Easy Software Products
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
25 * This file is subject to the Apple OS-Developed Software exception.
29 * ippAddBoolean() - Add a boolean attribute to an IPP message.
30 * ippAddBooleans() - Add an array of boolean values.
31 * ippAddDate() - Add a date attribute to an IPP message.
32 * ippAddInteger() - Add a integer attribute to an IPP message.
33 * ippAddIntegers() - Add an array of integer values.
34 * ippAddOctetString() - Add an octetString value to an IPP message.
35 * ippAddString() - Add a language-encoded string to an IPP message.
36 * ippAddStrings() - Add language-encoded strings to an IPP message.
37 * ippAddRange() - Add a range of values to an IPP message.
38 * ippAddRanges() - Add ranges of values to an IPP message.
39 * ippAddResolution() - Add a resolution value to an IPP message.
40 * ippAddResolutions() - Add resolution values to an IPP message.
41 * ippAddSeparator() - Add a group separator to an IPP message.
42 * ippDateToTime() - Convert from RFC 1903 Date/Time format to
43 * UNIX time in seconds.
44 * ippDelete() - Delete an IPP message.
45 * ippDeleteAttribute() - Delete a single attribute in an IPP message.
46 * ippFindAttribute() - Find a named attribute in a request...
47 * ippFindNextAttribute() - Find the next named attribute in a request...
48 * ippLength() - Compute the length of an IPP message.
49 * ippNew() - Allocate a new IPP message.
50 * ippNewRequest() - Allocate a new IPP message.
51 * ippRead() - Read data for an IPP message from a HTTP
53 * ippReadFile() - Read data for an IPP message from a file.
54 * ippReadIO() - Read data for an IPP message.
55 * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
56 * ippWrite() - Write data for an IPP message to a HTTP
58 * ippWriteFile() - Write data for an IPP message to a file.
59 * ippWriteIO() - Write data for an IPP message.
60 * _ippAddAttr() - Add a new attribute to the request.
61 * _ippFreeAttr() - Free an attribute.
62 * ipp_length() - Compute the length of an IPP message or
64 * ipp_read_http() - Semi-blocking read on a HTTP connection...
65 * ipp_read_file() - Read IPP data from a file.
66 * ipp_write_file() - Write IPP data to a file.
70 * Include necessary headers...
73 #include "http-private.h"
87 static size_t ipp_length(ipp_t
*ipp
, int collection
);
88 static ssize_t
ipp_read_http(http_t
*http
, ipp_uchar_t
*buffer
,
90 static ssize_t
ipp_read_file(int *fd
, ipp_uchar_t
*buffer
,
92 static ssize_t
ipp_write_file(int *fd
, ipp_uchar_t
*buffer
,
97 * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
100 ipp_attribute_t
* /* O - New attribute */
101 ippAddBoolean(ipp_t
*ipp
, /* I - IPP message */
102 ipp_tag_t group
, /* I - IPP group */
103 const char *name
, /* I - Name of attribute */
104 char value
) /* I - Value of attribute */
106 ipp_attribute_t
*attr
; /* New attribute */
109 DEBUG_printf(("ippAddBoolean(%p, %02x, \'%s\', %d)\n", ipp
, group
, name
, value
));
111 if (ipp
== NULL
|| name
== NULL
)
114 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
117 attr
->name
= _cupsStrAlloc(name
);
118 attr
->group_tag
= group
;
119 attr
->value_tag
= IPP_TAG_BOOLEAN
;
120 attr
->values
[0].boolean
= value
;
127 * 'ippAddBooleans()' - Add an array of boolean values.
130 ipp_attribute_t
* /* O - New attribute */
131 ippAddBooleans(ipp_t
*ipp
, /* I - IPP message */
132 ipp_tag_t group
, /* I - IPP group */
133 const char *name
, /* I - Name of attribute */
134 int num_values
, /* I - Number of values */
135 const char *values
) /* I - Values */
137 int i
; /* Looping var */
138 ipp_attribute_t
*attr
; /* New attribute */
139 ipp_value_t
*value
; /* Current value */
142 DEBUG_printf(("ippAddBooleans(%p, %02x, \'%s\', %d, %p)\n", ipp
,
143 group
, name
, num_values
, values
));
145 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
148 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
151 attr
->name
= _cupsStrAlloc(name
);
152 attr
->group_tag
= group
;
153 attr
->value_tag
= IPP_TAG_BOOLEAN
;
156 for (i
= 0, value
= attr
->values
;
159 value
->boolean
= values
[i
];
166 * 'ippAddCollection()' - Add a collection value.
168 * @since CUPS 1.1.19@
171 ipp_attribute_t
* /* O - New attribute */
172 ippAddCollection(ipp_t
*ipp
, /* I - IPP message */
173 ipp_tag_t group
, /* I - IPP group */
174 const char *name
, /* I - Name of attribute */
175 ipp_t
*value
) /* I - Value */
177 ipp_attribute_t
*attr
; /* New attribute */
180 DEBUG_printf(("ippAddCollection(%p, %02x, \'%s\', %p)\n", ipp
, group
, name
,
183 if (ipp
== NULL
|| name
== NULL
)
186 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
189 attr
->name
= _cupsStrAlloc(name
);
190 attr
->group_tag
= group
;
191 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
192 attr
->values
[0].collection
= value
;
199 * 'ippAddCollections()' - Add an array of collection values.
201 * @since CUPS 1.1.19@
204 ipp_attribute_t
* /* O - New attribute */
206 ipp_t
*ipp
, /* I - IPP message */
207 ipp_tag_t group
, /* I - IPP group */
208 const char *name
, /* I - Name of attribute */
209 int num_values
, /* I - Number of values */
210 const ipp_t
**values
) /* I - Values */
212 int i
; /* Looping var */
213 ipp_attribute_t
*attr
; /* New attribute */
214 ipp_value_t
*value
; /* Current value */
217 DEBUG_printf(("ippAddCollections(%p, %02x, \'%s\', %d, %p)\n", ipp
,
218 group
, name
, num_values
, values
));
220 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
223 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
226 attr
->name
= _cupsStrAlloc(name
);
227 attr
->group_tag
= group
;
228 attr
->value_tag
= IPP_TAG_BEGIN_COLLECTION
;
231 for (i
= 0, value
= attr
->values
;
234 value
->collection
= (ipp_t
*)values
[i
];
241 * 'ippAddDate()' - Add a date attribute to an IPP message.
244 ipp_attribute_t
* /* O - New attribute */
245 ippAddDate(ipp_t
*ipp
, /* I - IPP message */
246 ipp_tag_t group
, /* I - IPP group */
247 const char *name
, /* I - Name of attribute */
248 const ipp_uchar_t
*value
) /* I - Value */
250 ipp_attribute_t
*attr
; /* New attribute */
253 DEBUG_printf(("ippAddDate(%p, %02x, \'%s\', %p)\n", ipp
, group
, name
,
256 if (ipp
== NULL
|| name
== NULL
|| value
== NULL
)
259 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
262 attr
->name
= _cupsStrAlloc(name
);
263 attr
->group_tag
= group
;
264 attr
->value_tag
= IPP_TAG_DATE
;
265 memcpy(attr
->values
[0].date
, value
, 11);
272 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
275 ipp_attribute_t
* /* O - New attribute */
276 ippAddInteger(ipp_t
*ipp
, /* I - IPP message */
277 ipp_tag_t group
, /* I - IPP group */
278 ipp_tag_t type
, /* I - Type of attribute */
279 const char *name
, /* I - Name of attribute */
280 int value
) /* I - Value of attribute */
282 ipp_attribute_t
*attr
; /* New attribute */
285 DEBUG_printf(("ippAddInteger(%p, %d, \'%s\', %d)\n", ipp
, group
, name
,
288 if (ipp
== NULL
|| name
== NULL
)
291 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
294 attr
->name
= _cupsStrAlloc(name
);
295 attr
->group_tag
= group
;
296 attr
->value_tag
= type
;
297 attr
->values
[0].integer
= value
;
304 * 'ippAddIntegers()' - Add an array of integer values.
307 ipp_attribute_t
* /* O - New attribute */
308 ippAddIntegers(ipp_t
*ipp
, /* I - IPP message */
309 ipp_tag_t group
, /* I - IPP group */
310 ipp_tag_t type
, /* I - Type of attribute */
311 const char *name
, /* I - Name of attribute */
312 int num_values
, /* I - Number of values */
313 const int *values
) /* I - Values */
315 int i
; /* Looping var */
316 ipp_attribute_t
*attr
; /* New attribute */
317 ipp_value_t
*value
; /* Current value */
320 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
323 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
326 attr
->name
= _cupsStrAlloc(name
);
327 attr
->group_tag
= group
;
328 attr
->value_tag
= type
;
331 for (i
= 0, value
= attr
->values
;
334 value
->integer
= values
[i
];
341 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
346 ipp_attribute_t
* /* O - New attribute */
347 ippAddOctetString(ipp_t
*ipp
, /* I - IPP message */
348 ipp_tag_t group
, /* I - IPP group */
349 const char *name
, /* I - Name of attribute */
350 const void *data
, /* I - octetString data */
351 int datalen
) /* I - Length of data in bytes */
353 ipp_attribute_t
*attr
; /* New attribute */
356 if (ipp
== NULL
|| name
== NULL
)
359 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
363 * Initialize the attribute data...
366 attr
->name
= _cupsStrAlloc(name
);
367 attr
->group_tag
= group
;
368 attr
->value_tag
= IPP_TAG_STRING
;
369 attr
->values
[0].unknown
.length
= datalen
;
373 attr
->values
[0].unknown
.data
= malloc(datalen
);
374 memcpy(attr
->values
[0].unknown
.data
, data
, datalen
);
378 * Return the new attribute...
386 * 'ippAddString()' - Add a language-encoded string to an IPP message.
389 ipp_attribute_t
* /* O - New attribute */
390 ippAddString(ipp_t
*ipp
, /* I - IPP message */
391 ipp_tag_t group
, /* I - IPP group */
392 ipp_tag_t type
, /* I - Type of attribute */
393 const char *name
, /* I - Name of attribute */
394 const char *charset
, /* I - Character set */
395 const char *value
) /* I - Value */
397 ipp_attribute_t
*attr
; /* New attribute */
398 char buffer
[1024], /* Language/charset value buffer */
399 *bufptr
; /* Pointer into buffer */
402 if (ipp
== NULL
|| name
== NULL
)
405 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
409 * Force value to be English for the POSIX locale...
412 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(value
, "C"))
416 * Convert language values to lowercase and change _ to - as needed...
419 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) && value
)
421 strlcpy(buffer
, value
, sizeof(buffer
));
424 for (bufptr
= buffer
; *bufptr
; bufptr
++)
428 *bufptr
= tolower(*bufptr
& 255);
432 * Initialize the attribute data...
435 attr
->name
= _cupsStrAlloc(name
);
436 attr
->group_tag
= group
;
437 attr
->value_tag
= type
;
438 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
439 charset
? _cupsStrAlloc(charset
) : NULL
;
440 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
441 value
? _cupsStrAlloc(value
) : NULL
;
448 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
451 ipp_attribute_t
* /* O - New attribute */
453 ipp_t
*ipp
, /* I - IPP message */
454 ipp_tag_t group
, /* I - IPP group */
455 ipp_tag_t type
, /* I - Type of attribute */
456 const char *name
, /* I - Name of attribute */
457 int num_values
, /* I - Number of values */
458 const char *charset
, /* I - Character set */
459 const char * const *values
) /* I - Values */
461 int i
; /* Looping var */
462 ipp_attribute_t
*attr
; /* New attribute */
463 ipp_value_t
*value
; /* Current value */
466 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
469 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
473 * Initialize the attribute data...
476 attr
->name
= _cupsStrAlloc(name
);
477 attr
->group_tag
= group
;
478 attr
->value_tag
= type
;
480 for (i
= 0, value
= attr
->values
;
485 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
486 charset
? _cupsStrAlloc(charset
) : NULL
;
488 value
->string
.charset
= attr
->values
[0].string
.charset
;
493 * Force language to be English for the POSIX locale...
496 if (type
== IPP_TAG_LANGUAGE
&& !strcasecmp(values
[i
], "C"))
497 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
500 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)values
[i
] :
501 _cupsStrAlloc(values
[i
]);
510 * 'ippAddRange()' - Add a range of values to an IPP message.
513 ipp_attribute_t
* /* O - New attribute */
514 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
515 ipp_tag_t group
, /* I - IPP group */
516 const char *name
, /* I - Name of attribute */
517 int lower
, /* I - Lower value */
518 int upper
) /* I - Upper value */
520 ipp_attribute_t
*attr
; /* New attribute */
523 if (ipp
== NULL
|| name
== NULL
)
526 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
529 attr
->name
= _cupsStrAlloc(name
);
530 attr
->group_tag
= group
;
531 attr
->value_tag
= IPP_TAG_RANGE
;
532 attr
->values
[0].range
.lower
= lower
;
533 attr
->values
[0].range
.upper
= upper
;
540 * 'ippAddRanges()' - Add ranges of values to an IPP message.
543 ipp_attribute_t
* /* O - New attribute */
544 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
545 ipp_tag_t group
, /* I - IPP group */
546 const char *name
, /* I - Name of attribute */
547 int num_values
, /* I - Number of values */
548 const int *lower
, /* I - Lower values */
549 const int *upper
) /* I - Upper values */
551 int i
; /* Looping var */
552 ipp_attribute_t
*attr
; /* New attribute */
553 ipp_value_t
*value
; /* Current value */
556 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
559 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
562 attr
->name
= _cupsStrAlloc(name
);
563 attr
->group_tag
= group
;
564 attr
->value_tag
= IPP_TAG_RANGE
;
566 if (lower
!= NULL
&& upper
!= NULL
)
567 for (i
= 0, value
= attr
->values
;
571 value
->range
.lower
= lower
[i
];
572 value
->range
.upper
= upper
[i
];
580 * 'ippAddResolution()' - Add a resolution value to an IPP message.
583 ipp_attribute_t
* /* O - New attribute */
584 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
585 ipp_tag_t group
, /* I - IPP group */
586 const char *name
, /* I - Name of attribute */
587 ipp_res_t units
, /* I - Units for resolution */
588 int xres
, /* I - X resolution */
589 int yres
) /* I - Y resolution */
591 ipp_attribute_t
*attr
; /* New attribute */
594 if (ipp
== NULL
|| name
== NULL
)
597 if ((attr
= _ippAddAttr(ipp
, 1)) == NULL
)
600 attr
->name
= _cupsStrAlloc(name
);
601 attr
->group_tag
= group
;
602 attr
->value_tag
= IPP_TAG_RESOLUTION
;
603 attr
->values
[0].resolution
.xres
= xres
;
604 attr
->values
[0].resolution
.yres
= yres
;
605 attr
->values
[0].resolution
.units
= units
;
612 * 'ippAddResolutions()' - Add resolution values to an IPP message.
615 ipp_attribute_t
* /* O - New attribute */
616 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
617 ipp_tag_t group
, /* I - IPP group */
618 const char *name
, /* I - Name of attribute */
619 int num_values
,/* I - Number of values */
620 ipp_res_t units
, /* I - Units for resolution */
621 const int *xres
, /* I - X resolutions */
622 const int *yres
) /* I - Y resolutions */
624 int i
; /* Looping var */
625 ipp_attribute_t
*attr
; /* New attribute */
626 ipp_value_t
*value
; /* Current value */
629 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
632 if ((attr
= _ippAddAttr(ipp
, num_values
)) == NULL
)
635 attr
->name
= _cupsStrAlloc(name
);
636 attr
->group_tag
= group
;
637 attr
->value_tag
= IPP_TAG_RESOLUTION
;
639 if (xres
!= NULL
&& yres
!= NULL
)
640 for (i
= 0, value
= attr
->values
;
644 value
->resolution
.xres
= xres
[i
];
645 value
->resolution
.yres
= yres
[i
];
646 value
->resolution
.units
= units
;
654 * 'ippAddSeparator()' - Add a group separator to an IPP message.
657 ipp_attribute_t
* /* O - New attribute */
658 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
660 ipp_attribute_t
*attr
; /* New attribute */
663 DEBUG_printf(("ippAddSeparator(%p)\n", ipp
));
668 if ((attr
= _ippAddAttr(ipp
, 0)) == NULL
)
671 attr
->group_tag
= IPP_TAG_ZERO
;
672 attr
->value_tag
= IPP_TAG_ZERO
;
679 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
683 time_t /* O - UNIX time value */
684 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
686 struct tm unixdate
; /* UNIX date/time info */
687 time_t t
; /* Computed time */
690 memset(&unixdate
, 0, sizeof(unixdate
));
693 * RFC-1903 date/time format is:
695 * Byte(s) Description
696 * ------- -----------
697 * 0-1 Year (0 to 65535)
701 * 5 Minutes (0 to 59)
702 * 6 Seconds (0 to 60, 60 = "leap second")
703 * 7 Deciseconds (0 to 9)
705 * 9 UTC hours (0 to 11)
706 * 10 UTC minutes (0 to 59)
709 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
710 unixdate
.tm_mon
= date
[2] - 1;
711 unixdate
.tm_mday
= date
[3];
712 unixdate
.tm_hour
= date
[4];
713 unixdate
.tm_min
= date
[5];
714 unixdate
.tm_sec
= date
[6];
716 t
= mktime(&unixdate
);
719 t
+= date
[9] * 3600 + date
[10] * 60;
721 t
-= date
[9] * 3600 + date
[10] * 60;
728 * 'ippDelete()' - Delete an IPP message.
732 ippDelete(ipp_t
*ipp
) /* I - IPP message */
734 ipp_attribute_t
*attr
, /* Current attribute */
735 *next
; /* Next attribute */
738 DEBUG_printf(("ippDelete(): %p\n", ipp
));
743 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
754 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
756 * @since CUPS 1.1.19@
761 ipp_t
*ipp
, /* I - IPP message */
762 ipp_attribute_t
*attr
) /* I - Attribute to delete */
764 ipp_attribute_t
*current
, /* Current attribute */
765 *prev
; /* Previous attribute */
769 * Find the attribute in the list...
772 for (current
= ipp
->attrs
, prev
= NULL
;
773 current
!= NULL
&& current
!= attr
;
774 prev
= current
, current
= current
->next
);
779 * Found it, remove the attribute from the list...
783 prev
->next
= current
->next
;
785 ipp
->attrs
= current
->next
;
787 if (current
== ipp
->last
)
791 * Free memory used by the attribute...
794 _ippFreeAttr(current
);
800 * 'ippFindAttribute()' - Find a named attribute in a request...
803 ipp_attribute_t
* /* O - Matching attribute */
804 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
805 const char *name
, /* I - Name of attribute */
806 ipp_tag_t type
) /* I - Type of attribute */
808 DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp
, name
));
810 if (ipp
== NULL
|| name
== NULL
)
814 * Reset the current pointer...
820 * Search for the attribute...
823 return (ippFindNextAttribute(ipp
, name
, type
));
828 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
831 ipp_attribute_t
* /* O - Matching attribute */
832 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
833 const char *name
, /* I - Name of attribute */
834 ipp_tag_t type
) /* I - Type of attribute */
836 ipp_attribute_t
*attr
; /* Current atttribute */
837 ipp_tag_t value_tag
; /* Value tag */
840 DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp
, name
));
842 if (ipp
== NULL
|| name
== NULL
)
847 ipp
->prev
= ipp
->current
;
848 attr
= ipp
->current
->next
;
856 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
858 DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr
,
861 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
863 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
864 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
865 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
866 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
882 * 'ippLength()' - Compute the length of an IPP message.
885 size_t /* O - Size of IPP message */
886 ippLength(ipp_t
*ipp
) /* I - IPP message */
888 return (ipp_length(ipp
, 0));
893 * 'ippNew()' - Allocate a new IPP message.
896 ipp_t
* /* O - New IPP message */
899 ipp_t
*temp
; /* New IPP message */
902 DEBUG_puts("ippNew()");
904 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
907 * Default to IPP 1.1...
910 temp
->request
.any
.version
[0] = 1;
911 temp
->request
.any
.version
[1] = 1;
914 DEBUG_printf(("ippNew: %p\n", temp
));
921 * 'ippNewRequest()' - Allocate a new IPP request message.
923 * The new request message is initialized with the attributes-charset and
924 * attributes-natural-language attributes added. The
925 * attributes-natural-language value is derived from the current locale.
930 ipp_t
* /* O - IPP request message */
931 ippNewRequest(ipp_op_t op
) /* I - Operation code */
933 ipp_t
*request
; /* IPP request message */
934 cups_lang_t
*language
; /* Current language localization */
938 * Create a new IPP message...
941 if ((request
= ippNew()) == NULL
)
945 * Set the operation and request ID...
948 request
->request
.op
.operation_id
= op
;
949 request
->request
.op
.request_id
= 1;
952 * Use UTF-8 as the character set...
955 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
956 "attributes-charset", NULL
, "utf-8");
959 * Get the language from the current locale...
962 language
= cupsLangDefault();
964 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
965 "attributes-natural-language", NULL
, language
->language
);
968 * Return the new request...
976 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
979 ipp_state_t
/* O - Current state */
980 ippRead(http_t
*http
, /* I - HTTP connection */
981 ipp_t
*ipp
) /* I - IPP data */
983 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
"\n",
984 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
989 DEBUG_printf(("http->state = %d\n", http
->state
));
991 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
,
992 http
->blocking
|| http
->used
!= 0, NULL
, ipp
));
997 * 'ippReadFile()' - Read data for an IPP message from a file.
999 * @since CUPS 1.1.19@
1002 ipp_state_t
/* O - Current state */
1003 ippReadFile(int fd
, /* I - HTTP data */
1004 ipp_t
*ipp
) /* I - IPP data */
1006 DEBUG_printf(("ippReadFile(%d, %p)\n", fd
, ipp
));
1008 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1013 * 'ippReadIO()' - Read data for an IPP message.
1018 ipp_state_t
/* O - Current state */
1019 ippReadIO(void *src
, /* I - Data source */
1020 ipp_iocb_t cb
, /* I - Read callback function */
1021 int blocking
, /* I - Use blocking IO? */
1022 ipp_t
*parent
, /* I - Parent request, if any */
1023 ipp_t
*ipp
) /* I - IPP data */
1025 int n
; /* Length of data */
1026 unsigned char buffer
[32768], /* Data buffer */
1027 string
[255], /* Small string buffer */
1028 *bufptr
; /* Pointer into buffer */
1029 ipp_attribute_t
*attr
; /* Current attribute */
1030 ipp_tag_t tag
; /* Current tag */
1031 ipp_tag_t value_tag
; /* Current value tag */
1032 ipp_value_t
*value
; /* Current value */
1035 DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src
, cb
, blocking
,
1037 DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp
->state
));
1039 if (src
== NULL
|| ipp
== NULL
)
1045 ipp
->state
++; /* Avoid common problem... */
1051 * Get the request header...
1054 if ((n
= (*cb
)(src
, buffer
, 8)) < 8)
1056 DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n
));
1061 * Verify the major version number...
1066 DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer
[0],
1072 * Then copy the request header over...
1075 ipp
->request
.any
.version
[0] = buffer
[0];
1076 ipp
->request
.any
.version
[1] = buffer
[1];
1077 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1078 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1079 buffer
[6]) << 8) | buffer
[7];
1081 DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1082 DEBUG_printf(("ippReadIO: op_status=%04x\n",
1083 ipp
->request
.any
.op_status
));
1084 DEBUG_printf(("ippReadIO: request_id=%d\n",
1085 ipp
->request
.any
.request_id
));
1088 ipp
->state
= IPP_ATTRIBUTE
;
1089 ipp
->current
= NULL
;
1090 ipp
->curtag
= IPP_TAG_ZERO
;
1091 ipp
->prev
= ipp
->last
;
1094 * If blocking is disabled, stop here...
1100 case IPP_ATTRIBUTE
:
1103 if ((*cb
)(src
, buffer
, 1) < 1)
1106 DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
1107 ipp
->current
, ipp
->prev
));
1110 * Read this attribute...
1113 tag
= (ipp_tag_t
)buffer
[0];
1115 if (tag
== IPP_TAG_END
)
1118 * No more attributes left...
1121 DEBUG_puts("ippReadIO: IPP_TAG_END!");
1123 ipp
->state
= IPP_DATA
;
1126 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1129 * Group tag... Set the current group and continue...
1132 if (ipp
->curtag
== tag
)
1133 ipp
->prev
= ippAddSeparator(ipp
);
1134 else if (ipp
->current
)
1135 ipp
->prev
= ipp
->current
;
1138 ipp
->current
= NULL
;
1139 DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag
,
1144 DEBUG_printf(("ippReadIO: value tag = %x\n", tag
));
1150 if ((*cb
)(src
, buffer
, 2) < 2)
1152 DEBUG_puts("ippReadIO: unable to read name length!");
1156 n
= (buffer
[0] << 8) | buffer
[1];
1158 if (n
> (sizeof(buffer
) - 1))
1160 DEBUG_printf(("ippReadIO: bad name length %d!\n", n
));
1164 DEBUG_printf(("ippReadIO: name length = %d\n", n
));
1166 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1167 tag
!= IPP_TAG_END_COLLECTION
)
1170 * More values for current attribute...
1173 if (ipp
->current
== NULL
)
1176 attr
= ipp
->current
;
1177 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1180 * Make sure we aren't adding a new value of a different
1184 if (value_tag
== IPP_TAG_ZERO
)
1187 * Setting the value of a collection member...
1190 attr
->value_tag
= tag
;
1192 else if (value_tag
== IPP_TAG_STRING
||
1193 (value_tag
>= IPP_TAG_TEXTLANG
&&
1194 value_tag
<= IPP_TAG_MIMETYPE
))
1197 * String values can sometimes come across in different
1198 * forms; accept sets of differing values...
1201 if (tag
!= IPP_TAG_STRING
&&
1202 (tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
))
1205 else if (value_tag
!= tag
)
1209 * Finally, reallocate the attribute array as needed...
1212 if (attr
->num_values
== 1 ||
1213 (attr
->num_values
> 0 &&
1214 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1216 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1219 DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
1220 attr
->num_values
+ IPP_MAX_VALUES
));
1223 * Reallocate memory...
1226 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1227 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1228 sizeof(ipp_value_t
))) == NULL
)
1234 * Reset pointers in the list...
1238 ipp
->prev
->next
= temp
;
1242 attr
= ipp
->current
= ipp
->last
= temp
;
1246 else if (tag
== IPP_TAG_MEMBERNAME
)
1249 * Name must be length 0!
1254 DEBUG_puts("ippReadIO: member name not empty!");
1259 ipp
->prev
= ipp
->current
;
1261 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1263 DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
1264 ipp
->current
, ipp
->prev
));
1266 attr
->group_tag
= ipp
->curtag
;
1267 attr
->value_tag
= IPP_TAG_ZERO
;
1268 attr
->num_values
= 0;
1270 else if (tag
!= IPP_TAG_END_COLLECTION
)
1273 * New attribute; read the name and add it...
1276 if ((*cb
)(src
, buffer
, n
) < n
)
1278 DEBUG_puts("ippReadIO: unable to read name!");
1285 ipp
->prev
= ipp
->current
;
1287 attr
= ipp
->current
= _ippAddAttr(ipp
, 1);
1289 DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n",
1290 buffer
, ipp
->current
, ipp
->prev
));
1292 attr
->group_tag
= ipp
->curtag
;
1293 attr
->value_tag
= tag
;
1294 attr
->name
= _cupsStrAlloc((char *)buffer
);
1295 attr
->num_values
= 0;
1300 if (tag
!= IPP_TAG_END_COLLECTION
)
1301 value
= attr
->values
+ attr
->num_values
;
1305 if ((*cb
)(src
, buffer
, 2) < 2)
1307 DEBUG_puts("ippReadIO: unable to read value length!");
1311 n
= (buffer
[0] << 8) | buffer
[1];
1312 DEBUG_printf(("ippReadIO: value length = %d\n", n
));
1316 case IPP_TAG_INTEGER
:
1318 if ((*cb
)(src
, buffer
, 4) < 4)
1320 DEBUG_puts("ippReadIO: Unable to read integer value!");
1324 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1329 case IPP_TAG_BOOLEAN
:
1330 if ((*cb
)(src
, buffer
, 1) < 1)
1332 DEBUG_puts("ippReadIO: Unable to read boolean value!");
1336 value
->boolean
= buffer
[0];
1340 case IPP_TAG_KEYWORD
:
1341 case IPP_TAG_STRING
:
1343 case IPP_TAG_URISCHEME
:
1344 case IPP_TAG_CHARSET
:
1345 case IPP_TAG_LANGUAGE
:
1346 case IPP_TAG_MIMETYPE
:
1347 if ((*cb
)(src
, buffer
, n
) < n
)
1349 DEBUG_puts("ippReadIO: unable to read name!");
1354 value
->string
.text
= _cupsStrAlloc((char *)buffer
);
1355 DEBUG_printf(("ippReadIO: value = \'%s\'\n",
1356 value
->string
.text
));
1359 if ((*cb
)(src
, value
->date
, 11) < 11)
1361 DEBUG_puts("ippReadIO: Unable to date integer value!");
1365 case IPP_TAG_RESOLUTION
:
1366 if ((*cb
)(src
, buffer
, 9) < 9)
1368 DEBUG_puts("ippReadIO: Unable to read resolution value!");
1372 value
->resolution
.xres
=
1373 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1375 value
->resolution
.yres
=
1376 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1378 value
->resolution
.units
=
1379 (ipp_res_t
)buffer
[8];
1381 case IPP_TAG_RANGE
:
1382 if ((*cb
)(src
, buffer
, 8) < 8)
1384 DEBUG_puts("ippReadIO: Unable to read range value!");
1388 value
->range
.lower
=
1389 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1391 value
->range
.upper
=
1392 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1395 case IPP_TAG_TEXTLANG
:
1396 case IPP_TAG_NAMELANG
:
1397 if (n
> sizeof(buffer
) || n
< 4)
1399 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1403 if ((*cb
)(src
, buffer
, n
) < n
)
1405 DEBUG_puts("ippReadIO: Unable to read string w/language value!");
1412 * text-with-language and name-with-language are composite
1421 n
= (bufptr
[0] << 8) | bufptr
[1];
1423 if (n
>= sizeof(string
))
1425 memcpy(string
, bufptr
+ 2, sizeof(string
) - 1);
1426 string
[sizeof(string
) - 1] = '\0';
1430 memcpy(string
, bufptr
+ 2, n
);
1434 value
->string
.charset
= _cupsStrAlloc((char *)string
);
1437 n
= (bufptr
[0] << 8) | bufptr
[1];
1439 bufptr
[2 + n
] = '\0';
1440 value
->string
.text
= _cupsStrAlloc((char *)bufptr
+ 2);
1443 case IPP_TAG_BEGIN_COLLECTION
:
1445 * Oh, boy, here comes a collection value, so read it...
1448 value
->collection
= ippNew();
1452 DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
1456 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1458 DEBUG_puts("ippReadIO: Unable to read collection value!");
1463 case IPP_TAG_END_COLLECTION
:
1466 DEBUG_puts("ippReadIO: endCollection tag with value length > 0!");
1470 DEBUG_puts("ippReadIO: endCollection tag...");
1472 return (ipp
->state
= IPP_DATA
);
1474 case IPP_TAG_MEMBERNAME
:
1476 * The value the name of the member in the collection, which
1477 * we need to carry over...
1480 if ((*cb
)(src
, buffer
, n
) < n
)
1482 DEBUG_puts("ippReadIO: Unable to read member name value!");
1487 attr
->name
= _cupsStrAlloc((char *)buffer
);
1490 * Since collection members are encoded differently than
1491 * regular attributes, make sure we don't start with an
1495 attr
->num_values
--;
1497 DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr
->name
));
1500 default : /* Other unsupported values */
1501 value
->unknown
.length
= n
;
1504 value
->unknown
.data
= malloc(n
);
1505 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1507 DEBUG_puts("ippReadIO: Unable to read unsupported value!");
1512 value
->unknown
.data
= NULL
;
1516 attr
->num_values
++;
1519 * If blocking is disabled, stop here...
1531 break; /* anti-compiler-warning-code */
1534 DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp
->state
));
1536 return (ipp
->state
);
1541 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1544 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1545 ippTimeToDate(time_t t
) /* I - UNIX time value */
1547 struct tm
*unixdate
; /* UNIX unixdate/time info */
1548 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1549 /* RFC-1903 date/time data */
1553 * RFC-1903 date/time format is:
1555 * Byte(s) Description
1556 * ------- -----------
1557 * 0-1 Year (0 to 65535)
1561 * 5 Minutes (0 to 59)
1562 * 6 Seconds (0 to 60, 60 = "leap second")
1563 * 7 Deciseconds (0 to 9)
1565 * 9 UTC hours (0 to 11)
1566 * 10 UTC minutes (0 to 59)
1569 unixdate
= gmtime(&t
);
1570 unixdate
->tm_year
+= 1900;
1572 date
[0] = unixdate
->tm_year
>> 8;
1573 date
[1] = unixdate
->tm_year
;
1574 date
[2] = unixdate
->tm_mon
+ 1;
1575 date
[3] = unixdate
->tm_mday
;
1576 date
[4] = unixdate
->tm_hour
;
1577 date
[5] = unixdate
->tm_min
;
1578 date
[6] = unixdate
->tm_sec
;
1589 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1592 ipp_state_t
/* O - Current state */
1593 ippWrite(http_t
*http
, /* I - HTTP connection */
1594 ipp_t
*ipp
) /* I - IPP data */
1596 DEBUG_printf(("ippWrite(%p, %p)\n", http
, ipp
));
1601 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
,
1602 http
->blocking
, NULL
, ipp
));
1607 * 'ippWriteFile()' - Write data for an IPP message to a file.
1609 * @since CUPS 1.1.19@
1612 ipp_state_t
/* O - Current state */
1613 ippWriteFile(int fd
, /* I - HTTP data */
1614 ipp_t
*ipp
) /* I - IPP data */
1616 DEBUG_printf(("ippWriteFile(%d, %p)\n", fd
, ipp
));
1618 ipp
->state
= IPP_IDLE
;
1620 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1625 * 'ippWriteIO()' - Write data for an IPP message.
1630 ipp_state_t
/* O - Current state */
1631 ippWriteIO(void *dst
, /* I - Destination */
1632 ipp_iocb_t cb
, /* I - Write callback function */
1633 int blocking
, /* I - Use blocking IO? */
1634 ipp_t
*parent
, /* I - Parent IPP message */
1635 ipp_t
*ipp
) /* I - IPP data */
1637 int i
; /* Looping var */
1638 int n
; /* Length of data */
1639 unsigned char buffer
[32768], /* Data buffer */
1640 *bufptr
; /* Pointer into buffer */
1641 ipp_attribute_t
*attr
; /* Current attribute */
1642 ipp_value_t
*value
; /* Current value */
1645 DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst
, cb
, blocking
,
1648 if (dst
== NULL
|| ipp
== NULL
)
1654 ipp
->state
++; /* Avoid common problem... */
1660 * Send the request header:
1663 * Operation/Status Code = 2 bytes
1664 * Request ID = 4 bytes
1670 *bufptr
++ = ipp
->request
.any
.version
[0];
1671 *bufptr
++ = ipp
->request
.any
.version
[1];
1672 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1673 *bufptr
++ = ipp
->request
.any
.op_status
;
1674 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1675 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1676 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1677 *bufptr
++ = ipp
->request
.any
.request_id
;
1679 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1681 DEBUG_puts("ippWriteIO: Could not write IPP header...");
1687 * Reset the state engine to point to the first attribute
1688 * in the request/response, with no current group.
1691 ipp
->state
= IPP_ATTRIBUTE
;
1692 ipp
->current
= ipp
->attrs
;
1693 ipp
->curtag
= IPP_TAG_ZERO
;
1695 DEBUG_printf(("ippWriteIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1696 DEBUG_printf(("ippWriteIO: op_status=%04x\n", ipp
->request
.any
.op_status
));
1697 DEBUG_printf(("ippWriteIO: request_id=%d\n", ipp
->request
.any
.request_id
));
1700 * If blocking is disabled, stop here...
1706 case IPP_ATTRIBUTE
:
1707 while (ipp
->current
!= NULL
)
1710 * Write this attribute...
1714 attr
= ipp
->current
;
1716 ipp
->current
= ipp
->current
->next
;
1718 if (ipp
->curtag
!= attr
->group_tag
&& parent
== NULL
)
1721 * Send a group tag byte...
1724 ipp
->curtag
= attr
->group_tag
;
1726 if (attr
->group_tag
== IPP_TAG_ZERO
)
1729 DEBUG_printf(("ippWriteIO: wrote group tag = %x\n", attr
->group_tag
));
1730 *bufptr
++ = attr
->group_tag
;
1732 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1736 * Write the attribute tag and name. The current implementation
1737 * does not support the extension value tags above 0x7f, so all
1738 * value tags are 1 byte.
1740 * The attribute name length does not include the trailing nul
1741 * character in the source string.
1743 * Collection values (parent != NULL) are written differently...
1749 * Get the length of the attribute name, and make sure it won't
1750 * overflow the buffer...
1753 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 4))
1757 * Write the value tag, name length, and name string...
1760 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr
->value_tag
));
1761 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n
, attr
->name
));
1763 *bufptr
++ = attr
->value_tag
;
1766 memcpy(bufptr
, attr
->name
, n
);
1772 * Get the length of the attribute name, and make sure it won't
1773 * overflow the buffer...
1776 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 7))
1780 * Write the member name tag, name length, name string, value tag,
1781 * and empty name for the collection member attribute...
1784 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1785 IPP_TAG_MEMBERNAME
));
1786 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n
, attr
->name
));
1787 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr
->value_tag
));
1788 DEBUG_puts("ippWriteIO: writing name = 0, \'\'\n");
1790 *bufptr
++ = IPP_TAG_MEMBERNAME
;
1795 memcpy(bufptr
, attr
->name
, n
);
1798 *bufptr
++ = attr
->value_tag
;
1804 * Now write the attribute value(s)...
1807 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
1809 case IPP_TAG_INTEGER
:
1811 for (i
= 0, value
= attr
->values
;
1812 i
< attr
->num_values
;
1815 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 9)
1817 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1819 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1829 * Arrays and sets are done by sending additional
1830 * values with a zero-length name...
1833 *bufptr
++ = attr
->value_tag
;
1839 * Integers and enumerations are both 4-byte signed
1840 * (twos-complement) values.
1842 * Put the 2-byte length and 4-byte value into the buffer...
1847 *bufptr
++ = value
->integer
>> 24;
1848 *bufptr
++ = value
->integer
>> 16;
1849 *bufptr
++ = value
->integer
>> 8;
1850 *bufptr
++ = value
->integer
;
1854 case IPP_TAG_BOOLEAN
:
1855 for (i
= 0, value
= attr
->values
;
1856 i
< attr
->num_values
;
1859 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 6)
1861 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1863 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1873 * Arrays and sets are done by sending additional
1874 * values with a zero-length name...
1877 *bufptr
++ = attr
->value_tag
;
1883 * Boolean values are 1-byte; 0 = false, 1 = true.
1885 * Put the 2-byte length and 1-byte value into the buffer...
1890 *bufptr
++ = value
->boolean
;
1896 case IPP_TAG_KEYWORD
:
1897 case IPP_TAG_STRING
:
1899 case IPP_TAG_URISCHEME
:
1900 case IPP_TAG_CHARSET
:
1901 case IPP_TAG_LANGUAGE
:
1902 case IPP_TAG_MIMETYPE
:
1903 for (i
= 0, value
= attr
->values
;
1904 i
< attr
->num_values
;
1910 * Arrays and sets are done by sending additional
1911 * values with a zero-length name...
1914 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1916 DEBUG_printf(("ippWriteIO: writing name = 0, \'\'\n"));
1918 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
1920 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1922 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1929 *bufptr
++ = attr
->value_tag
;
1934 if (value
->string
.text
!= NULL
)
1935 n
= (int)strlen(value
->string
.text
);
1939 if (n
> (sizeof(buffer
) - 2))
1942 DEBUG_printf(("ippWriteIO: writing string = %d, \'%s\'\n", n
,
1943 value
->string
.text
));
1945 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
1947 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1949 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1957 * All simple strings consist of the 2-byte length and
1958 * character data without the trailing nul normally found
1959 * in C strings. Also, strings cannot be longer than 32767
1960 * bytes since the 2-byte length is a signed (twos-complement)
1963 * Put the 2-byte length and string characters in the buffer.
1971 memcpy(bufptr
, value
->string
.text
, n
);
1978 for (i
= 0, value
= attr
->values
;
1979 i
< attr
->num_values
;
1982 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 16)
1984 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1986 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1996 * Arrays and sets are done by sending additional
1997 * values with a zero-length name...
2000 *bufptr
++ = attr
->value_tag
;
2006 * Date values consist of a 2-byte length and an
2007 * 11-byte date/time structure defined by RFC 1903.
2009 * Put the 2-byte length and 11-byte date/time
2010 * structure in the buffer.
2015 memcpy(bufptr
, value
->date
, 11);
2020 case IPP_TAG_RESOLUTION
:
2021 for (i
= 0, value
= attr
->values
;
2022 i
< attr
->num_values
;
2025 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 14)
2027 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2029 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2039 * Arrays and sets are done by sending additional
2040 * values with a zero-length name...
2043 *bufptr
++ = attr
->value_tag
;
2049 * Resolution values consist of a 2-byte length,
2050 * 4-byte horizontal resolution value, 4-byte vertical
2051 * resolution value, and a 1-byte units value.
2053 * Put the 2-byte length and resolution value data
2059 *bufptr
++ = value
->resolution
.xres
>> 24;
2060 *bufptr
++ = value
->resolution
.xres
>> 16;
2061 *bufptr
++ = value
->resolution
.xres
>> 8;
2062 *bufptr
++ = value
->resolution
.xres
;
2063 *bufptr
++ = value
->resolution
.yres
>> 24;
2064 *bufptr
++ = value
->resolution
.yres
>> 16;
2065 *bufptr
++ = value
->resolution
.yres
>> 8;
2066 *bufptr
++ = value
->resolution
.yres
;
2067 *bufptr
++ = value
->resolution
.units
;
2071 case IPP_TAG_RANGE
:
2072 for (i
= 0, value
= attr
->values
;
2073 i
< attr
->num_values
;
2076 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 13)
2078 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2080 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2090 * Arrays and sets are done by sending additional
2091 * values with a zero-length name...
2094 *bufptr
++ = attr
->value_tag
;
2100 * Range values consist of a 2-byte length,
2101 * 4-byte lower value, and 4-byte upper value.
2103 * Put the 2-byte length and range value data
2109 *bufptr
++ = value
->range
.lower
>> 24;
2110 *bufptr
++ = value
->range
.lower
>> 16;
2111 *bufptr
++ = value
->range
.lower
>> 8;
2112 *bufptr
++ = value
->range
.lower
;
2113 *bufptr
++ = value
->range
.upper
>> 24;
2114 *bufptr
++ = value
->range
.upper
>> 16;
2115 *bufptr
++ = value
->range
.upper
>> 8;
2116 *bufptr
++ = value
->range
.upper
;
2120 case IPP_TAG_TEXTLANG
:
2121 case IPP_TAG_NAMELANG
:
2122 for (i
= 0, value
= attr
->values
;
2123 i
< attr
->num_values
;
2129 * Arrays and sets are done by sending additional
2130 * values with a zero-length name...
2133 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2135 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2137 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2144 *bufptr
++ = attr
->value_tag
;
2150 * textWithLanguage and nameWithLanguage values consist
2151 * of a 2-byte length for both strings and their
2152 * individual lengths, a 2-byte length for the
2153 * character string, the character string without the
2154 * trailing nul, a 2-byte length for the character
2155 * set string, and the character set string without
2161 if (value
->string
.charset
!= NULL
)
2162 n
+= (int)strlen(value
->string
.charset
);
2164 if (value
->string
.text
!= NULL
)
2165 n
+= (int)strlen(value
->string
.text
);
2167 if (n
> (sizeof(buffer
) - 2))
2170 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2172 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2174 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2181 /* Length of entire value */
2185 /* Length of charset */
2186 if (value
->string
.charset
!= NULL
)
2187 n
= (int)strlen(value
->string
.charset
);
2197 memcpy(bufptr
, value
->string
.charset
, n
);
2201 /* Length of text */
2202 if (value
->string
.text
!= NULL
)
2203 n
= (int)strlen(value
->string
.text
);
2213 memcpy(bufptr
, value
->string
.text
, n
);
2219 case IPP_TAG_BEGIN_COLLECTION
:
2220 for (i
= 0, value
= attr
->values
;
2221 i
< attr
->num_values
;
2225 * Collections are written with the begin-collection
2226 * tag first with a value of 0 length, followed by the
2227 * attributes in the collection, then the end-collection
2231 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 5)
2233 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2235 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2245 * Arrays and sets are done by sending additional
2246 * values with a zero-length name...
2249 *bufptr
++ = attr
->value_tag
;
2255 * Write a data length of 0 and flush the buffer...
2261 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2263 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2270 * Then write the collection attribute...
2273 value
->collection
->state
= IPP_IDLE
;
2275 if (ippWriteIO(dst
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
2281 for (i
= 0, value
= attr
->values
;
2282 i
< attr
->num_values
;
2288 * Arrays and sets are done by sending additional
2289 * values with a zero-length name...
2292 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2294 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2296 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2303 *bufptr
++ = attr
->value_tag
;
2309 * An unknown value might some new value that a
2310 * vendor has come up with. It consists of a
2311 * 2-byte length and the bytes in the unknown
2315 n
= value
->unknown
.length
;
2317 if (n
> (sizeof(buffer
) - 2))
2320 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2322 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2324 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2331 /* Length of unknown value */
2338 memcpy(bufptr
, value
->unknown
.data
, n
);
2346 * Write the data out...
2349 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2351 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2355 DEBUG_printf(("ippWriteIO: wrote %d bytes\n", bufptr
- buffer
));
2358 * If blocking is disabled, stop here...
2365 if (ipp
->current
== NULL
)
2368 * Done with all of the attributes; add the end-of-attributes
2369 * tag or end-collection attribute...
2374 buffer
[0] = IPP_TAG_END
;
2379 buffer
[0] = IPP_TAG_END_COLLECTION
;
2380 buffer
[1] = 0; /* empty name */
2382 buffer
[3] = 0; /* empty value */
2387 if ((*cb
)(dst
, buffer
, n
) < 0)
2389 DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
2393 ipp
->state
= IPP_DATA
;
2401 break; /* anti-compiler-warning-code */
2404 return (ipp
->state
);
2409 * '_ippAddAttr()' - Add a new attribute to the request.
2412 ipp_attribute_t
* /* O - New attribute */
2413 _ippAddAttr(ipp_t
*ipp
, /* I - IPP message */
2414 int num_values
) /* I - Number of values */
2416 ipp_attribute_t
*attr
; /* New attribute */
2419 DEBUG_printf(("_ippAddAttr(%p, %d)\n", ipp
, num_values
));
2421 if (ipp
== NULL
|| num_values
< 0)
2424 attr
= calloc(sizeof(ipp_attribute_t
) +
2425 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2429 attr
->num_values
= num_values
;
2431 if (ipp
->last
== NULL
)
2434 ipp
->last
->next
= attr
;
2439 DEBUG_printf(("_ippAddAttr(): %p\n", attr
));
2446 * '_ippFreeAttr()' - Free an attribute.
2450 _ippFreeAttr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2452 int i
; /* Looping var */
2453 ipp_value_t
*value
; /* Current value */
2456 DEBUG_printf(("_ippFreeAttr(): %p\n", attr
));
2458 switch (attr
->value_tag
)
2462 case IPP_TAG_KEYWORD
:
2463 case IPP_TAG_STRING
:
2465 case IPP_TAG_URISCHEME
:
2466 case IPP_TAG_CHARSET
:
2467 case IPP_TAG_LANGUAGE
:
2468 case IPP_TAG_MIMETYPE
:
2469 for (i
= 0, value
= attr
->values
;
2470 i
< attr
->num_values
;
2472 _cupsStrFree(value
->string
.text
);
2475 case IPP_TAG_TEXTLANG
:
2476 case IPP_TAG_NAMELANG
:
2477 for (i
= 0, value
= attr
->values
;
2478 i
< attr
->num_values
;
2481 if (value
->string
.charset
&& i
== 0)
2482 _cupsStrFree(value
->string
.charset
);
2483 _cupsStrFree(value
->string
.text
);
2487 case IPP_TAG_INTEGER
:
2489 case IPP_TAG_BOOLEAN
:
2491 case IPP_TAG_RESOLUTION
:
2492 case IPP_TAG_RANGE
:
2495 case IPP_TAG_BEGIN_COLLECTION
:
2496 for (i
= 0, value
= attr
->values
;
2497 i
< attr
->num_values
;
2499 ippDelete(value
->collection
);
2503 if (!((int)attr
->value_tag
& IPP_TAG_COPY
))
2505 for (i
= 0, value
= attr
->values
;
2506 i
< attr
->num_values
;
2508 if (value
->unknown
.data
)
2509 free(value
->unknown
.data
);
2515 _cupsStrFree(attr
->name
);
2522 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2525 static size_t /* O - Size of IPP message */
2526 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2527 int collection
) /* I - 1 if a collection, 0 otherwise */
2529 int i
; /* Looping var */
2530 int bytes
; /* Number of bytes */
2531 ipp_attribute_t
*attr
; /* Current attribute */
2532 ipp_tag_t group
; /* Current group */
2533 ipp_value_t
*value
; /* Current value */
2540 * Start with 8 bytes for the IPP message header...
2543 bytes
= collection
? 0 : 8;
2546 * Then add the lengths of each attribute...
2549 group
= IPP_TAG_ZERO
;
2551 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2553 if (attr
->group_tag
!= group
&& !collection
)
2555 group
= attr
->group_tag
;
2556 if (group
== IPP_TAG_ZERO
)
2559 bytes
++; /* Group tag */
2565 DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n",
2566 attr
->name
, attr
->num_values
, bytes
));
2568 bytes
+= (int)strlen(attr
->name
); /* Name */
2569 bytes
+= attr
->num_values
; /* Value tag for each value */
2570 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2571 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2574 bytes
+= 5; /* Add membername overhead */
2576 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2578 case IPP_TAG_INTEGER
:
2580 bytes
+= 4 * attr
->num_values
;
2583 case IPP_TAG_BOOLEAN
:
2584 bytes
+= attr
->num_values
;
2589 case IPP_TAG_KEYWORD
:
2590 case IPP_TAG_STRING
:
2592 case IPP_TAG_URISCHEME
:
2593 case IPP_TAG_CHARSET
:
2594 case IPP_TAG_LANGUAGE
:
2595 case IPP_TAG_MIMETYPE
:
2596 for (i
= 0, value
= attr
->values
;
2597 i
< attr
->num_values
;
2599 if (value
->string
.text
!= NULL
)
2600 bytes
+= (int)strlen(value
->string
.text
);
2604 bytes
+= 11 * attr
->num_values
;
2607 case IPP_TAG_RESOLUTION
:
2608 bytes
+= 9 * attr
->num_values
;
2611 case IPP_TAG_RANGE
:
2612 bytes
+= 8 * attr
->num_values
;
2615 case IPP_TAG_TEXTLANG
:
2616 case IPP_TAG_NAMELANG
:
2617 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2619 for (i
= 0, value
= attr
->values
;
2620 i
< attr
->num_values
;
2623 if (value
->string
.charset
!= NULL
)
2624 bytes
+= (int)strlen(value
->string
.charset
);
2626 if (value
->string
.text
!= NULL
)
2627 bytes
+= (int)strlen(value
->string
.text
);
2631 case IPP_TAG_BEGIN_COLLECTION
:
2632 for (i
= 0, value
= attr
->values
;
2633 i
< attr
->num_values
;
2635 bytes
+= (int)ipp_length(value
->collection
, 1);
2639 for (i
= 0, value
= attr
->values
;
2640 i
< attr
->num_values
;
2642 bytes
+= value
->unknown
.length
;
2648 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2649 * for the "end of collection" tag and return...
2657 DEBUG_printf(("bytes = %d\n", bytes
));
2664 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2667 static ssize_t
/* O - Number of bytes read */
2668 ipp_read_http(http_t
*http
, /* I - Client connection */
2669 ipp_uchar_t
*buffer
, /* O - Buffer for data */
2670 size_t length
) /* I - Total length */
2672 int tbytes
, /* Total bytes read */
2673 bytes
; /* Bytes read this pass */
2674 char len
[32]; /* Length string */
2677 DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
2678 http
, buffer
, length
));
2681 * Loop until all bytes are read...
2684 for (tbytes
= 0, bytes
= 0; tbytes
< (int)length
; tbytes
+= bytes
, buffer
+= bytes
)
2686 DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes
, http
->state
));
2688 if (http
->state
== HTTP_WAITING
)
2691 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
2694 * Do "fast read" from HTTP buffer directly...
2697 if (http
->used
> (int)(length
- tbytes
))
2698 bytes
= (int)(length
- tbytes
);
2703 buffer
[0] = http
->buffer
[0];
2705 memcpy(buffer
, http
->buffer
, bytes
);
2707 http
->used
-= bytes
;
2708 http
->data_remaining
-= bytes
;
2710 if (http
->data_remaining
<= INT_MAX
)
2711 http
->_data_remaining
= (int)http
->data_remaining
;
2713 http
->_data_remaining
= INT_MAX
;
2716 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
2718 if (http
->data_remaining
== 0)
2720 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
2723 * Get the trailing CR LF after the chunk...
2726 if (!httpGets(len
, sizeof(len
), http
))
2730 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
2732 if (http
->state
== HTTP_POST_RECV
)
2735 http
->state
= HTTP_WAITING
;
2742 * Wait a maximum of 1 second for data...
2745 if (!http
->blocking
)
2748 * Wait up to 10 seconds for more data on non-blocking sockets...
2751 if (!httpWait(http
, 10000))
2762 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) <= 0)
2768 * Return the number of bytes read...
2771 if (tbytes
== 0 && bytes
< 0)
2774 DEBUG_printf(("returning %d bytes...\n", tbytes
));
2781 * 'ipp_read_file()' - Read IPP data from a file.
2784 static ssize_t
/* O - Number of bytes read */
2785 ipp_read_file(int *fd
, /* I - File descriptor */
2786 ipp_uchar_t
*buffer
, /* O - Read buffer */
2787 size_t length
) /* I - Number of bytes to read */
2790 return ((ssize_t
)read(*fd
, buffer
, (unsigned)length
));
2792 return (read(*fd
, buffer
, length
));
2798 * 'ipp_write_file()' - Write IPP data to a file.
2801 static ssize_t
/* O - Number of bytes written */
2802 ipp_write_file(int *fd
, /* I - File descriptor */
2803 ipp_uchar_t
*buffer
, /* I - Data to write */
2804 size_t length
) /* I - Number of bytes to write */
2807 return ((ssize_t
)write(*fd
, buffer
, (unsigned)length
));
2809 return (write(*fd
, buffer
, length
));
2816 * The following symbol definitions are provided only for KDE
2817 * compatibility during the CUPS 1.2 testing period and will be
2818 * removed in a future release of CUPS. These are PRIVATE APIs
2819 * from CUPS 1.1.x that the KDE developers chose to use...
2822 ipp_attribute_t
* /* O - New attribute */
2823 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
2824 int num_values
) /* I - Number of values */
2826 return (_ippAddAttr(ipp
, num_values
));
2830 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2834 #endif /* __linux */
2838 * End of "$Id: ipp.c 6230 2007-02-05 20:08:47Z mike $".