2 * "$Id: ipp.c 5023 2006-01-29 14:39:44Z mike $"
4 * Internet Printing Protocol support functions for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2006 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 * _ipp_add_attr() - Add a new attribute to the request.
61 * _ipp_free_attr() - 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
= _ipp_add_attr(ipp
, 1)) == NULL
)
117 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
151 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, 1)) == NULL
)
189 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
226 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, 1)) == NULL
)
262 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, 1)) == NULL
)
294 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
326 attr
->name
= strdup(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
= _ipp_add_attr(ipp
, 1)) == NULL
)
363 * Initialize the attribute data...
366 attr
->name
= strdup(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 */
400 if (ipp
== NULL
|| name
== NULL
)
403 if ((attr
= _ipp_add_attr(ipp
, 1)) == NULL
)
407 * Force value to be English for the POSIX locale...
410 if (type
== IPP_TAG_LANGUAGE
&& strcasecmp(value
, "C") == 0)
414 * Initialize the attribute data...
417 attr
->name
= strdup(name
);
418 attr
->group_tag
= group
;
419 attr
->value_tag
= type
;
420 attr
->values
[0].string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
421 charset
? strdup(charset
) : NULL
;
422 attr
->values
[0].string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)value
:
423 value
? strdup(value
) : NULL
;
426 * Convert language values to lowercase and change _ to - as needed...
429 if ((type
== IPP_TAG_LANGUAGE
|| type
== IPP_TAG_CHARSET
) &&
430 attr
->values
[0].string
.text
)
435 for (p
= attr
->values
[0].string
.text
; *p
; p
++)
439 *p
= tolower(*p
& 255);
447 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
450 ipp_attribute_t
* /* O - New attribute */
452 ipp_t
*ipp
, /* I - IPP message */
453 ipp_tag_t group
, /* I - IPP group */
454 ipp_tag_t type
, /* I - Type of attribute */
455 const char *name
, /* I - Name of attribute */
456 int num_values
, /* I - Number of values */
457 const char *charset
, /* I - Character set */
458 const char * const *values
) /* I - Values */
460 int i
; /* Looping var */
461 ipp_attribute_t
*attr
; /* New attribute */
462 ipp_value_t
*value
; /* Current value */
465 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
468 if ((attr
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
472 * Initialize the attribute data...
475 attr
->name
= strdup(name
);
476 attr
->group_tag
= group
;
477 attr
->value_tag
= type
;
479 for (i
= 0, value
= attr
->values
;
484 value
->string
.charset
= ((int)type
& IPP_TAG_COPY
) ? (char *)charset
:
485 charset
? strdup(charset
) : NULL
;
487 value
->string
.charset
= attr
->values
[0].string
.charset
;
492 * Force language to be English for the POSIX locale...
495 if (type
== IPP_TAG_LANGUAGE
&& strcasecmp(values
[i
], "C") == 0)
496 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? "en" :
499 value
->string
.text
= ((int)type
& IPP_TAG_COPY
) ? (char *)values
[i
] :
509 * 'ippAddRange()' - Add a range of values to an IPP message.
512 ipp_attribute_t
* /* O - New attribute */
513 ippAddRange(ipp_t
*ipp
, /* I - IPP message */
514 ipp_tag_t group
, /* I - IPP group */
515 const char *name
, /* I - Name of attribute */
516 int lower
, /* I - Lower value */
517 int upper
) /* I - Upper value */
519 ipp_attribute_t
*attr
; /* New attribute */
522 if (ipp
== NULL
|| name
== NULL
)
525 if ((attr
= _ipp_add_attr(ipp
, 1)) == NULL
)
528 attr
->name
= strdup(name
);
529 attr
->group_tag
= group
;
530 attr
->value_tag
= IPP_TAG_RANGE
;
531 attr
->values
[0].range
.lower
= lower
;
532 attr
->values
[0].range
.upper
= upper
;
539 * 'ippAddRanges()' - Add ranges of values to an IPP message.
542 ipp_attribute_t
* /* O - New attribute */
543 ippAddRanges(ipp_t
*ipp
, /* I - IPP message */
544 ipp_tag_t group
, /* I - IPP group */
545 const char *name
, /* I - Name of attribute */
546 int num_values
, /* I - Number of values */
547 const int *lower
, /* I - Lower values */
548 const int *upper
) /* I - Upper values */
550 int i
; /* Looping var */
551 ipp_attribute_t
*attr
; /* New attribute */
552 ipp_value_t
*value
; /* Current value */
555 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
558 if ((attr
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
561 attr
->name
= strdup(name
);
562 attr
->group_tag
= group
;
563 attr
->value_tag
= IPP_TAG_RANGE
;
565 if (lower
!= NULL
&& upper
!= NULL
)
566 for (i
= 0, value
= attr
->values
;
570 value
->range
.lower
= lower
[i
];
571 value
->range
.upper
= upper
[i
];
579 * 'ippAddResolution()' - Add a resolution value to an IPP message.
582 ipp_attribute_t
* /* O - New attribute */
583 ippAddResolution(ipp_t
*ipp
, /* I - IPP message */
584 ipp_tag_t group
, /* I - IPP group */
585 const char *name
, /* I - Name of attribute */
586 ipp_res_t units
, /* I - Units for resolution */
587 int xres
, /* I - X resolution */
588 int yres
) /* I - Y resolution */
590 ipp_attribute_t
*attr
; /* New attribute */
593 if (ipp
== NULL
|| name
== NULL
)
596 if ((attr
= _ipp_add_attr(ipp
, 1)) == NULL
)
599 attr
->name
= strdup(name
);
600 attr
->group_tag
= group
;
601 attr
->value_tag
= IPP_TAG_RESOLUTION
;
602 attr
->values
[0].resolution
.xres
= xres
;
603 attr
->values
[0].resolution
.yres
= yres
;
604 attr
->values
[0].resolution
.units
= units
;
611 * 'ippAddResolutions()' - Add resolution values to an IPP message.
614 ipp_attribute_t
* /* O - New attribute */
615 ippAddResolutions(ipp_t
*ipp
, /* I - IPP message */
616 ipp_tag_t group
, /* I - IPP group */
617 const char *name
, /* I - Name of attribute */
618 int num_values
,/* I - Number of values */
619 ipp_res_t units
, /* I - Units for resolution */
620 const int *xres
, /* I - X resolutions */
621 const int *yres
) /* I - Y resolutions */
623 int i
; /* Looping var */
624 ipp_attribute_t
*attr
; /* New attribute */
625 ipp_value_t
*value
; /* Current value */
628 if (ipp
== NULL
|| name
== NULL
|| num_values
< 1)
631 if ((attr
= _ipp_add_attr(ipp
, num_values
)) == NULL
)
634 attr
->name
= strdup(name
);
635 attr
->group_tag
= group
;
636 attr
->value_tag
= IPP_TAG_RESOLUTION
;
638 if (xres
!= NULL
&& yres
!= NULL
)
639 for (i
= 0, value
= attr
->values
;
643 value
->resolution
.xres
= xres
[i
];
644 value
->resolution
.yres
= yres
[i
];
645 value
->resolution
.units
= units
;
653 * 'ippAddSeparator()' - Add a group separator to an IPP message.
656 ipp_attribute_t
* /* O - New attribute */
657 ippAddSeparator(ipp_t
*ipp
) /* I - IPP message */
659 ipp_attribute_t
*attr
; /* New attribute */
662 DEBUG_printf(("ippAddSeparator(%p)\n", ipp
));
667 if ((attr
= _ipp_add_attr(ipp
, 0)) == NULL
)
670 attr
->group_tag
= IPP_TAG_ZERO
;
671 attr
->value_tag
= IPP_TAG_ZERO
;
678 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
682 time_t /* O - UNIX time value */
683 ippDateToTime(const ipp_uchar_t
*date
) /* I - RFC 1903 date info */
685 struct tm unixdate
; /* UNIX date/time info */
686 time_t t
; /* Computed time */
689 memset(&unixdate
, 0, sizeof(unixdate
));
692 * RFC-1903 date/time format is:
694 * Byte(s) Description
695 * ------- -----------
696 * 0-1 Year (0 to 65535)
700 * 5 Minutes (0 to 59)
701 * 6 Seconds (0 to 60, 60 = "leap second")
702 * 7 Deciseconds (0 to 9)
704 * 9 UTC hours (0 to 11)
705 * 10 UTC minutes (0 to 59)
708 unixdate
.tm_year
= ((date
[0] << 8) | date
[1]) - 1900;
709 unixdate
.tm_mon
= date
[2] - 1;
710 unixdate
.tm_mday
= date
[3];
711 unixdate
.tm_hour
= date
[4];
712 unixdate
.tm_min
= date
[5];
713 unixdate
.tm_sec
= date
[6];
715 t
= mktime(&unixdate
);
718 t
+= date
[9] * 3600 + date
[10] * 60;
720 t
-= date
[9] * 3600 + date
[10] * 60;
727 * 'ippDelete()' - Delete an IPP message.
731 ippDelete(ipp_t
*ipp
) /* I - IPP message */
733 ipp_attribute_t
*attr
, /* Current attribute */
734 *next
; /* Next attribute */
737 DEBUG_printf(("ippDelete(): %p\n", ipp
));
742 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= next
)
745 _ipp_free_attr(attr
);
753 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
755 * @since CUPS 1.1.19@
760 ipp_t
*ipp
, /* I - IPP message */
761 ipp_attribute_t
*attr
) /* I - Attribute to delete */
763 ipp_attribute_t
*current
, /* Current attribute */
764 *prev
; /* Previous attribute */
768 * Find the attribute in the list...
771 for (current
= ipp
->attrs
, prev
= NULL
;
772 current
!= NULL
&& current
!= attr
;
773 prev
= current
, current
= current
->next
);
778 * Found it, remove the attribute from the list...
782 prev
->next
= current
->next
;
784 ipp
->attrs
= current
->next
;
786 if (current
== ipp
->last
)
790 * Free memory used by the attribute...
793 _ipp_free_attr(current
);
799 * 'ippFindAttribute()' - Find a named attribute in a request...
802 ipp_attribute_t
* /* O - Matching attribute */
803 ippFindAttribute(ipp_t
*ipp
, /* I - IPP message */
804 const char *name
, /* I - Name of attribute */
805 ipp_tag_t type
) /* I - Type of attribute */
807 DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp
, name
));
809 if (ipp
== NULL
|| name
== NULL
)
813 * Reset the current pointer...
819 * Search for the attribute...
822 return (ippFindNextAttribute(ipp
, name
, type
));
827 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
830 ipp_attribute_t
* /* O - Matching attribute */
831 ippFindNextAttribute(ipp_t
*ipp
, /* I - IPP message */
832 const char *name
, /* I - Name of attribute */
833 ipp_tag_t type
) /* I - Type of attribute */
835 ipp_attribute_t
*attr
; /* Current atttribute */
836 ipp_tag_t value_tag
; /* Value tag */
839 DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp
, name
));
841 if (ipp
== NULL
|| name
== NULL
)
846 ipp
->prev
= ipp
->current
;
847 attr
= ipp
->current
->next
;
855 for (; attr
!= NULL
; ipp
->prev
= attr
, attr
= attr
->next
)
857 DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr
,
860 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
862 if (attr
->name
!= NULL
&& strcasecmp(attr
->name
, name
) == 0 &&
863 (value_tag
== type
|| type
== IPP_TAG_ZERO
||
864 (value_tag
== IPP_TAG_TEXTLANG
&& type
== IPP_TAG_TEXT
) ||
865 (value_tag
== IPP_TAG_NAMELANG
&& type
== IPP_TAG_NAME
)))
881 * 'ippLength()' - Compute the length of an IPP message.
884 size_t /* O - Size of IPP message */
885 ippLength(ipp_t
*ipp
) /* I - IPP message */
887 return (ipp_length(ipp
, 0));
892 * 'ippNew()' - Allocate a new IPP message.
895 ipp_t
* /* O - New IPP message */
898 ipp_t
*temp
; /* New IPP message */
901 DEBUG_puts("ippNew()");
903 if ((temp
= (ipp_t
*)calloc(1, sizeof(ipp_t
))) != NULL
)
906 * Default to IPP 1.1...
909 temp
->request
.any
.version
[0] = 1;
910 temp
->request
.any
.version
[1] = 1;
913 DEBUG_printf(("ippNew: %p\n", temp
));
920 * 'ippNewRequest()' - Allocate a new IPP request message.
922 * The new request message is initialized with the attributes-charset and
923 * attributes-natural-language attributes added. The
924 * attributes-natural-language value is derived from the current locale.
929 ipp_t
* /* O - IPP request message */
930 ippNewRequest(ipp_op_t op
) /* I - Operation code */
932 ipp_t
*request
; /* IPP request message */
933 cups_lang_t
*language
; /* Current language localization */
937 * Create a new IPP message...
940 if ((request
= ippNew()) == NULL
)
944 * Set the operation and request ID...
947 request
->request
.op
.operation_id
= op
;
948 request
->request
.op
.request_id
= 1;
951 * Use UTF-8 as the character set...
954 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
955 "attributes-charset", NULL
, "utf-8");
958 * Get the language from the current locale...
961 language
= cupsLangDefault();
963 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
964 "attributes-natural-language", NULL
, language
->language
);
967 * Return the new request...
975 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
978 ipp_state_t
/* O - Current state */
979 ippRead(http_t
*http
, /* I - HTTP connection */
980 ipp_t
*ipp
) /* I - IPP data */
982 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT
"\n",
983 http
, ipp
, CUPS_LLCAST (http
? http
->data_remaining
: -1)));
988 DEBUG_printf(("http->state = %d\n", http
->state
));
990 return (ippReadIO(http
, (ipp_iocb_t
)ipp_read_http
,
991 http
->blocking
|| http
->used
!= 0, NULL
, ipp
));
996 * 'ippReadFile()' - Read data for an IPP message from a file.
998 * @since CUPS 1.1.19@
1001 ipp_state_t
/* O - Current state */
1002 ippReadFile(int fd
, /* I - HTTP data */
1003 ipp_t
*ipp
) /* I - IPP data */
1005 DEBUG_printf(("ippReadFile(%d, %p)\n", fd
, ipp
));
1007 return (ippReadIO(&fd
, (ipp_iocb_t
)ipp_read_file
, 1, NULL
, ipp
));
1012 * 'ippReadIO()' - Read data for an IPP message.
1014 * @since CUPS 1.1.19@
1017 ipp_state_t
/* O - Current state */
1018 ippReadIO(void *src
, /* I - Data source */
1019 ipp_iocb_t cb
, /* I - Read callback function */
1020 int blocking
, /* I - Use blocking IO? */
1021 ipp_t
*parent
, /* I - Parent request, if any */
1022 ipp_t
*ipp
) /* I - IPP data */
1024 int n
; /* Length of data */
1025 unsigned char buffer
[32768], /* Data buffer */
1026 *bufptr
; /* Pointer into buffer */
1027 ipp_attribute_t
*attr
; /* Current attribute */
1028 ipp_tag_t tag
; /* Current tag */
1029 ipp_tag_t value_tag
; /* Current value tag */
1030 ipp_value_t
*value
; /* Current value */
1033 DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src
, cb
, blocking
,
1036 if (src
== NULL
|| ipp
== NULL
)
1042 ipp
->state
++; /* Avoid common problem... */
1048 * Get the request header...
1051 if ((n
= (*cb
)(src
, buffer
, 8)) < 8)
1053 DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n
));
1054 return (n
== 0 ? IPP_IDLE
: IPP_ERROR
);
1058 * Verify the major version number...
1063 DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer
[0],
1069 * Then copy the request header over...
1072 ipp
->request
.any
.version
[0] = buffer
[0];
1073 ipp
->request
.any
.version
[1] = buffer
[1];
1074 ipp
->request
.any
.op_status
= (buffer
[2] << 8) | buffer
[3];
1075 ipp
->request
.any
.request_id
= (((((buffer
[4] << 8) | buffer
[5]) << 8) |
1076 buffer
[6]) << 8) | buffer
[7];
1078 DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer
[0], buffer
[1]));
1079 DEBUG_printf(("ippReadIO: op_status=%04x\n",
1080 ipp
->request
.any
.op_status
));
1081 DEBUG_printf(("ippReadIO: request_id=%d\n",
1082 ipp
->request
.any
.request_id
));
1085 ipp
->state
= IPP_ATTRIBUTE
;
1086 ipp
->current
= NULL
;
1087 ipp
->curtag
= IPP_TAG_ZERO
;
1088 ipp
->prev
= ipp
->last
;
1091 * If blocking is disabled, stop here...
1097 case IPP_ATTRIBUTE
:
1098 while ((*cb
)(src
, buffer
, 1) > 0)
1100 DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
1101 ipp
->current
, ipp
->prev
));
1104 * Read this attribute...
1107 tag
= (ipp_tag_t
)buffer
[0];
1109 if (tag
== IPP_TAG_END
)
1112 * No more attributes left...
1115 DEBUG_puts("ippReadIO: IPP_TAG_END!");
1117 ipp
->state
= IPP_DATA
;
1120 else if (tag
< IPP_TAG_UNSUPPORTED_VALUE
)
1123 * Group tag... Set the current group and continue...
1126 if (ipp
->curtag
== tag
)
1127 ipp
->prev
= ippAddSeparator(ipp
);
1128 else if (ipp
->current
)
1129 ipp
->prev
= ipp
->current
;
1132 ipp
->current
= NULL
;
1133 DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag
,
1138 DEBUG_printf(("ippReadIO: value tag = %x\n", tag
));
1144 if ((*cb
)(src
, buffer
, 2) < 2)
1146 DEBUG_puts("ippReadIO: unable to read name length!");
1150 n
= (buffer
[0] << 8) | buffer
[1];
1152 if (n
> (sizeof(buffer
) - 1))
1154 DEBUG_printf(("ippReadIO: bad name length %d!\n", n
));
1158 DEBUG_printf(("ippReadIO: name length = %d\n", n
));
1160 if (n
== 0 && tag
!= IPP_TAG_MEMBERNAME
&&
1161 tag
!= IPP_TAG_END_COLLECTION
)
1164 * More values for current attribute...
1167 if (ipp
->current
== NULL
)
1170 attr
= ipp
->current
;
1171 value_tag
= (ipp_tag_t
)(attr
->value_tag
& IPP_TAG_MASK
);
1174 * Make sure we aren't adding a new value of a different
1178 if (value_tag
== IPP_TAG_ZERO
)
1181 * Setting the value of a collection member...
1184 attr
->value_tag
= tag
;
1186 else if (value_tag
== IPP_TAG_STRING
||
1187 (value_tag
>= IPP_TAG_TEXTLANG
&&
1188 value_tag
<= IPP_TAG_MIMETYPE
))
1191 * String values can sometimes come across in different
1192 * forms; accept sets of differing values...
1195 if (tag
!= IPP_TAG_STRING
&&
1196 (tag
< IPP_TAG_TEXTLANG
|| tag
> IPP_TAG_MIMETYPE
))
1199 else if (value_tag
!= tag
)
1203 * Finally, reallocate the attribute array as needed...
1206 if (attr
->num_values
== 1 ||
1207 (attr
->num_values
> 0 &&
1208 (attr
->num_values
& (IPP_MAX_VALUES
- 1)) == 0))
1210 ipp_attribute_t
*temp
; /* Pointer to new buffer */
1213 DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
1214 attr
->num_values
+ IPP_MAX_VALUES
));
1217 * Reallocate memory...
1220 if ((temp
= realloc(attr
, sizeof(ipp_attribute_t
) +
1221 (attr
->num_values
+ IPP_MAX_VALUES
- 1) *
1222 sizeof(ipp_value_t
))) == NULL
)
1228 * Reset pointers in the list...
1232 ipp
->prev
->next
= temp
;
1236 attr
= ipp
->current
= ipp
->last
= temp
;
1240 else if (tag
== IPP_TAG_MEMBERNAME
)
1243 * Name must be length 0!
1248 DEBUG_puts("ippReadIO: member name not empty!");
1253 ipp
->prev
= ipp
->current
;
1255 attr
= ipp
->current
= _ipp_add_attr(ipp
, 1);
1257 DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
1258 ipp
->current
, ipp
->prev
));
1260 attr
->group_tag
= ipp
->curtag
;
1261 attr
->value_tag
= IPP_TAG_ZERO
;
1262 attr
->num_values
= 0;
1264 else if (tag
!= IPP_TAG_END_COLLECTION
)
1267 * New attribute; read the name and add it...
1270 if ((*cb
)(src
, buffer
, n
) < n
)
1272 DEBUG_puts("ippReadIO: unable to read name!");
1279 ipp
->prev
= ipp
->current
;
1281 attr
= ipp
->current
= _ipp_add_attr(ipp
, 1);
1283 DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n",
1284 buffer
, ipp
->current
, ipp
->prev
));
1286 attr
->group_tag
= ipp
->curtag
;
1287 attr
->value_tag
= tag
;
1288 attr
->name
= strdup((char *)buffer
);
1289 attr
->num_values
= 0;
1294 if (tag
!= IPP_TAG_END_COLLECTION
)
1295 value
= attr
->values
+ attr
->num_values
;
1299 if ((*cb
)(src
, buffer
, 2) < 2)
1301 DEBUG_puts("ippReadIO: unable to read value length!");
1305 n
= (buffer
[0] << 8) | buffer
[1];
1306 DEBUG_printf(("ippReadIO: value length = %d\n", n
));
1310 case IPP_TAG_INTEGER
:
1312 if ((*cb
)(src
, buffer
, 4) < 4)
1314 DEBUG_puts("ippReadIO: Unable to read integer value!");
1318 n
= (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1323 case IPP_TAG_BOOLEAN
:
1324 if ((*cb
)(src
, buffer
, 1) < 1)
1326 DEBUG_puts("ippReadIO: Unable to read boolean value!");
1330 value
->boolean
= buffer
[0];
1334 case IPP_TAG_KEYWORD
:
1335 case IPP_TAG_STRING
:
1337 case IPP_TAG_URISCHEME
:
1338 case IPP_TAG_CHARSET
:
1339 case IPP_TAG_LANGUAGE
:
1340 case IPP_TAG_MIMETYPE
:
1341 value
->string
.text
= calloc(n
+ 1, 1);
1343 if ((*cb
)(src
, (ipp_uchar_t
*)value
->string
.text
, n
) < n
)
1345 DEBUG_puts("ippReadIO: Unable to read string value!");
1349 DEBUG_printf(("ippReadIO: value = \'%s\'\n",
1350 value
->string
.text
));
1353 if ((*cb
)(src
, value
->date
, 11) < 11)
1355 DEBUG_puts("ippReadIO: Unable to date integer value!");
1359 case IPP_TAG_RESOLUTION
:
1360 if ((*cb
)(src
, buffer
, 9) < 9)
1362 DEBUG_puts("ippReadIO: Unable to read resolution value!");
1366 value
->resolution
.xres
=
1367 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1369 value
->resolution
.yres
=
1370 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1372 value
->resolution
.units
=
1373 (ipp_res_t
)buffer
[8];
1375 case IPP_TAG_RANGE
:
1376 if ((*cb
)(src
, buffer
, 8) < 8)
1378 DEBUG_puts("ippReadIO: Unable to read range value!");
1382 value
->range
.lower
=
1383 (((((buffer
[0] << 8) | buffer
[1]) << 8) | buffer
[2]) << 8) |
1385 value
->range
.upper
=
1386 (((((buffer
[4] << 8) | buffer
[5]) << 8) | buffer
[6]) << 8) |
1389 case IPP_TAG_TEXTLANG
:
1390 case IPP_TAG_NAMELANG
:
1391 if (n
> sizeof(buffer
) || n
< 4)
1393 DEBUG_printf(("ippReadIO: bad value length %d!\n", n
));
1397 if ((*cb
)(src
, buffer
, n
) < n
)
1399 DEBUG_puts("ippReadIO: Unable to read string w/language value!");
1406 * text-with-language and name-with-language are composite
1415 n
= (bufptr
[0] << 8) | bufptr
[1];
1417 value
->string
.charset
= calloc(n
+ 1, 1);
1419 memcpy(value
->string
.charset
,
1423 n
= (bufptr
[0] << 8) | bufptr
[1];
1425 value
->string
.text
= calloc(n
+ 1, 1);
1427 memcpy(value
->string
.text
,
1431 case IPP_TAG_BEGIN_COLLECTION
:
1433 * Oh, boy, here comes a collection value, so read it...
1436 value
->collection
= ippNew();
1440 DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
1444 if (ippReadIO(src
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
1446 DEBUG_puts("ippReadIO: Unable to read collection value!");
1451 case IPP_TAG_END_COLLECTION
:
1454 DEBUG_puts("ippReadIO: endCollection tag with value length > 0!");
1458 DEBUG_puts("ippReadIO: endCollection tag...");
1460 return (ipp
->state
= IPP_DATA
);
1462 case IPP_TAG_MEMBERNAME
:
1464 * The value is the name of the member in the collection,
1465 * which we need to carry over...
1468 attr
->name
= calloc(n
+ 1, 1);
1470 if ((*cb
)(src
, (ipp_uchar_t
*)attr
->name
, n
) < n
)
1472 DEBUG_puts("ippReadIO: Unable to read member name value!");
1477 * Since collection members are encoded differently than
1478 * regular attributes, make sure we don't start with an
1482 attr
->num_values
--;
1484 DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr
->name
));
1487 default : /* Other unsupported values */
1488 value
->unknown
.length
= n
;
1491 value
->unknown
.data
= malloc(n
);
1492 if ((*cb
)(src
, value
->unknown
.data
, n
) < n
)
1494 DEBUG_puts("ippReadIO: Unable to read unsupported value!");
1499 value
->unknown
.data
= NULL
;
1503 attr
->num_values
++;
1506 * If blocking is disabled, stop here...
1518 break; /* anti-compiler-warning-code */
1521 return (ipp
->state
);
1526 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1529 const ipp_uchar_t
* /* O - RFC-1903 date/time data */
1530 ippTimeToDate(time_t t
) /* I - UNIX time value */
1532 struct tm
*unixdate
; /* UNIX unixdate/time info */
1533 ipp_uchar_t
*date
= _cupsGlobals()->ipp_date
;
1534 /* RFC-1903 date/time data */
1538 * RFC-1903 date/time format is:
1540 * Byte(s) Description
1541 * ------- -----------
1542 * 0-1 Year (0 to 65535)
1546 * 5 Minutes (0 to 59)
1547 * 6 Seconds (0 to 60, 60 = "leap second")
1548 * 7 Deciseconds (0 to 9)
1550 * 9 UTC hours (0 to 11)
1551 * 10 UTC minutes (0 to 59)
1554 unixdate
= gmtime(&t
);
1555 unixdate
->tm_year
+= 1900;
1557 date
[0] = unixdate
->tm_year
>> 8;
1558 date
[1] = unixdate
->tm_year
;
1559 date
[2] = unixdate
->tm_mon
+ 1;
1560 date
[3] = unixdate
->tm_mday
;
1561 date
[4] = unixdate
->tm_hour
;
1562 date
[5] = unixdate
->tm_min
;
1563 date
[6] = unixdate
->tm_sec
;
1574 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1577 ipp_state_t
/* O - Current state */
1578 ippWrite(http_t
*http
, /* I - HTTP connection */
1579 ipp_t
*ipp
) /* I - IPP data */
1581 DEBUG_printf(("ippWrite(%p, %p)\n", http
, ipp
));
1586 return (ippWriteIO(http
, (ipp_iocb_t
)httpWrite2
,
1587 http
->blocking
, NULL
, ipp
));
1592 * 'ippWriteFile()' - Write data for an IPP message to a file.
1594 * @since CUPS 1.1.19@
1597 ipp_state_t
/* O - Current state */
1598 ippWriteFile(int fd
, /* I - HTTP data */
1599 ipp_t
*ipp
) /* I - IPP data */
1601 DEBUG_printf(("ippWriteFile(%d, %p)\n", fd
, ipp
));
1603 ipp
->state
= IPP_IDLE
;
1605 return (ippWriteIO(&fd
, (ipp_iocb_t
)ipp_write_file
, 1, NULL
, ipp
));
1610 * 'ippWriteIO()' - Write data for an IPP message.
1612 * @since CUPS 1.1.19@
1615 ipp_state_t
/* O - Current state */
1616 ippWriteIO(void *dst
, /* I - Destination */
1617 ipp_iocb_t cb
, /* I - Write callback function */
1618 int blocking
, /* I - Use blocking IO? */
1619 ipp_t
*parent
, /* I - Parent IPP message */
1620 ipp_t
*ipp
) /* I - IPP data */
1622 int i
; /* Looping var */
1623 int n
; /* Length of data */
1624 unsigned char buffer
[32768], /* Data buffer */
1625 *bufptr
; /* Pointer into buffer */
1626 ipp_attribute_t
*attr
; /* Current attribute */
1627 ipp_value_t
*value
; /* Current value */
1630 DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst
, cb
, blocking
,
1633 if (dst
== NULL
|| ipp
== NULL
)
1639 ipp
->state
++; /* Avoid common problem... */
1645 * Send the request header:
1648 * Operation/Status Code = 2 bytes
1649 * Request ID = 4 bytes
1655 *bufptr
++ = ipp
->request
.any
.version
[0];
1656 *bufptr
++ = ipp
->request
.any
.version
[1];
1657 *bufptr
++ = ipp
->request
.any
.op_status
>> 8;
1658 *bufptr
++ = ipp
->request
.any
.op_status
;
1659 *bufptr
++ = ipp
->request
.any
.request_id
>> 24;
1660 *bufptr
++ = ipp
->request
.any
.request_id
>> 16;
1661 *bufptr
++ = ipp
->request
.any
.request_id
>> 8;
1662 *bufptr
++ = ipp
->request
.any
.request_id
;
1664 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1666 DEBUG_puts("ippWrite: Could not write IPP header...");
1672 * Reset the state engine to point to the first attribute
1673 * in the request/response, with no current group.
1676 ipp
->state
= IPP_ATTRIBUTE
;
1677 ipp
->current
= ipp
->attrs
;
1678 ipp
->curtag
= IPP_TAG_ZERO
;
1680 DEBUG_printf(("ippWrite: version=%d.%d\n", buffer
[0], buffer
[1]));
1681 DEBUG_printf(("ippWrite: op_status=%04x\n", ipp
->request
.any
.op_status
));
1682 DEBUG_printf(("ippWrite: request_id=%d\n", ipp
->request
.any
.request_id
));
1685 * If blocking is disabled, stop here...
1691 case IPP_ATTRIBUTE
:
1692 while (ipp
->current
!= NULL
)
1695 * Write this attribute...
1699 attr
= ipp
->current
;
1701 ipp
->current
= ipp
->current
->next
;
1703 if (ipp
->curtag
!= attr
->group_tag
&& parent
== NULL
)
1706 * Send a group tag byte...
1709 ipp
->curtag
= attr
->group_tag
;
1711 if (attr
->group_tag
== IPP_TAG_ZERO
)
1714 DEBUG_printf(("ippWrite: wrote group tag = %x\n", attr
->group_tag
));
1715 *bufptr
++ = attr
->group_tag
;
1717 else if (attr
->group_tag
== IPP_TAG_ZERO
)
1721 * Write the attribute tag and name. The current implementation
1722 * does not support the extension value tags above 0x7f, so all
1723 * value tags are 1 byte.
1725 * The attribute name length does not include the trailing nul
1726 * character in the source string.
1728 * Collection values (parent != NULL) are written differently...
1734 * Get the length of the attribute name, and make sure it won't
1735 * overflow the buffer...
1738 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 4))
1742 * Write the value tag, name length, and name string...
1745 DEBUG_printf(("ippWrite: writing value tag = %x\n", attr
->value_tag
));
1746 DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n
, attr
->name
));
1748 *bufptr
++ = attr
->value_tag
;
1751 memcpy(bufptr
, attr
->name
, n
);
1757 * Get the length of the attribute name, and make sure it won't
1758 * overflow the buffer...
1761 if ((n
= (int)strlen(attr
->name
)) > (sizeof(buffer
) - 7))
1765 * Write the member name tag, name length, name string, value tag,
1766 * and empty name for the collection member attribute...
1769 DEBUG_printf(("ippWrite: writing value tag = %x\n",
1770 IPP_TAG_MEMBERNAME
));
1771 DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n
, attr
->name
));
1772 DEBUG_printf(("ippWrite: writing value tag = %x\n", attr
->value_tag
));
1773 DEBUG_puts("ippWrite: writing name = 0, \'\'\n");
1775 *bufptr
++ = IPP_TAG_MEMBERNAME
;
1780 memcpy(bufptr
, attr
->name
, n
);
1783 *bufptr
++ = attr
->value_tag
;
1789 * Now write the attribute value(s)...
1792 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
1794 case IPP_TAG_INTEGER
:
1796 for (i
= 0, value
= attr
->values
;
1797 i
< attr
->num_values
;
1800 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 9)
1802 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1804 DEBUG_puts("ippWrite: Could not write IPP attribute...");
1814 * Arrays and sets are done by sending additional
1815 * values with a zero-length name...
1818 *bufptr
++ = attr
->value_tag
;
1824 * Integers and enumerations are both 4-byte signed
1825 * (twos-complement) values.
1827 * Put the 2-byte length and 4-byte value into the buffer...
1832 *bufptr
++ = value
->integer
>> 24;
1833 *bufptr
++ = value
->integer
>> 16;
1834 *bufptr
++ = value
->integer
>> 8;
1835 *bufptr
++ = value
->integer
;
1839 case IPP_TAG_BOOLEAN
:
1840 for (i
= 0, value
= attr
->values
;
1841 i
< attr
->num_values
;
1844 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 6)
1846 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1848 DEBUG_puts("ippWrite: Could not write IPP attribute...");
1858 * Arrays and sets are done by sending additional
1859 * values with a zero-length name...
1862 *bufptr
++ = attr
->value_tag
;
1868 * Boolean values are 1-byte; 0 = false, 1 = true.
1870 * Put the 2-byte length and 1-byte value into the buffer...
1875 *bufptr
++ = value
->boolean
;
1881 case IPP_TAG_KEYWORD
:
1882 case IPP_TAG_STRING
:
1884 case IPP_TAG_URISCHEME
:
1885 case IPP_TAG_CHARSET
:
1886 case IPP_TAG_LANGUAGE
:
1887 case IPP_TAG_MIMETYPE
:
1888 for (i
= 0, value
= attr
->values
;
1889 i
< attr
->num_values
;
1895 * Arrays and sets are done by sending additional
1896 * values with a zero-length name...
1899 DEBUG_printf(("ippWrite: writing value tag = %x\n",
1901 DEBUG_printf(("ippWrite: writing name = 0, \'\'\n"));
1903 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
1905 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1907 DEBUG_puts("ippWrite: Could not write IPP attribute...");
1914 *bufptr
++ = attr
->value_tag
;
1919 if (value
->string
.text
!= NULL
)
1920 n
= (int)strlen(value
->string
.text
);
1924 if (n
> (sizeof(buffer
) - 2))
1927 DEBUG_printf(("ippWrite: writing string = %d, \'%s\'\n", n
,
1928 value
->string
.text
));
1930 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
1932 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1934 DEBUG_puts("ippWrite: Could not write IPP attribute...");
1942 * All simple strings consist of the 2-byte length and
1943 * character data without the trailing nul normally found
1944 * in C strings. Also, strings cannot be longer than 32767
1945 * bytes since the 2-byte length is a signed (twos-complement)
1948 * Put the 2-byte length and string characters in the buffer.
1956 memcpy(bufptr
, value
->string
.text
, n
);
1963 for (i
= 0, value
= attr
->values
;
1964 i
< attr
->num_values
;
1967 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 16)
1969 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
1971 DEBUG_puts("ippWrite: Could not write IPP attribute...");
1981 * Arrays and sets are done by sending additional
1982 * values with a zero-length name...
1985 *bufptr
++ = attr
->value_tag
;
1991 * Date values consist of a 2-byte length and an
1992 * 11-byte date/time structure defined by RFC 1903.
1994 * Put the 2-byte length and 11-byte date/time
1995 * structure in the buffer.
2000 memcpy(bufptr
, value
->date
, 11);
2005 case IPP_TAG_RESOLUTION
:
2006 for (i
= 0, value
= attr
->values
;
2007 i
< attr
->num_values
;
2010 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 14)
2012 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2014 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2024 * Arrays and sets are done by sending additional
2025 * values with a zero-length name...
2028 *bufptr
++ = attr
->value_tag
;
2034 * Resolution values consist of a 2-byte length,
2035 * 4-byte horizontal resolution value, 4-byte vertical
2036 * resolution value, and a 1-byte units value.
2038 * Put the 2-byte length and resolution value data
2044 *bufptr
++ = value
->resolution
.xres
>> 24;
2045 *bufptr
++ = value
->resolution
.xres
>> 16;
2046 *bufptr
++ = value
->resolution
.xres
>> 8;
2047 *bufptr
++ = value
->resolution
.xres
;
2048 *bufptr
++ = value
->resolution
.yres
>> 24;
2049 *bufptr
++ = value
->resolution
.yres
>> 16;
2050 *bufptr
++ = value
->resolution
.yres
>> 8;
2051 *bufptr
++ = value
->resolution
.yres
;
2052 *bufptr
++ = value
->resolution
.units
;
2056 case IPP_TAG_RANGE
:
2057 for (i
= 0, value
= attr
->values
;
2058 i
< attr
->num_values
;
2061 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 13)
2063 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2065 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2075 * Arrays and sets are done by sending additional
2076 * values with a zero-length name...
2079 *bufptr
++ = attr
->value_tag
;
2085 * Range values consist of a 2-byte length,
2086 * 4-byte lower value, and 4-byte upper value.
2088 * Put the 2-byte length and range value data
2094 *bufptr
++ = value
->range
.lower
>> 24;
2095 *bufptr
++ = value
->range
.lower
>> 16;
2096 *bufptr
++ = value
->range
.lower
>> 8;
2097 *bufptr
++ = value
->range
.lower
;
2098 *bufptr
++ = value
->range
.upper
>> 24;
2099 *bufptr
++ = value
->range
.upper
>> 16;
2100 *bufptr
++ = value
->range
.upper
>> 8;
2101 *bufptr
++ = value
->range
.upper
;
2105 case IPP_TAG_TEXTLANG
:
2106 case IPP_TAG_NAMELANG
:
2107 for (i
= 0, value
= attr
->values
;
2108 i
< attr
->num_values
;
2114 * Arrays and sets are done by sending additional
2115 * values with a zero-length name...
2118 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2120 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2122 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2129 *bufptr
++ = attr
->value_tag
;
2135 * textWithLanguage and nameWithLanguage values consist
2136 * of a 2-byte length for both strings and their
2137 * individual lengths, a 2-byte length for the
2138 * character string, the character string without the
2139 * trailing nul, a 2-byte length for the character
2140 * set string, and the character set string without
2146 if (value
->string
.charset
!= NULL
)
2147 n
+= strlen(value
->string
.charset
);
2149 if (value
->string
.text
!= NULL
)
2150 n
+= strlen(value
->string
.text
);
2152 if (n
> (sizeof(buffer
) - 2))
2155 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2157 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2159 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2166 /* Length of entire value */
2170 /* Length of charset */
2171 if (value
->string
.charset
!= NULL
)
2172 n
= (int)strlen(value
->string
.charset
);
2182 memcpy(bufptr
, value
->string
.charset
, n
);
2186 /* Length of text */
2187 if (value
->string
.text
!= NULL
)
2188 n
= (int)strlen(value
->string
.text
);
2198 memcpy(bufptr
, value
->string
.text
, n
);
2204 case IPP_TAG_BEGIN_COLLECTION
:
2205 for (i
= 0, value
= attr
->values
;
2206 i
< attr
->num_values
;
2210 * Collections are written with the begin-collection
2211 * tag first with a value of 0 length, followed by the
2212 * attributes in the collection, then the end-collection
2216 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 5)
2218 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2220 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2230 * Arrays and sets are done by sending additional
2231 * values with a zero-length name...
2234 *bufptr
++ = attr
->value_tag
;
2240 * Write a data length of 0 and flush the buffer...
2246 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2248 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2255 * Then write the collection attribute...
2258 value
->collection
->state
= IPP_IDLE
;
2260 if (ippWriteIO(dst
, cb
, 1, ipp
, value
->collection
) == IPP_ERROR
)
2266 for (i
= 0, value
= attr
->values
;
2267 i
< attr
->num_values
;
2273 * Arrays and sets are done by sending additional
2274 * values with a zero-length name...
2277 if ((sizeof(buffer
) - (bufptr
- buffer
)) < 3)
2279 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2281 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2288 *bufptr
++ = attr
->value_tag
;
2294 * An unknown value might some new value that a
2295 * vendor has come up with. It consists of a
2296 * 2-byte length and the bytes in the unknown
2300 n
= value
->unknown
.length
;
2302 if (n
> (sizeof(buffer
) - 2))
2305 if ((int)(sizeof(buffer
) - (bufptr
- buffer
)) < (n
+ 2))
2307 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2309 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2316 /* Length of unknown value */
2323 memcpy(bufptr
, value
->unknown
.data
, n
);
2331 * Write the data out...
2334 if ((*cb
)(dst
, buffer
, (int)(bufptr
- buffer
)) < 0)
2336 DEBUG_puts("ippWrite: Could not write IPP attribute...");
2340 DEBUG_printf(("ippWrite: wrote %d bytes\n", bufptr
- buffer
));
2343 * If blocking is disabled, stop here...
2350 if (ipp
->current
== NULL
)
2353 * Done with all of the attributes; add the end-of-attributes
2354 * tag or end-collection attribute...
2359 buffer
[0] = IPP_TAG_END
;
2364 buffer
[0] = IPP_TAG_END_COLLECTION
;
2365 buffer
[1] = 0; /* empty name */
2367 buffer
[3] = 0; /* empty value */
2372 if ((*cb
)(dst
, buffer
, n
) < 0)
2374 DEBUG_puts("ippWrite: Could not write IPP end-tag...");
2378 ipp
->state
= IPP_DATA
;
2386 break; /* anti-compiler-warning-code */
2389 return (ipp
->state
);
2394 * '_ipp_add_attr()' - Add a new attribute to the request.
2397 ipp_attribute_t
* /* O - New attribute */
2398 _ipp_add_attr(ipp_t
*ipp
, /* I - IPP message */
2399 int num_values
) /* I - Number of values */
2401 ipp_attribute_t
*attr
; /* New attribute */
2404 DEBUG_printf(("_ipp_add_attr(%p, %d)\n", ipp
, num_values
));
2406 if (ipp
== NULL
|| num_values
< 0)
2409 attr
= calloc(sizeof(ipp_attribute_t
) +
2410 (num_values
- 1) * sizeof(ipp_value_t
), 1);
2414 attr
->num_values
= num_values
;
2416 if (ipp
->last
== NULL
)
2419 ipp
->last
->next
= attr
;
2424 DEBUG_printf(("_ipp_add_attr(): %p\n", attr
));
2431 * '_ipp_free_attr()' - Free an attribute.
2435 _ipp_free_attr(ipp_attribute_t
*attr
) /* I - Attribute to free */
2437 int i
; /* Looping var */
2438 ipp_value_t
*value
; /* Current value */
2441 DEBUG_printf(("_ipp_free_attr(): %p\n", attr
));
2443 switch (attr
->value_tag
)
2447 case IPP_TAG_KEYWORD
:
2448 case IPP_TAG_STRING
:
2450 case IPP_TAG_URISCHEME
:
2451 case IPP_TAG_CHARSET
:
2452 case IPP_TAG_LANGUAGE
:
2453 case IPP_TAG_MIMETYPE
:
2454 for (i
= 0, value
= attr
->values
;
2455 i
< attr
->num_values
;
2457 free(value
->string
.text
);
2460 case IPP_TAG_TEXTLANG
:
2461 case IPP_TAG_NAMELANG
:
2462 for (i
= 0, value
= attr
->values
;
2463 i
< attr
->num_values
;
2466 if (value
->string
.charset
&& i
== 0)
2467 free(value
->string
.charset
);
2468 free(value
->string
.text
);
2473 break; /* anti-compiler-warning-code */
2484 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2487 static size_t /* O - Size of IPP message */
2488 ipp_length(ipp_t
*ipp
, /* I - IPP message or collection */
2489 int collection
) /* I - 1 if a collection, 0 otherwise */
2491 int i
; /* Looping var */
2492 int bytes
; /* Number of bytes */
2493 ipp_attribute_t
*attr
; /* Current attribute */
2494 ipp_tag_t group
; /* Current group */
2495 ipp_value_t
*value
; /* Current value */
2502 * Start with 8 bytes for the IPP message header...
2505 bytes
= collection
? 0 : 8;
2508 * Then add the lengths of each attribute...
2511 group
= IPP_TAG_ZERO
;
2513 for (attr
= ipp
->attrs
; attr
!= NULL
; attr
= attr
->next
)
2515 if (attr
->group_tag
!= group
&& !collection
)
2517 group
= attr
->group_tag
;
2518 if (group
== IPP_TAG_ZERO
)
2521 bytes
++; /* Group tag */
2527 DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n",
2528 attr
->name
, attr
->num_values
, bytes
));
2530 bytes
+= strlen(attr
->name
); /* Name */
2531 bytes
+= attr
->num_values
; /* Value tag for each value */
2532 bytes
+= 2 * attr
->num_values
; /* Name lengths */
2533 bytes
+= 2 * attr
->num_values
; /* Value lengths */
2536 bytes
+= 5; /* Add membername overhead */
2538 switch (attr
->value_tag
& ~IPP_TAG_COPY
)
2540 case IPP_TAG_INTEGER
:
2542 bytes
+= 4 * attr
->num_values
;
2545 case IPP_TAG_BOOLEAN
:
2546 bytes
+= attr
->num_values
;
2551 case IPP_TAG_KEYWORD
:
2552 case IPP_TAG_STRING
:
2554 case IPP_TAG_URISCHEME
:
2555 case IPP_TAG_CHARSET
:
2556 case IPP_TAG_LANGUAGE
:
2557 case IPP_TAG_MIMETYPE
:
2558 for (i
= 0, value
= attr
->values
;
2559 i
< attr
->num_values
;
2561 if (value
->string
.text
!= NULL
)
2562 bytes
+= strlen(value
->string
.text
);
2566 bytes
+= 11 * attr
->num_values
;
2569 case IPP_TAG_RESOLUTION
:
2570 bytes
+= 9 * attr
->num_values
;
2573 case IPP_TAG_RANGE
:
2574 bytes
+= 8 * attr
->num_values
;
2577 case IPP_TAG_TEXTLANG
:
2578 case IPP_TAG_NAMELANG
:
2579 bytes
+= 4 * attr
->num_values
;/* Charset + text length */
2581 for (i
= 0, value
= attr
->values
;
2582 i
< attr
->num_values
;
2585 if (value
->string
.charset
!= NULL
)
2586 bytes
+= strlen(value
->string
.charset
);
2588 if (value
->string
.text
!= NULL
)
2589 bytes
+= strlen(value
->string
.text
);
2593 case IPP_TAG_BEGIN_COLLECTION
:
2594 for (i
= 0, value
= attr
->values
;
2595 i
< attr
->num_values
;
2597 bytes
+= ipp_length(attr
->values
[i
].collection
, 1);
2601 for (i
= 0, value
= attr
->values
;
2602 i
< attr
->num_values
;
2604 bytes
+= attr
->values
[0].unknown
.length
;
2610 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2611 * for the "end of collection" tag and return...
2619 DEBUG_printf(("bytes = %d\n", bytes
));
2626 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2629 static ssize_t
/* O - Number of bytes read */
2630 ipp_read_http(http_t
*http
, /* I - Client connection */
2631 ipp_uchar_t
*buffer
, /* O - Buffer for data */
2632 size_t length
) /* I - Total length */
2634 int tbytes
, /* Total bytes read */
2635 bytes
; /* Bytes read this pass */
2636 char len
[32]; /* Length string */
2639 DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
2640 http
, buffer
, length
));
2643 * Loop until all bytes are read...
2646 for (tbytes
= 0, bytes
= 0; tbytes
< length
; tbytes
+= bytes
, buffer
+= bytes
)
2648 DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes
, http
->state
));
2650 if (http
->state
== HTTP_WAITING
)
2653 if (http
->used
> 0 && http
->data_encoding
== HTTP_ENCODE_LENGTH
)
2656 * Do "fast read" from HTTP buffer directly...
2659 if (http
->used
> (length
- tbytes
))
2660 bytes
= length
- tbytes
;
2665 buffer
[0] = http
->buffer
[0];
2667 memcpy(buffer
, http
->buffer
, bytes
);
2669 http
->used
-= bytes
;
2670 http
->data_remaining
-= bytes
;
2672 if (http
->data_remaining
<= INT_MAX
)
2673 http
->_data_remaining
= (int)http
->data_remaining
;
2675 http
->_data_remaining
= INT_MAX
;
2678 memmove(http
->buffer
, http
->buffer
+ bytes
, http
->used
);
2680 if (http
->data_remaining
== 0)
2682 if (http
->data_encoding
== HTTP_ENCODE_CHUNKED
)
2685 * Get the trailing CR LF after the chunk...
2688 if (!httpGets(len
, sizeof(len
), http
))
2692 if (http
->data_encoding
!= HTTP_ENCODE_CHUNKED
)
2694 if (http
->state
== HTTP_POST_RECV
)
2697 http
->state
= HTTP_WAITING
;
2704 * Wait a maximum of 1 second for data...
2707 if (!http
->blocking
)
2710 * Wait up to 1 second for more data on non-blocking sockets...
2713 if (!httpWait(http
, 1000))
2724 if ((bytes
= httpRead2(http
, (char *)buffer
, length
- tbytes
)) <= 0)
2730 * Return the number of bytes read...
2733 if (tbytes
== 0 && bytes
< 0)
2736 DEBUG_printf(("returning %d bytes...\n", tbytes
));
2743 * 'ipp_read_file()' - Read IPP data from a file.
2746 static ssize_t
/* O - Number of bytes read */
2747 ipp_read_file(int *fd
, /* I - File descriptor */
2748 ipp_uchar_t
*buffer
, /* O - Read buffer */
2749 size_t length
) /* I - Number of bytes to read */
2751 return (read(*fd
, buffer
, length
));
2756 * 'ipp_write_file()' - Write IPP data to a file.
2759 static ssize_t
/* O - Number of bytes written */
2760 ipp_write_file(int *fd
, /* I - File descriptor */
2761 ipp_uchar_t
*buffer
, /* I - Data to write */
2762 size_t length
) /* I - Number of bytes to write */
2764 return (write(*fd
, buffer
, length
));
2769 * End of "$Id: ipp.c 5023 2006-01-29 14:39:44Z mike $".