]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp.c
Merge changes from CUPS 1.5b1-r9798.
[thirdparty/cups.git] / cups / ipp.c
1 /*
2 * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
3 *
4 * Internet Printing Protocol functions for CUPS.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * ippAddBoolean() - Add a boolean attribute to an IPP message.
20 * ippAddBooleans() - Add an array of boolean values.
21 * ippAddDate() - Add a date attribute to an IPP message.
22 * ippAddInteger() - Add a integer attribute to an IPP message.
23 * ippAddIntegers() - Add an array of integer values.
24 * ippAddOctetString() - Add an octetString value to an IPP message.
25 * ippAddString() - Add a language-encoded string to an IPP message.
26 * ippAddStrings() - Add language-encoded strings to an IPP message.
27 * ippAddRange() - Add a range of values to an IPP message.
28 * ippAddRanges() - Add ranges of values to an IPP message.
29 * ippAddResolution() - Add a resolution value to an IPP message.
30 * ippAddResolutions() - Add resolution values to an IPP message.
31 * ippAddSeparator() - Add a group separator to an IPP message.
32 * ippDateToTime() - Convert from RFC 1903 Date/Time format to
33 * UNIX time in seconds.
34 * ippDelete() - Delete an IPP message.
35 * ippDeleteAttribute() - Delete a single attribute in an IPP message.
36 * ippFindAttribute() - Find a named attribute in a request...
37 * ippFindNextAttribute() - Find the next named attribute in a request...
38 * ippLength() - Compute the length of an IPP message.
39 * ippNew() - Allocate a new IPP message.
40 * ippNewRequest() - Allocate a new IPP message.
41 * ippRead() - Read data for an IPP message from a HTTP
42 * connection.
43 * ippReadFile() - Read data for an IPP message from a file.
44 * ippReadIO() - Read data for an IPP message.
45 * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
46 * ippWrite() - Write data for an IPP message to a HTTP
47 * connection.
48 * ippWriteFile() - Write data for an IPP message to a file.
49 * ippWriteIO() - Write data for an IPP message.
50 * _ippAddAttr() - Add a new attribute to the request.
51 * _ippFreeAttr() - Free an attribute.
52 * ipp_length() - Compute the length of an IPP message or
53 * collection value.
54 * ipp_read_http() - Semi-blocking read on a HTTP connection...
55 * ipp_read_file() - Read IPP data from a file.
56 * ipp_write_file() - Write IPP data to a file.
57 */
58
59 /*
60 * Include necessary headers...
61 */
62
63 #include "cups-private.h"
64 #ifdef WIN32
65 # include <io.h>
66 #endif /* WIN32 */
67
68
69 /*
70 * Local functions...
71 */
72
73 static unsigned char *ipp_buffer_get(void);
74 static void ipp_buffer_release(unsigned char *b);
75 static size_t ipp_length(ipp_t *ipp, int collection);
76 static ssize_t ipp_read_http(http_t *http, ipp_uchar_t *buffer,
77 size_t length);
78 static ssize_t ipp_read_file(int *fd, ipp_uchar_t *buffer,
79 size_t length);
80 static ssize_t ipp_write_file(int *fd, ipp_uchar_t *buffer,
81 size_t length);
82
83
84 /*
85 * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
86 */
87
88 ipp_attribute_t * /* O - New attribute */
89 ippAddBoolean(ipp_t *ipp, /* I - IPP message */
90 ipp_tag_t group, /* I - IPP group */
91 const char *name, /* I - Name of attribute */
92 char value) /* I - Value of attribute */
93 {
94 ipp_attribute_t *attr; /* New attribute */
95
96
97 DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)",
98 ipp, group, ippTagString(group), name, value));
99
100 if (!ipp || !name)
101 return (NULL);
102
103 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
104 return (NULL);
105
106 attr->name = _cupsStrAlloc(name);
107 attr->group_tag = group;
108 attr->value_tag = IPP_TAG_BOOLEAN;
109 attr->values[0].boolean = value;
110
111 return (attr);
112 }
113
114
115 /*
116 * 'ippAddBooleans()' - Add an array of boolean values.
117 */
118
119 ipp_attribute_t * /* O - New attribute */
120 ippAddBooleans(ipp_t *ipp, /* I - IPP message */
121 ipp_tag_t group, /* I - IPP group */
122 const char *name, /* I - Name of attribute */
123 int num_values, /* I - Number of values */
124 const char *values) /* I - Values */
125 {
126 int i; /* Looping var */
127 ipp_attribute_t *attr; /* New attribute */
128 ipp_value_t *value; /* Current value */
129
130
131 DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", "
132 "num_values=%d, values=%p)", ipp, group, ippTagString(group),
133 name, num_values, values));
134
135 if (!ipp || !name || num_values < 1)
136 return (NULL);
137
138 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
139 return (NULL);
140
141 attr->name = _cupsStrAlloc(name);
142 attr->group_tag = group;
143 attr->value_tag = IPP_TAG_BOOLEAN;
144
145 if (values != NULL)
146 for (i = 0, value = attr->values;
147 i < num_values;
148 i ++, value ++)
149 value->boolean = values[i];
150
151 return (attr);
152 }
153
154
155 /*
156 * 'ippAddCollection()' - Add a collection value.
157 *
158 * @since CUPS 1.1.19/Mac OS X 10.3@
159 */
160
161 ipp_attribute_t * /* O - New attribute */
162 ippAddCollection(ipp_t *ipp, /* I - IPP message */
163 ipp_tag_t group, /* I - IPP group */
164 const char *name, /* I - Name of attribute */
165 ipp_t *value) /* I - Value */
166 {
167 ipp_attribute_t *attr; /* New attribute */
168
169
170 DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", "
171 "value=%p)", ipp, group, ippTagString(group), name, value));
172
173 if (!ipp || !name)
174 return (NULL);
175
176 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
177 return (NULL);
178
179 attr->name = _cupsStrAlloc(name);
180 attr->group_tag = group;
181 attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
182 attr->values[0].collection = value;
183
184 value->use ++;
185
186 return (attr);
187 }
188
189
190 /*
191 * 'ippAddCollections()' - Add an array of collection values.
192 *
193 * @since CUPS 1.1.19/Mac OS X 10.3@
194 */
195
196 ipp_attribute_t * /* O - New attribute */
197 ippAddCollections(
198 ipp_t *ipp, /* I - IPP message */
199 ipp_tag_t group, /* I - IPP group */
200 const char *name, /* I - Name of attribute */
201 int num_values, /* I - Number of values */
202 const ipp_t **values) /* I - Values */
203 {
204 int i; /* Looping var */
205 ipp_attribute_t *attr; /* New attribute */
206 ipp_value_t *value; /* Current value */
207
208
209 DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
210 "num_values=%d, values=%p)", ipp, group, ippTagString(group),
211 name, num_values, values));
212
213 if (!ipp || !name || num_values < 1)
214 return (NULL);
215
216 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
217 return (NULL);
218
219 attr->name = _cupsStrAlloc(name);
220 attr->group_tag = group;
221 attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
222
223 if (values != NULL)
224 {
225 for (i = 0, value = attr->values;
226 i < num_values;
227 i ++, value ++)
228 {
229 value->collection = (ipp_t *)values[i];
230 value->collection->use ++;
231 }
232 }
233
234 return (attr);
235 }
236
237
238 /*
239 * 'ippAddDate()' - Add a date attribute to an IPP message.
240 */
241
242 ipp_attribute_t * /* O - New attribute */
243 ippAddDate(ipp_t *ipp, /* I - IPP message */
244 ipp_tag_t group, /* I - IPP group */
245 const char *name, /* I - Name of attribute */
246 const ipp_uchar_t *value) /* I - Value */
247 {
248 ipp_attribute_t *attr; /* New attribute */
249
250
251 DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
252 ipp, group, ippTagString(group), name, value));
253
254 if (!ipp || !name || !value)
255 return (NULL);
256
257 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
258 return (NULL);
259
260 attr->name = _cupsStrAlloc(name);
261 attr->group_tag = group;
262 attr->value_tag = IPP_TAG_DATE;
263 memcpy(attr->values[0].date, value, 11);
264
265 return (attr);
266 }
267
268
269 /*
270 * 'ippAddInteger()' - Add a integer attribute to an IPP message.
271 */
272
273 ipp_attribute_t * /* O - New attribute */
274 ippAddInteger(ipp_t *ipp, /* I - IPP message */
275 ipp_tag_t group, /* I - IPP group */
276 ipp_tag_t type, /* I - Type of attribute */
277 const char *name, /* I - Name of attribute */
278 int value) /* I - Value of attribute */
279 {
280 ipp_attribute_t *attr; /* New attribute */
281
282
283 DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
284 "name=\"%s\", value=%d)", ipp, group, ippTagString(group),
285 type, ippTagString(type), name, value));
286
287 if (!ipp || !name)
288 return (NULL);
289
290 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
291 return (NULL);
292
293 attr->name = _cupsStrAlloc(name);
294 attr->group_tag = group;
295 attr->value_tag = type;
296 attr->values[0].integer = value;
297
298 return (attr);
299 }
300
301
302 /*
303 * 'ippAddIntegers()' - Add an array of integer values.
304 */
305
306 ipp_attribute_t * /* O - New attribute */
307 ippAddIntegers(ipp_t *ipp, /* I - IPP message */
308 ipp_tag_t group, /* I - IPP group */
309 ipp_tag_t type, /* I - Type of attribute */
310 const char *name, /* I - Name of attribute */
311 int num_values, /* I - Number of values */
312 const int *values) /* I - Values */
313 {
314 int i; /* Looping var */
315 ipp_attribute_t *attr; /* New attribute */
316 ipp_value_t *value; /* Current value */
317
318
319 DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
320 "name=\"%s\", num_values=%d, values=%p)", ipp,
321 group, ippTagString(group), type, ippTagString(type), name,
322 num_values, values));
323
324 if (!ipp || !name || num_values < 1)
325 return (NULL);
326
327 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
328 return (NULL);
329
330 attr->name = _cupsStrAlloc(name);
331 attr->group_tag = group;
332 attr->value_tag = type;
333
334 if (values != NULL)
335 for (i = 0, value = attr->values;
336 i < num_values;
337 i ++, value ++)
338 value->integer = values[i];
339
340 return (attr);
341 }
342
343
344 /*
345 * 'ippAddOctetString()' - Add an octetString value to an IPP message.
346 *
347 * @since CUPS 1.2/Mac OS X 10.5@
348 */
349
350 ipp_attribute_t * /* O - New attribute */
351 ippAddOctetString(ipp_t *ipp, /* I - IPP message */
352 ipp_tag_t group, /* I - IPP group */
353 const char *name, /* I - Name of attribute */
354 const void *data, /* I - octetString data */
355 int datalen) /* I - Length of data in bytes */
356 {
357 ipp_attribute_t *attr; /* New attribute */
358
359
360 if (ipp == NULL || name == NULL)
361 return (NULL);
362
363 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
364 return (NULL);
365
366 /*
367 * Initialize the attribute data...
368 */
369
370 attr->name = _cupsStrAlloc(name);
371 attr->group_tag = group;
372 attr->value_tag = IPP_TAG_STRING;
373 attr->values[0].unknown.length = datalen;
374
375 if (data)
376 {
377 if ((attr->values[0].unknown.data = malloc(datalen)) == NULL)
378 {
379 ippDeleteAttribute(ipp, attr);
380 return (NULL);
381 }
382
383 memcpy(attr->values[0].unknown.data, data, datalen);
384 }
385
386 /*
387 * Return the new attribute...
388 */
389
390 return (attr);
391 }
392
393
394 /*
395 * 'ippAddString()' - Add a language-encoded string to an IPP message.
396 */
397
398 ipp_attribute_t * /* O - New attribute */
399 ippAddString(ipp_t *ipp, /* I - IPP message */
400 ipp_tag_t group, /* I - IPP group */
401 ipp_tag_t type, /* I - Type of attribute */
402 const char *name, /* I - Name of attribute */
403 const char *charset, /* I - Character set */
404 const char *value) /* I - Value */
405 {
406 ipp_attribute_t *attr; /* New attribute */
407 char buffer[1024], /* Language/charset value buffer */
408 *bufptr; /* Pointer into buffer */
409
410
411 DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
412 "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp,
413 group, ippTagString(group), type, ippTagString(type), name,
414 charset, value));
415
416 if (!ipp || !name)
417 return (NULL);
418
419 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
420 return (NULL);
421
422 /*
423 * Force value to be English for the POSIX locale...
424 */
425
426 if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(value, "C"))
427 value = "en";
428
429 /*
430 * Convert language and charset values to lowercase and change _ to - as
431 * needed...
432 */
433
434 if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value)
435 {
436 strlcpy(buffer, value, sizeof(buffer));
437 value = buffer;
438
439 for (bufptr = buffer; *bufptr; bufptr ++)
440 if (*bufptr == '_')
441 *bufptr = '-';
442 else
443 *bufptr = tolower(*bufptr & 255);
444 }
445
446 /*
447 * Initialize the attribute data...
448 */
449
450 attr->name = _cupsStrAlloc(name);
451 attr->group_tag = group;
452 attr->value_tag = type;
453 attr->values[0].string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
454 charset ? _cupsStrAlloc(charset) : NULL;
455 attr->values[0].string.text = ((int)type & IPP_TAG_COPY) ? (char *)value :
456 value ? _cupsStrAlloc(value) : NULL;
457
458 return (attr);
459 }
460
461
462 /*
463 * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
464 */
465
466 ipp_attribute_t * /* O - New attribute */
467 ippAddStrings(
468 ipp_t *ipp, /* I - IPP message */
469 ipp_tag_t group, /* I - IPP group */
470 ipp_tag_t type, /* I - Type of attribute */
471 const char *name, /* I - Name of attribute */
472 int num_values, /* I - Number of values */
473 const char *charset, /* I - Character set */
474 const char * const *values) /* I - Values */
475 {
476 int i; /* Looping var */
477 ipp_attribute_t *attr; /* New attribute */
478 ipp_value_t *value; /* Current value */
479 char buffer[1024], /* Language/charset value buffer */
480 *bufptr; /* Pointer into buffer */
481
482
483 DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
484 "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp,
485 group, ippTagString(group), type, ippTagString(type), name,
486 num_values, charset, values));
487
488 if (!ipp || !name || num_values < 1)
489 return (NULL);
490
491 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
492 return (NULL);
493
494 /*
495 * Initialize the attribute data...
496 */
497
498 attr->name = _cupsStrAlloc(name);
499 attr->group_tag = group;
500 attr->value_tag = type;
501
502 for (i = 0, value = attr->values;
503 i < num_values;
504 i ++, value ++)
505 {
506 if (i == 0)
507 value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
508 charset ? _cupsStrAlloc(charset) : NULL;
509 else
510 value->string.charset = attr->values[0].string.charset;
511
512 if (values != NULL)
513 {
514 if ((int)type & IPP_TAG_COPY)
515 value->string.text = (char *)values[i];
516 else if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(values[i], "C"))
517 {
518 /*
519 * Force language to be English for the POSIX locale...
520 */
521
522 value->string.text = ((int)type & IPP_TAG_COPY) ? "en" :
523 _cupsStrAlloc("en");
524 }
525 else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET)
526 {
527 /*
528 * Convert language values to lowercase and change _ to - as needed...
529 */
530
531 strlcpy(buffer, values[i], sizeof(buffer));
532
533 for (bufptr = buffer; *bufptr; bufptr ++)
534 if (*bufptr == '_')
535 *bufptr = '-';
536 else
537 *bufptr = tolower(*bufptr & 255);
538
539 value->string.text = _cupsStrAlloc(buffer);
540 }
541 else
542 value->string.text = _cupsStrAlloc(values[i]);
543
544 }
545 }
546
547 return (attr);
548 }
549
550
551 /*
552 * 'ippAddRange()' - Add a range of values to an IPP message.
553 */
554
555 ipp_attribute_t * /* O - New attribute */
556 ippAddRange(ipp_t *ipp, /* I - IPP message */
557 ipp_tag_t group, /* I - IPP group */
558 const char *name, /* I - Name of attribute */
559 int lower, /* I - Lower value */
560 int upper) /* I - Upper value */
561 {
562 ipp_attribute_t *attr; /* New attribute */
563
564
565 DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
566 "upper=%d)", ipp, group, ippTagString(group), name, lower,
567 upper));
568
569 if (!ipp || !name)
570 return (NULL);
571
572 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
573 return (NULL);
574
575 attr->name = _cupsStrAlloc(name);
576 attr->group_tag = group;
577 attr->value_tag = IPP_TAG_RANGE;
578 attr->values[0].range.lower = lower;
579 attr->values[0].range.upper = upper;
580
581 return (attr);
582 }
583
584
585 /*
586 * 'ippAddRanges()' - Add ranges of values to an IPP message.
587 */
588
589 ipp_attribute_t * /* O - New attribute */
590 ippAddRanges(ipp_t *ipp, /* I - IPP message */
591 ipp_tag_t group, /* I - IPP group */
592 const char *name, /* I - Name of attribute */
593 int num_values, /* I - Number of values */
594 const int *lower, /* I - Lower values */
595 const int *upper) /* I - Upper values */
596 {
597 int i; /* Looping var */
598 ipp_attribute_t *attr; /* New attribute */
599 ipp_value_t *value; /* Current value */
600
601
602 DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
603 "num_values=%d, lower=%p, upper=%p)", ipp, group,
604 ippTagString(group), name, num_values, lower, upper));
605
606 if (!ipp || !name || num_values < 1)
607 return (NULL);
608
609 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
610 return (NULL);
611
612 attr->name = _cupsStrAlloc(name);
613 attr->group_tag = group;
614 attr->value_tag = IPP_TAG_RANGE;
615
616 if (lower != NULL && upper != NULL)
617 for (i = 0, value = attr->values;
618 i < num_values;
619 i ++, value ++)
620 {
621 value->range.lower = lower[i];
622 value->range.upper = upper[i];
623 }
624
625 return (attr);
626 }
627
628
629 /*
630 * 'ippAddResolution()' - Add a resolution value to an IPP message.
631 */
632
633 ipp_attribute_t * /* O - New attribute */
634 ippAddResolution(ipp_t *ipp, /* I - IPP message */
635 ipp_tag_t group, /* I - IPP group */
636 const char *name, /* I - Name of attribute */
637 ipp_res_t units, /* I - Units for resolution */
638 int xres, /* I - X resolution */
639 int yres) /* I - Y resolution */
640 {
641 ipp_attribute_t *attr; /* New attribute */
642
643
644 DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
645 "units=%d, xres=%d, yres=%d)", ipp, group,
646 ippTagString(group), name, units, xres, yres));
647
648 if (!ipp || !name)
649 return (NULL);
650
651 if ((attr = _ippAddAttr(ipp, 1)) == NULL)
652 return (NULL);
653
654 attr->name = _cupsStrAlloc(name);
655 attr->group_tag = group;
656 attr->value_tag = IPP_TAG_RESOLUTION;
657 attr->values[0].resolution.xres = xres;
658 attr->values[0].resolution.yres = yres;
659 attr->values[0].resolution.units = units;
660
661 return (attr);
662 }
663
664
665 /*
666 * 'ippAddResolutions()' - Add resolution values to an IPP message.
667 */
668
669 ipp_attribute_t * /* O - New attribute */
670 ippAddResolutions(ipp_t *ipp, /* I - IPP message */
671 ipp_tag_t group, /* I - IPP group */
672 const char *name, /* I - Name of attribute */
673 int num_values,/* I - Number of values */
674 ipp_res_t units, /* I - Units for resolution */
675 const int *xres, /* I - X resolutions */
676 const int *yres) /* I - Y resolutions */
677 {
678 int i; /* Looping var */
679 ipp_attribute_t *attr; /* New attribute */
680 ipp_value_t *value; /* Current value */
681
682
683 DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
684 "num_value=%d, units=%d, xres=%p, yres=%p)", ipp, group,
685 ippTagString(group), name, num_values, units, xres, yres));
686
687 if (!ipp || !name || num_values < 1)
688 return (NULL);
689
690 if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
691 return (NULL);
692
693 attr->name = _cupsStrAlloc(name);
694 attr->group_tag = group;
695 attr->value_tag = IPP_TAG_RESOLUTION;
696
697 if (xres != NULL && yres != NULL)
698 for (i = 0, value = attr->values;
699 i < num_values;
700 i ++, value ++)
701 {
702 value->resolution.xres = xres[i];
703 value->resolution.yres = yres[i];
704 value->resolution.units = units;
705 }
706
707 return (attr);
708 }
709
710
711 /*
712 * 'ippAddSeparator()' - Add a group separator to an IPP message.
713 */
714
715 ipp_attribute_t * /* O - New attribute */
716 ippAddSeparator(ipp_t *ipp) /* I - IPP message */
717 {
718 ipp_attribute_t *attr; /* New attribute */
719
720
721 DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp));
722
723 if (!ipp)
724 return (NULL);
725
726 if ((attr = _ippAddAttr(ipp, 0)) == NULL)
727 return (NULL);
728
729 attr->group_tag = IPP_TAG_ZERO;
730 attr->value_tag = IPP_TAG_ZERO;
731
732 return (attr);
733 }
734
735
736 /*
737 * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
738 * in seconds.
739 */
740
741 time_t /* O - UNIX time value */
742 ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
743 {
744 struct tm unixdate; /* UNIX date/time info */
745 time_t t; /* Computed time */
746
747
748 if (!date)
749 return (0);
750
751 memset(&unixdate, 0, sizeof(unixdate));
752
753 /*
754 * RFC-1903 date/time format is:
755 *
756 * Byte(s) Description
757 * ------- -----------
758 * 0-1 Year (0 to 65535)
759 * 2 Month (1 to 12)
760 * 3 Day (1 to 31)
761 * 4 Hours (0 to 23)
762 * 5 Minutes (0 to 59)
763 * 6 Seconds (0 to 60, 60 = "leap second")
764 * 7 Deciseconds (0 to 9)
765 * 8 +/- UTC
766 * 9 UTC hours (0 to 11)
767 * 10 UTC minutes (0 to 59)
768 */
769
770 unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900;
771 unixdate.tm_mon = date[2] - 1;
772 unixdate.tm_mday = date[3];
773 unixdate.tm_hour = date[4];
774 unixdate.tm_min = date[5];
775 unixdate.tm_sec = date[6];
776
777 t = mktime(&unixdate);
778
779 if (date[8] == '-')
780 t += date[9] * 3600 + date[10] * 60;
781 else
782 t -= date[9] * 3600 + date[10] * 60;
783
784 return (t);
785 }
786
787
788 /*
789 * 'ippDelete()' - Delete an IPP message.
790 */
791
792 void
793 ippDelete(ipp_t *ipp) /* I - IPP message */
794 {
795 ipp_attribute_t *attr, /* Current attribute */
796 *next; /* Next attribute */
797
798
799 DEBUG_printf(("ippDelete(ipp=%p)", ipp));
800
801 if (!ipp)
802 return;
803
804 ipp->use --;
805 if (ipp->use > 0)
806 return;
807
808 for (attr = ipp->attrs; attr != NULL; attr = next)
809 {
810 next = attr->next;
811 _ippFreeAttr(attr);
812 }
813
814 free(ipp);
815 }
816
817
818 /*
819 * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
820 *
821 * @since CUPS 1.1.19/Mac OS X 10.3@
822 */
823
824 void
825 ippDeleteAttribute(
826 ipp_t *ipp, /* I - IPP message */
827 ipp_attribute_t *attr) /* I - Attribute to delete */
828 {
829 ipp_attribute_t *current, /* Current attribute */
830 *prev; /* Previous attribute */
831
832
833 DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr,
834 attr ? attr->name : "(null)"));
835
836 /*
837 * Find the attribute in the list...
838 */
839
840 for (current = ipp->attrs, prev = NULL;
841 current != NULL && current != attr;
842 prev = current, current = current->next);
843
844 if (current)
845 {
846 /*
847 * Found it, remove the attribute from the list...
848 */
849
850 if (prev)
851 prev->next = current->next;
852 else
853 ipp->attrs = current->next;
854
855 if (current == ipp->last)
856 ipp->last = prev;
857
858 /*
859 * Free memory used by the attribute...
860 */
861
862 _ippFreeAttr(current);
863 }
864 }
865
866
867 /*
868 * 'ippFindAttribute()' - Find a named attribute in a request...
869 */
870
871 ipp_attribute_t * /* O - Matching attribute */
872 ippFindAttribute(ipp_t *ipp, /* I - IPP message */
873 const char *name, /* I - Name of attribute */
874 ipp_tag_t type) /* I - Type of attribute */
875 {
876 DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp,
877 name, type, ippTagString(type)));
878
879 if (!ipp || !name)
880 return (NULL);
881
882 /*
883 * Reset the current pointer...
884 */
885
886 ipp->current = NULL;
887
888 /*
889 * Search for the attribute...
890 */
891
892 return (ippFindNextAttribute(ipp, name, type));
893 }
894
895
896 /*
897 * 'ippFindNextAttribute()' - Find the next named attribute in a request...
898 */
899
900 ipp_attribute_t * /* O - Matching attribute */
901 ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */
902 const char *name, /* I - Name of attribute */
903 ipp_tag_t type) /* I - Type of attribute */
904 {
905 ipp_attribute_t *attr; /* Current atttribute */
906 ipp_tag_t value_tag; /* Value tag */
907
908
909 DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
910 ipp, name, type, ippTagString(type)));
911
912 if (!ipp || !name)
913 return (NULL);
914
915 if (ipp->current)
916 {
917 ipp->prev = ipp->current;
918 attr = ipp->current->next;
919 }
920 else
921 {
922 ipp->prev = NULL;
923 attr = ipp->attrs;
924 }
925
926 for (; attr != NULL; ipp->prev = attr, attr = attr->next)
927 {
928 DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr,
929 attr->name));
930
931 value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
932
933 if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 &&
934 (value_tag == type || type == IPP_TAG_ZERO ||
935 (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) ||
936 (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
937 {
938 ipp->current = attr;
939
940 return (attr);
941 }
942 }
943
944 ipp->current = NULL;
945 ipp->prev = NULL;
946
947 return (NULL);
948 }
949
950
951 /*
952 * 'ippLength()' - Compute the length of an IPP message.
953 */
954
955 size_t /* O - Size of IPP message */
956 ippLength(ipp_t *ipp) /* I - IPP message */
957 {
958 return (ipp_length(ipp, 0));
959 }
960
961
962 /*
963 * 'ippNew()' - Allocate a new IPP message.
964 */
965
966 ipp_t * /* O - New IPP message */
967 ippNew(void)
968 {
969 ipp_t *temp; /* New IPP message */
970
971
972 DEBUG_puts("ippNew()");
973
974 if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL)
975 {
976 /*
977 * Default to IPP 1.1...
978 */
979
980 temp->request.any.version[0] = 1;
981 temp->request.any.version[1] = 1;
982 temp->use = 1;
983 }
984
985 DEBUG_printf(("1ippNew: Returning %p", temp));
986
987 return (temp);
988 }
989
990
991 /*
992 * 'ippNewRequest()' - Allocate a new IPP request message.
993 *
994 * The new request message is initialized with the attributes-charset and
995 * attributes-natural-language attributes added. The
996 * attributes-natural-language value is derived from the current locale.
997 *
998 * @since CUPS 1.2/Mac OS X 10.5@
999 */
1000
1001 ipp_t * /* O - IPP request message */
1002 ippNewRequest(ipp_op_t op) /* I - Operation code */
1003 {
1004 ipp_t *request; /* IPP request message */
1005 cups_lang_t *language; /* Current language localization */
1006
1007
1008 DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op)));
1009
1010 /*
1011 * Create a new IPP message...
1012 */
1013
1014 if ((request = ippNew()) == NULL)
1015 return (NULL);
1016
1017 /*
1018 * Set the operation and request ID...
1019 */
1020
1021 request->request.op.operation_id = op;
1022 request->request.op.request_id = 1;
1023
1024 /*
1025 * Use UTF-8 as the character set...
1026 */
1027
1028 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1029 "attributes-charset", NULL, "utf-8");
1030
1031 /*
1032 * Get the language from the current locale...
1033 */
1034
1035 language = cupsLangDefault();
1036
1037 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1038 "attributes-natural-language", NULL, language->language);
1039
1040 /*
1041 * Return the new request...
1042 */
1043
1044 return (request);
1045 }
1046
1047
1048 /*
1049 * 'ippRead()' - Read data for an IPP message from a HTTP connection.
1050 */
1051
1052 ipp_state_t /* O - Current state */
1053 ippRead(http_t *http, /* I - HTTP connection */
1054 ipp_t *ipp) /* I - IPP data */
1055 {
1056 DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT,
1057 http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
1058
1059 if (!http)
1060 return (IPP_ERROR);
1061
1062 DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state,
1063 http->used));
1064
1065 return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
1066 ipp));
1067 }
1068
1069
1070 /*
1071 * 'ippReadFile()' - Read data for an IPP message from a file.
1072 *
1073 * @since CUPS 1.1.19/Mac OS X 10.3@
1074 */
1075
1076 ipp_state_t /* O - Current state */
1077 ippReadFile(int fd, /* I - HTTP data */
1078 ipp_t *ipp) /* I - IPP data */
1079 {
1080 DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp));
1081
1082 return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
1083 }
1084
1085
1086 /*
1087 * 'ippReadIO()' - Read data for an IPP message.
1088 *
1089 * @since CUPS 1.2/Mac OS X 10.5@
1090 */
1091
1092 ipp_state_t /* O - Current state */
1093 ippReadIO(void *src, /* I - Data source */
1094 ipp_iocb_t cb, /* I - Read callback function */
1095 int blocking, /* I - Use blocking IO? */
1096 ipp_t *parent, /* I - Parent request, if any */
1097 ipp_t *ipp) /* I - IPP data */
1098 {
1099 int n; /* Length of data */
1100 unsigned char *buffer, /* Data buffer */
1101 string[IPP_MAX_NAME],
1102 /* Small string buffer */
1103 *bufptr; /* Pointer into buffer */
1104 ipp_attribute_t *attr; /* Current attribute */
1105 ipp_tag_t tag; /* Current tag */
1106 ipp_tag_t value_tag; /* Current value tag */
1107 ipp_value_t *value; /* Current value */
1108
1109
1110 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1111 src, cb, blocking, parent, ipp));
1112 DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state));
1113
1114 if (!src || !ipp)
1115 return (IPP_ERROR);
1116
1117 if ((buffer = ipp_buffer_get()) == NULL)
1118 {
1119 DEBUG_puts("1ippReadIO: Unable to get read buffer!");
1120 return (IPP_ERROR);
1121 }
1122
1123 switch (ipp->state)
1124 {
1125 case IPP_IDLE :
1126 ipp->state ++; /* Avoid common problem... */
1127
1128 case IPP_HEADER :
1129 if (parent == NULL)
1130 {
1131 /*
1132 * Get the request header...
1133 */
1134
1135 if ((*cb)(src, buffer, 8) < 8)
1136 {
1137 DEBUG_puts("1ippReadIO: Unable to read header!");
1138 ipp_buffer_release(buffer);
1139 return (IPP_ERROR);
1140 }
1141
1142 /*
1143 * Then copy the request header over...
1144 */
1145
1146 ipp->request.any.version[0] = buffer[0];
1147 ipp->request.any.version[1] = buffer[1];
1148 ipp->request.any.op_status = (buffer[2] << 8) | buffer[3];
1149 ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) |
1150 buffer[6]) << 8) | buffer[7];
1151
1152 DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1]));
1153 DEBUG_printf(("2ippReadIO: op_status=%04x",
1154 ipp->request.any.op_status));
1155 DEBUG_printf(("2ippReadIO: request_id=%d",
1156 ipp->request.any.request_id));
1157 }
1158
1159 ipp->state = IPP_ATTRIBUTE;
1160 ipp->current = NULL;
1161 ipp->curtag = IPP_TAG_ZERO;
1162 ipp->prev = ipp->last;
1163
1164 /*
1165 * If blocking is disabled, stop here...
1166 */
1167
1168 if (!blocking)
1169 break;
1170
1171 case IPP_ATTRIBUTE :
1172 for (;;)
1173 {
1174 if ((*cb)(src, buffer, 1) < 1)
1175 {
1176 DEBUG_puts("1ippReadIO: Callback returned EOF/error");
1177 ipp_buffer_release(buffer);
1178 return (IPP_ERROR);
1179 }
1180
1181 DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
1182 ipp->current, ipp->prev));
1183
1184 /*
1185 * Read this attribute...
1186 */
1187
1188 tag = (ipp_tag_t)buffer[0];
1189
1190 if (tag == IPP_TAG_END)
1191 {
1192 /*
1193 * No more attributes left...
1194 */
1195
1196 DEBUG_puts("2ippReadIO: IPP_TAG_END!");
1197
1198 ipp->state = IPP_DATA;
1199 break;
1200 }
1201 else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
1202 {
1203 /*
1204 * Group tag... Set the current group and continue...
1205 */
1206
1207 if (ipp->curtag == tag)
1208 ipp->prev = ippAddSeparator(ipp);
1209 else if (ipp->current)
1210 ipp->prev = ipp->current;
1211
1212 ipp->curtag = tag;
1213 ipp->current = NULL;
1214 DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag,
1215 ippTagString(tag), ipp->prev));
1216 continue;
1217 }
1218
1219 DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag,
1220 ippTagString(tag)));
1221
1222 /*
1223 * Get the name...
1224 */
1225
1226 if ((*cb)(src, buffer, 2) < 2)
1227 {
1228 DEBUG_puts("1ippReadIO: unable to read name length!");
1229 ipp_buffer_release(buffer);
1230 return (IPP_ERROR);
1231 }
1232
1233 n = (buffer[0] << 8) | buffer[1];
1234
1235 if (n >= IPP_BUF_SIZE)
1236 {
1237 DEBUG_printf(("1ippReadIO: bad name length %d!", n));
1238 ipp_buffer_release(buffer);
1239 return (IPP_ERROR);
1240 }
1241
1242 DEBUG_printf(("2ippReadIO: name length=%d", n));
1243
1244 if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
1245 tag != IPP_TAG_END_COLLECTION)
1246 {
1247 /*
1248 * More values for current attribute...
1249 */
1250
1251 if (ipp->current == NULL)
1252 {
1253 DEBUG_puts("1ippReadIO: Attribute without name and no current");
1254 ipp_buffer_release(buffer);
1255 return (IPP_ERROR);
1256 }
1257
1258 attr = ipp->current;
1259 value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
1260
1261 /*
1262 * Make sure we aren't adding a new value of a different
1263 * type...
1264 */
1265
1266 if (value_tag == IPP_TAG_ZERO)
1267 {
1268 /*
1269 * Setting the value of a collection member...
1270 */
1271
1272 attr->value_tag = tag;
1273 }
1274 else if (value_tag == IPP_TAG_TEXTLANG ||
1275 value_tag == IPP_TAG_NAMELANG ||
1276 (value_tag >= IPP_TAG_TEXT &&
1277 value_tag <= IPP_TAG_MIMETYPE))
1278 {
1279 /*
1280 * String values can sometimes come across in different
1281 * forms; accept sets of differing values...
1282 */
1283
1284 if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG &&
1285 (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) &&
1286 tag != IPP_TAG_NOVALUE)
1287 {
1288 DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
1289 value_tag, ippTagString(value_tag), tag,
1290 ippTagString(tag)));
1291 ipp_buffer_release(buffer);
1292 return (IPP_ERROR);
1293 }
1294 }
1295 else if (value_tag != tag)
1296 {
1297 DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
1298 value_tag, ippTagString(value_tag), tag,
1299 ippTagString(tag)));
1300 ipp_buffer_release(buffer);
1301 return (IPP_ERROR);
1302 }
1303
1304 /*
1305 * Finally, reallocate the attribute array as needed...
1306 */
1307
1308 if (attr->num_values == 1 ||
1309 (attr->num_values > 0 &&
1310 (attr->num_values & (IPP_MAX_VALUES - 1)) == 0))
1311 {
1312 ipp_attribute_t *temp; /* Pointer to new buffer */
1313
1314
1315 DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
1316 attr->num_values + IPP_MAX_VALUES));
1317
1318 /*
1319 * Reallocate memory...
1320 */
1321
1322 if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
1323 (attr->num_values + IPP_MAX_VALUES - 1) *
1324 sizeof(ipp_value_t))) == NULL)
1325 {
1326 DEBUG_puts("1ippReadIO: Unable to resize attribute");
1327 ipp_buffer_release(buffer);
1328 return (IPP_ERROR);
1329 }
1330
1331 if (temp != attr)
1332 {
1333 /*
1334 * Reset pointers in the list...
1335 */
1336
1337 if (ipp->prev)
1338 ipp->prev->next = temp;
1339 else
1340 ipp->attrs = temp;
1341
1342 attr = ipp->current = ipp->last = temp;
1343 }
1344 }
1345 }
1346 else if (tag == IPP_TAG_MEMBERNAME)
1347 {
1348 /*
1349 * Name must be length 0!
1350 */
1351
1352 if (n)
1353 {
1354 DEBUG_puts("1ippReadIO: member name not empty!");
1355 ipp_buffer_release(buffer);
1356 return (IPP_ERROR);
1357 }
1358
1359 if (ipp->current)
1360 ipp->prev = ipp->current;
1361
1362 attr = ipp->current = _ippAddAttr(ipp, 1);
1363
1364 DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
1365 "ipp->prev=%p", ipp->current, ipp->prev));
1366
1367 attr->group_tag = ipp->curtag;
1368 attr->value_tag = IPP_TAG_ZERO;
1369 attr->num_values = 0;
1370 }
1371 else if (tag != IPP_TAG_END_COLLECTION)
1372 {
1373 /*
1374 * New attribute; read the name and add it...
1375 */
1376
1377 if ((*cb)(src, buffer, n) < n)
1378 {
1379 DEBUG_puts("1ippReadIO: unable to read name!");
1380 ipp_buffer_release(buffer);
1381 return (IPP_ERROR);
1382 }
1383
1384 buffer[n] = '\0';
1385
1386 if (ipp->current)
1387 ipp->prev = ipp->current;
1388
1389 if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
1390 {
1391 DEBUG_puts("1ippReadIO: unable to allocate attribute!");
1392 ipp_buffer_release(buffer);
1393 return (IPP_ERROR);
1394 }
1395
1396 DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
1397 "ipp->prev=%p", buffer, ipp->current, ipp->prev));
1398
1399 attr->group_tag = ipp->curtag;
1400 attr->value_tag = tag;
1401 attr->name = _cupsStrAlloc((char *)buffer);
1402 attr->num_values = 0;
1403 }
1404 else
1405 attr = NULL;
1406
1407 if (tag != IPP_TAG_END_COLLECTION)
1408 value = attr->values + attr->num_values;
1409 else
1410 value = NULL;
1411
1412 if ((*cb)(src, buffer, 2) < 2)
1413 {
1414 DEBUG_puts("1ippReadIO: unable to read value length!");
1415 ipp_buffer_release(buffer);
1416 return (IPP_ERROR);
1417 }
1418
1419 n = (buffer[0] << 8) | buffer[1];
1420 DEBUG_printf(("2ippReadIO: value length=%d", n));
1421
1422 switch (tag)
1423 {
1424 case IPP_TAG_INTEGER :
1425 case IPP_TAG_ENUM :
1426 if (n != 4)
1427 {
1428 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1429 ipp_buffer_release(buffer);
1430 return (IPP_ERROR);
1431 }
1432
1433 if ((*cb)(src, buffer, 4) < 4)
1434 {
1435 DEBUG_puts("1ippReadIO: Unable to read integer value!");
1436 ipp_buffer_release(buffer);
1437 return (IPP_ERROR);
1438 }
1439
1440 n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1441 buffer[3];
1442
1443 value->integer = n;
1444 break;
1445
1446 case IPP_TAG_BOOLEAN :
1447 if (n != 1)
1448 {
1449 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1450 ipp_buffer_release(buffer);
1451 return (IPP_ERROR);
1452 }
1453
1454 if ((*cb)(src, buffer, 1) < 1)
1455 {
1456 DEBUG_puts("1ippReadIO: Unable to read boolean value!");
1457 ipp_buffer_release(buffer);
1458 return (IPP_ERROR);
1459 }
1460
1461 value->boolean = buffer[0];
1462 break;
1463
1464 case IPP_TAG_NOVALUE :
1465 case IPP_TAG_NOTSETTABLE :
1466 case IPP_TAG_DELETEATTR :
1467 case IPP_TAG_ADMINDEFINE :
1468 /*
1469 * These value types are not supposed to have values, however
1470 * some vendors (Brother) do not implement IPP correctly and so
1471 * we need to map non-empty values to text...
1472 */
1473
1474 if (attr->value_tag == tag)
1475 {
1476 if (n == 0)
1477 break;
1478
1479 attr->value_tag = IPP_TAG_TEXT;
1480 }
1481
1482 case IPP_TAG_TEXT :
1483 case IPP_TAG_NAME :
1484 case IPP_TAG_KEYWORD :
1485 case IPP_TAG_URI :
1486 case IPP_TAG_URISCHEME :
1487 case IPP_TAG_CHARSET :
1488 case IPP_TAG_LANGUAGE :
1489 case IPP_TAG_MIMETYPE :
1490 if (n >= IPP_BUF_SIZE)
1491 {
1492 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1493 ipp_buffer_release(buffer);
1494 return (IPP_ERROR);
1495 }
1496
1497 if ((*cb)(src, buffer, n) < n)
1498 {
1499 DEBUG_puts("1ippReadIO: unable to read name!");
1500 ipp_buffer_release(buffer);
1501 return (IPP_ERROR);
1502 }
1503
1504 buffer[n] = '\0';
1505 value->string.text = _cupsStrAlloc((char *)buffer);
1506 DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text));
1507 break;
1508
1509 case IPP_TAG_DATE :
1510 if (n != 11)
1511 {
1512 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1513 ipp_buffer_release(buffer);
1514 return (IPP_ERROR);
1515 }
1516
1517 if ((*cb)(src, value->date, 11) < 11)
1518 {
1519 DEBUG_puts("1ippReadIO: Unable to read date value!");
1520 ipp_buffer_release(buffer);
1521 return (IPP_ERROR);
1522 }
1523 break;
1524
1525 case IPP_TAG_RESOLUTION :
1526 if (n != 9)
1527 {
1528 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1529 ipp_buffer_release(buffer);
1530 return (IPP_ERROR);
1531 }
1532
1533 if ((*cb)(src, buffer, 9) < 9)
1534 {
1535 DEBUG_puts("1ippReadIO: Unable to read resolution value!");
1536 ipp_buffer_release(buffer);
1537 return (IPP_ERROR);
1538 }
1539
1540 value->resolution.xres =
1541 (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1542 buffer[3];
1543 value->resolution.yres =
1544 (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
1545 buffer[7];
1546 value->resolution.units =
1547 (ipp_res_t)buffer[8];
1548 break;
1549
1550 case IPP_TAG_RANGE :
1551 if (n != 8)
1552 {
1553 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1554 ipp_buffer_release(buffer);
1555 return (IPP_ERROR);
1556 }
1557
1558 if ((*cb)(src, buffer, 8) < 8)
1559 {
1560 DEBUG_puts("1ippReadIO: Unable to read range value!");
1561 ipp_buffer_release(buffer);
1562 return (IPP_ERROR);
1563 }
1564
1565 value->range.lower =
1566 (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1567 buffer[3];
1568 value->range.upper =
1569 (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
1570 buffer[7];
1571 break;
1572
1573 case IPP_TAG_TEXTLANG :
1574 case IPP_TAG_NAMELANG :
1575 if (n >= IPP_BUF_SIZE || n < 4)
1576 {
1577 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1578 ipp_buffer_release(buffer);
1579 return (IPP_ERROR);
1580 }
1581
1582 if ((*cb)(src, buffer, n) < n)
1583 {
1584 DEBUG_puts("1ippReadIO: Unable to read string w/language "
1585 "value!");
1586 ipp_buffer_release(buffer);
1587 return (IPP_ERROR);
1588 }
1589
1590 bufptr = buffer;
1591
1592 /*
1593 * text-with-language and name-with-language are composite
1594 * values:
1595 *
1596 * charset-length
1597 * charset
1598 * text-length
1599 * text
1600 */
1601
1602 n = (bufptr[0] << 8) | bufptr[1];
1603
1604 if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) ||
1605 n >= sizeof(string))
1606 {
1607 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1608 ipp_buffer_release(buffer);
1609 return (IPP_ERROR);
1610 }
1611
1612 memcpy(string, bufptr + 2, n);
1613 string[n] = '\0';
1614
1615 value->string.charset = _cupsStrAlloc((char *)string);
1616
1617 bufptr += 2 + n;
1618 n = (bufptr[0] << 8) | bufptr[1];
1619
1620 if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
1621 {
1622 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1623 ipp_buffer_release(buffer);
1624 return (IPP_ERROR);
1625 }
1626
1627 bufptr[2 + n] = '\0';
1628 value->string.text = _cupsStrAlloc((char *)bufptr + 2);
1629 break;
1630
1631 case IPP_TAG_BEGIN_COLLECTION :
1632 /*
1633 * Oh, boy, here comes a collection value, so read it...
1634 */
1635
1636 value->collection = ippNew();
1637
1638 if (n > 0)
1639 {
1640 DEBUG_puts("1ippReadIO: begCollection tag with value length "
1641 "> 0!");
1642 ipp_buffer_release(buffer);
1643 return (IPP_ERROR);
1644 }
1645
1646 if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
1647 {
1648 DEBUG_puts("1ippReadIO: Unable to read collection value!");
1649 ipp_buffer_release(buffer);
1650 return (IPP_ERROR);
1651 }
1652 break;
1653
1654 case IPP_TAG_END_COLLECTION :
1655 ipp_buffer_release(buffer);
1656
1657 if (n > 0)
1658 {
1659 DEBUG_puts("1ippReadIO: endCollection tag with value length "
1660 "> 0!");
1661 return (IPP_ERROR);
1662 }
1663
1664 DEBUG_puts("1ippReadIO: endCollection tag...");
1665 return (ipp->state = IPP_DATA);
1666
1667 case IPP_TAG_MEMBERNAME :
1668 /*
1669 * The value the name of the member in the collection, which
1670 * we need to carry over...
1671 */
1672
1673 if (n >= IPP_BUF_SIZE)
1674 {
1675 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1676 ipp_buffer_release(buffer);
1677 return (IPP_ERROR);
1678 }
1679
1680 if ((*cb)(src, buffer, n) < n)
1681 {
1682 DEBUG_puts("1ippReadIO: Unable to read member name value!");
1683 ipp_buffer_release(buffer);
1684 return (IPP_ERROR);
1685 }
1686
1687 buffer[n] = '\0';
1688 attr->name = _cupsStrAlloc((char *)buffer);
1689
1690 /*
1691 * Since collection members are encoded differently than
1692 * regular attributes, make sure we don't start with an
1693 * empty value...
1694 */
1695
1696 attr->num_values --;
1697
1698 DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name));
1699 break;
1700
1701 default : /* Other unsupported values */
1702 if (n > IPP_MAX_LENGTH)
1703 {
1704 DEBUG_printf(("1ippReadIO: bad value length %d!", n));
1705 ipp_buffer_release(buffer);
1706 return (IPP_ERROR);
1707 }
1708
1709 if (!value)
1710 {
1711 DEBUG_puts("1ippReadIO: NULL value!");
1712 ipp_buffer_release(buffer);
1713 return (IPP_ERROR);
1714 }
1715
1716 value->unknown.length = n;
1717 if (n > 0)
1718 {
1719 if ((value->unknown.data = malloc(n)) == NULL)
1720 {
1721 DEBUG_puts("1ippReadIO: Unable to allocate value");
1722 ipp_buffer_release(buffer);
1723 return (IPP_ERROR);
1724 }
1725
1726 if ((*cb)(src, value->unknown.data, n) < n)
1727 {
1728 DEBUG_puts("1ippReadIO: Unable to read unsupported value!");
1729 ipp_buffer_release(buffer);
1730 return (IPP_ERROR);
1731 }
1732 }
1733 else
1734 value->unknown.data = NULL;
1735 break;
1736 }
1737
1738 attr->num_values ++;
1739
1740 /*
1741 * If blocking is disabled, stop here...
1742 */
1743
1744 if (!blocking)
1745 break;
1746 }
1747 break;
1748
1749 case IPP_DATA :
1750 break;
1751
1752 default :
1753 break; /* anti-compiler-warning-code */
1754 }
1755
1756 DEBUG_printf(("1ippReadIO: returning ipp->state=%d!", ipp->state));
1757 ipp_buffer_release(buffer);
1758
1759 return (ipp->state);
1760 }
1761
1762
1763 /*
1764 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1765 */
1766
1767 const ipp_uchar_t * /* O - RFC-1903 date/time data */
1768 ippTimeToDate(time_t t) /* I - UNIX time value */
1769 {
1770 struct tm *unixdate; /* UNIX unixdate/time info */
1771 ipp_uchar_t *date = _cupsGlobals()->ipp_date;
1772 /* RFC-1903 date/time data */
1773
1774
1775 /*
1776 * RFC-1903 date/time format is:
1777 *
1778 * Byte(s) Description
1779 * ------- -----------
1780 * 0-1 Year (0 to 65535)
1781 * 2 Month (1 to 12)
1782 * 3 Day (1 to 31)
1783 * 4 Hours (0 to 23)
1784 * 5 Minutes (0 to 59)
1785 * 6 Seconds (0 to 60, 60 = "leap second")
1786 * 7 Deciseconds (0 to 9)
1787 * 8 +/- UTC
1788 * 9 UTC hours (0 to 11)
1789 * 10 UTC minutes (0 to 59)
1790 */
1791
1792 unixdate = gmtime(&t);
1793 unixdate->tm_year += 1900;
1794
1795 date[0] = unixdate->tm_year >> 8;
1796 date[1] = unixdate->tm_year;
1797 date[2] = unixdate->tm_mon + 1;
1798 date[3] = unixdate->tm_mday;
1799 date[4] = unixdate->tm_hour;
1800 date[5] = unixdate->tm_min;
1801 date[6] = unixdate->tm_sec;
1802 date[7] = 0;
1803 date[8] = '+';
1804 date[9] = 0;
1805 date[10] = 0;
1806
1807 return (date);
1808 }
1809
1810
1811 /*
1812 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1813 */
1814
1815 ipp_state_t /* O - Current state */
1816 ippWrite(http_t *http, /* I - HTTP connection */
1817 ipp_t *ipp) /* I - IPP data */
1818 {
1819 DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http, ipp));
1820
1821 if (!http)
1822 return (IPP_ERROR);
1823
1824 return (ippWriteIO(http, (ipp_iocb_t)httpWrite2, http->blocking, NULL, ipp));
1825 }
1826
1827
1828 /*
1829 * 'ippWriteFile()' - Write data for an IPP message to a file.
1830 *
1831 * @since CUPS 1.1.19/Mac OS X 10.3@
1832 */
1833
1834 ipp_state_t /* O - Current state */
1835 ippWriteFile(int fd, /* I - HTTP data */
1836 ipp_t *ipp) /* I - IPP data */
1837 {
1838 DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd, ipp));
1839
1840 ipp->state = IPP_IDLE;
1841
1842 return (ippWriteIO(&fd, (ipp_iocb_t)ipp_write_file, 1, NULL, ipp));
1843 }
1844
1845
1846 /*
1847 * 'ippWriteIO()' - Write data for an IPP message.
1848 *
1849 * @since CUPS 1.2/Mac OS X 10.5@
1850 */
1851
1852 ipp_state_t /* O - Current state */
1853 ippWriteIO(void *dst, /* I - Destination */
1854 ipp_iocb_t cb, /* I - Write callback function */
1855 int blocking, /* I - Use blocking IO? */
1856 ipp_t *parent, /* I - Parent IPP message */
1857 ipp_t *ipp) /* I - IPP data */
1858 {
1859 int i; /* Looping var */
1860 int n; /* Length of data */
1861 unsigned char *buffer, /* Data buffer */
1862 *bufptr; /* Pointer into buffer */
1863 ipp_attribute_t *attr; /* Current attribute */
1864 ipp_value_t *value; /* Current value */
1865
1866
1867 DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
1868 dst, cb, blocking, parent, ipp));
1869
1870 if (!dst || !ipp)
1871 return (IPP_ERROR);
1872
1873 if ((buffer = ipp_buffer_get()) == NULL)
1874 {
1875 DEBUG_puts("1ippWriteIO: Unable to get write buffer");
1876 return (IPP_ERROR);
1877 }
1878
1879 switch (ipp->state)
1880 {
1881 case IPP_IDLE :
1882 ipp->state ++; /* Avoid common problem... */
1883
1884 case IPP_HEADER :
1885 if (parent == NULL)
1886 {
1887 /*
1888 * Send the request header:
1889 *
1890 * Version = 2 bytes
1891 * Operation/Status Code = 2 bytes
1892 * Request ID = 4 bytes
1893 * Total = 8 bytes
1894 */
1895
1896 bufptr = buffer;
1897
1898 *bufptr++ = ipp->request.any.version[0];
1899 *bufptr++ = ipp->request.any.version[1];
1900 *bufptr++ = ipp->request.any.op_status >> 8;
1901 *bufptr++ = ipp->request.any.op_status;
1902 *bufptr++ = ipp->request.any.request_id >> 24;
1903 *bufptr++ = ipp->request.any.request_id >> 16;
1904 *bufptr++ = ipp->request.any.request_id >> 8;
1905 *bufptr++ = ipp->request.any.request_id;
1906
1907 DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer[0], buffer[1]));
1908 DEBUG_printf(("2ippWriteIO: op_status=%04x",
1909 ipp->request.any.op_status));
1910 DEBUG_printf(("2ippWriteIO: request_id=%d",
1911 ipp->request.any.request_id));
1912
1913 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
1914 {
1915 DEBUG_puts("1ippWriteIO: Could not write IPP header...");
1916 ipp_buffer_release(buffer);
1917 return (IPP_ERROR);
1918 }
1919 }
1920
1921 /*
1922 * Reset the state engine to point to the first attribute
1923 * in the request/response, with no current group.
1924 */
1925
1926 ipp->state = IPP_ATTRIBUTE;
1927 ipp->current = ipp->attrs;
1928 ipp->curtag = IPP_TAG_ZERO;
1929
1930 DEBUG_printf(("1ippWriteIO: ipp->current=%p", ipp->current));
1931
1932 /*
1933 * If blocking is disabled, stop here...
1934 */
1935
1936 if (!blocking)
1937 break;
1938
1939 case IPP_ATTRIBUTE :
1940 while (ipp->current != NULL)
1941 {
1942 /*
1943 * Write this attribute...
1944 */
1945
1946 bufptr = buffer;
1947 attr = ipp->current;
1948
1949 ipp->current = ipp->current->next;
1950
1951 if (!parent)
1952 {
1953 if (ipp->curtag != attr->group_tag)
1954 {
1955 /*
1956 * Send a group tag byte...
1957 */
1958
1959 ipp->curtag = attr->group_tag;
1960
1961 if (attr->group_tag == IPP_TAG_ZERO)
1962 continue;
1963
1964 DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
1965 attr->group_tag, ippTagString(attr->group_tag)));
1966 *bufptr++ = attr->group_tag;
1967 }
1968 else if (attr->group_tag == IPP_TAG_ZERO)
1969 continue;
1970 }
1971
1972 DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr->name,
1973 attr->num_values > 1 ? "1setOf " : "",
1974 ippTagString(attr->value_tag)));
1975
1976 /*
1977 * Write the attribute tag and name. The current implementation
1978 * does not support the extension value tags above 0x7f, so all
1979 * value tags are 1 byte.
1980 *
1981 * The attribute name length does not include the trailing nul
1982 * character in the source string.
1983 *
1984 * Collection values (parent != NULL) are written differently...
1985 */
1986
1987 if (parent == NULL)
1988 {
1989 /*
1990 * Get the length of the attribute name, and make sure it won't
1991 * overflow the buffer...
1992 */
1993
1994 if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 4))
1995 {
1996 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
1997 ipp_buffer_release(buffer);
1998 return (IPP_ERROR);
1999 }
2000
2001 /*
2002 * Write the value tag, name length, and name string...
2003 */
2004
2005 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2006 attr->value_tag, ippTagString(attr->value_tag)));
2007 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
2008 attr->name));
2009
2010 *bufptr++ = attr->value_tag;
2011 *bufptr++ = n >> 8;
2012 *bufptr++ = n;
2013 memcpy(bufptr, attr->name, n);
2014 bufptr += n;
2015 }
2016 else
2017 {
2018 /*
2019 * Get the length of the attribute name, and make sure it won't
2020 * overflow the buffer...
2021 */
2022
2023 if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 7))
2024 {
2025 DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
2026 ipp_buffer_release(buffer);
2027 return (IPP_ERROR);
2028 }
2029
2030 /*
2031 * Write the member name tag, name length, name string, value tag,
2032 * and empty name for the collection member attribute...
2033 */
2034
2035 DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
2036 IPP_TAG_MEMBERNAME));
2037 DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
2038 attr->name));
2039 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2040 attr->value_tag, ippTagString(attr->value_tag)));
2041 DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
2042
2043 *bufptr++ = IPP_TAG_MEMBERNAME;
2044 *bufptr++ = 0;
2045 *bufptr++ = 0;
2046 *bufptr++ = n >> 8;
2047 *bufptr++ = n;
2048 memcpy(bufptr, attr->name, n);
2049 bufptr += n;
2050
2051 *bufptr++ = attr->value_tag;
2052 *bufptr++ = 0;
2053 *bufptr++ = 0;
2054 }
2055
2056 /*
2057 * Now write the attribute value(s)...
2058 */
2059
2060 switch (attr->value_tag & ~IPP_TAG_COPY)
2061 {
2062 case IPP_TAG_INTEGER :
2063 case IPP_TAG_ENUM :
2064 for (i = 0, value = attr->values;
2065 i < attr->num_values;
2066 i ++, value ++)
2067 {
2068 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 9)
2069 {
2070 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2071 {
2072 DEBUG_puts("1ippWriteIO: Could not write IPP "
2073 "attribute...");
2074 ipp_buffer_release(buffer);
2075 return (IPP_ERROR);
2076 }
2077
2078 bufptr = buffer;
2079 }
2080
2081 if (i)
2082 {
2083 /*
2084 * Arrays and sets are done by sending additional
2085 * values with a zero-length name...
2086 */
2087
2088 *bufptr++ = attr->value_tag;
2089 *bufptr++ = 0;
2090 *bufptr++ = 0;
2091 }
2092
2093 /*
2094 * Integers and enumerations are both 4-byte signed
2095 * (twos-complement) values.
2096 *
2097 * Put the 2-byte length and 4-byte value into the buffer...
2098 */
2099
2100 *bufptr++ = 0;
2101 *bufptr++ = 4;
2102 *bufptr++ = value->integer >> 24;
2103 *bufptr++ = value->integer >> 16;
2104 *bufptr++ = value->integer >> 8;
2105 *bufptr++ = value->integer;
2106 }
2107 break;
2108
2109 case IPP_TAG_BOOLEAN :
2110 for (i = 0, value = attr->values;
2111 i < attr->num_values;
2112 i ++, value ++)
2113 {
2114 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 6)
2115 {
2116 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2117 {
2118 DEBUG_puts("1ippWriteIO: Could not write IPP "
2119 "attribute...");
2120 ipp_buffer_release(buffer);
2121 return (IPP_ERROR);
2122 }
2123
2124 bufptr = buffer;
2125 }
2126
2127 if (i)
2128 {
2129 /*
2130 * Arrays and sets are done by sending additional
2131 * values with a zero-length name...
2132 */
2133
2134 *bufptr++ = attr->value_tag;
2135 *bufptr++ = 0;
2136 *bufptr++ = 0;
2137 }
2138
2139 /*
2140 * Boolean values are 1-byte; 0 = false, 1 = true.
2141 *
2142 * Put the 2-byte length and 1-byte value into the buffer...
2143 */
2144
2145 *bufptr++ = 0;
2146 *bufptr++ = 1;
2147 *bufptr++ = value->boolean;
2148 }
2149 break;
2150
2151 case IPP_TAG_TEXT :
2152 case IPP_TAG_NAME :
2153 case IPP_TAG_KEYWORD :
2154 case IPP_TAG_URI :
2155 case IPP_TAG_URISCHEME :
2156 case IPP_TAG_CHARSET :
2157 case IPP_TAG_LANGUAGE :
2158 case IPP_TAG_MIMETYPE :
2159 for (i = 0, value = attr->values;
2160 i < attr->num_values;
2161 i ++, value ++)
2162 {
2163 if (i)
2164 {
2165 /*
2166 * Arrays and sets are done by sending additional
2167 * values with a zero-length name...
2168 */
2169
2170 DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
2171 attr->value_tag,
2172 ippTagString(attr->value_tag)));
2173 DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
2174
2175 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
2176 {
2177 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2178 {
2179 DEBUG_puts("1ippWriteIO: Could not write IPP "
2180 "attribute...");
2181 ipp_buffer_release(buffer);
2182 return (IPP_ERROR);
2183 }
2184
2185 bufptr = buffer;
2186 }
2187
2188 *bufptr++ = attr->value_tag;
2189 *bufptr++ = 0;
2190 *bufptr++ = 0;
2191 }
2192
2193 if (value->string.text != NULL)
2194 n = (int)strlen(value->string.text);
2195 else
2196 n = 0;
2197
2198 if (n > (IPP_BUF_SIZE - 2))
2199 {
2200 DEBUG_printf(("1ippWriteIO: String too long (%d)", n));
2201 ipp_buffer_release(buffer);
2202 return (IPP_ERROR);
2203 }
2204
2205 DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", n,
2206 value->string.text));
2207
2208 if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
2209 {
2210 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2211 {
2212 DEBUG_puts("1ippWriteIO: Could not write IPP "
2213 "attribute...");
2214 ipp_buffer_release(buffer);
2215 return (IPP_ERROR);
2216 }
2217
2218 bufptr = buffer;
2219 }
2220
2221 /*
2222 * All simple strings consist of the 2-byte length and
2223 * character data without the trailing nul normally found
2224 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2225 * bytes since the 2-byte length is a signed (twos-complement)
2226 * value.
2227 *
2228 * Put the 2-byte length and string characters in the buffer.
2229 */
2230
2231 *bufptr++ = n >> 8;
2232 *bufptr++ = n;
2233
2234 if (n > 0)
2235 {
2236 memcpy(bufptr, value->string.text, n);
2237 bufptr += n;
2238 }
2239 }
2240 break;
2241
2242 case IPP_TAG_DATE :
2243 for (i = 0, value = attr->values;
2244 i < attr->num_values;
2245 i ++, value ++)
2246 {
2247 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 16)
2248 {
2249 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2250 {
2251 DEBUG_puts("1ippWriteIO: Could not write IPP "
2252 "attribute...");
2253 ipp_buffer_release(buffer);
2254 return (IPP_ERROR);
2255 }
2256
2257 bufptr = buffer;
2258 }
2259
2260 if (i)
2261 {
2262 /*
2263 * Arrays and sets are done by sending additional
2264 * values with a zero-length name...
2265 */
2266
2267 *bufptr++ = attr->value_tag;
2268 *bufptr++ = 0;
2269 *bufptr++ = 0;
2270 }
2271
2272 /*
2273 * Date values consist of a 2-byte length and an
2274 * 11-byte date/time structure defined by RFC 1903.
2275 *
2276 * Put the 2-byte length and 11-byte date/time
2277 * structure in the buffer.
2278 */
2279
2280 *bufptr++ = 0;
2281 *bufptr++ = 11;
2282 memcpy(bufptr, value->date, 11);
2283 bufptr += 11;
2284 }
2285 break;
2286
2287 case IPP_TAG_RESOLUTION :
2288 for (i = 0, value = attr->values;
2289 i < attr->num_values;
2290 i ++, value ++)
2291 {
2292 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 14)
2293 {
2294 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2295 {
2296 DEBUG_puts("1ippWriteIO: Could not write IPP "
2297 "attribute...");
2298 ipp_buffer_release(buffer);
2299 return (IPP_ERROR);
2300 }
2301
2302 bufptr = buffer;
2303 }
2304
2305 if (i)
2306 {
2307 /*
2308 * Arrays and sets are done by sending additional
2309 * values with a zero-length name...
2310 */
2311
2312 *bufptr++ = attr->value_tag;
2313 *bufptr++ = 0;
2314 *bufptr++ = 0;
2315 }
2316
2317 /*
2318 * Resolution values consist of a 2-byte length,
2319 * 4-byte horizontal resolution value, 4-byte vertical
2320 * resolution value, and a 1-byte units value.
2321 *
2322 * Put the 2-byte length and resolution value data
2323 * into the buffer.
2324 */
2325
2326 *bufptr++ = 0;
2327 *bufptr++ = 9;
2328 *bufptr++ = value->resolution.xres >> 24;
2329 *bufptr++ = value->resolution.xres >> 16;
2330 *bufptr++ = value->resolution.xres >> 8;
2331 *bufptr++ = value->resolution.xres;
2332 *bufptr++ = value->resolution.yres >> 24;
2333 *bufptr++ = value->resolution.yres >> 16;
2334 *bufptr++ = value->resolution.yres >> 8;
2335 *bufptr++ = value->resolution.yres;
2336 *bufptr++ = value->resolution.units;
2337 }
2338 break;
2339
2340 case IPP_TAG_RANGE :
2341 for (i = 0, value = attr->values;
2342 i < attr->num_values;
2343 i ++, value ++)
2344 {
2345 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 13)
2346 {
2347 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2348 {
2349 DEBUG_puts("1ippWriteIO: Could not write IPP "
2350 "attribute...");
2351 ipp_buffer_release(buffer);
2352 return (IPP_ERROR);
2353 }
2354
2355 bufptr = buffer;
2356 }
2357
2358 if (i)
2359 {
2360 /*
2361 * Arrays and sets are done by sending additional
2362 * values with a zero-length name...
2363 */
2364
2365 *bufptr++ = attr->value_tag;
2366 *bufptr++ = 0;
2367 *bufptr++ = 0;
2368 }
2369
2370 /*
2371 * Range values consist of a 2-byte length,
2372 * 4-byte lower value, and 4-byte upper value.
2373 *
2374 * Put the 2-byte length and range value data
2375 * into the buffer.
2376 */
2377
2378 *bufptr++ = 0;
2379 *bufptr++ = 8;
2380 *bufptr++ = value->range.lower >> 24;
2381 *bufptr++ = value->range.lower >> 16;
2382 *bufptr++ = value->range.lower >> 8;
2383 *bufptr++ = value->range.lower;
2384 *bufptr++ = value->range.upper >> 24;
2385 *bufptr++ = value->range.upper >> 16;
2386 *bufptr++ = value->range.upper >> 8;
2387 *bufptr++ = value->range.upper;
2388 }
2389 break;
2390
2391 case IPP_TAG_TEXTLANG :
2392 case IPP_TAG_NAMELANG :
2393 for (i = 0, value = attr->values;
2394 i < attr->num_values;
2395 i ++, value ++)
2396 {
2397 if (i)
2398 {
2399 /*
2400 * Arrays and sets are done by sending additional
2401 * values with a zero-length name...
2402 */
2403
2404 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
2405 {
2406 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2407 {
2408 DEBUG_puts("1ippWriteIO: Could not write IPP "
2409 "attribute...");
2410 ipp_buffer_release(buffer);
2411 return (IPP_ERROR);
2412 }
2413
2414 bufptr = buffer;
2415 }
2416
2417 *bufptr++ = attr->value_tag;
2418 *bufptr++ = 0;
2419 *bufptr++ = 0;
2420 }
2421
2422 /*
2423 * textWithLanguage and nameWithLanguage values consist
2424 * of a 2-byte length for both strings and their
2425 * individual lengths, a 2-byte length for the
2426 * character string, the character string without the
2427 * trailing nul, a 2-byte length for the character
2428 * set string, and the character set string without
2429 * the trailing nul.
2430 */
2431
2432 n = 4;
2433
2434 if (value->string.charset != NULL)
2435 n += (int)strlen(value->string.charset);
2436
2437 if (value->string.text != NULL)
2438 n += (int)strlen(value->string.text);
2439
2440 if (n > (IPP_BUF_SIZE - 2))
2441 {
2442 DEBUG_printf(("1ippWriteIO: text/nameWithLanguage value "
2443 "too long (%d)", n));
2444 ipp_buffer_release(buffer);
2445 return (IPP_ERROR);
2446 }
2447
2448 if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
2449 {
2450 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2451 {
2452 DEBUG_puts("1ippWriteIO: Could not write IPP "
2453 "attribute...");
2454 ipp_buffer_release(buffer);
2455 return (IPP_ERROR);
2456 }
2457
2458 bufptr = buffer;
2459 }
2460
2461 /* Length of entire value */
2462 *bufptr++ = n >> 8;
2463 *bufptr++ = n;
2464
2465 /* Length of charset */
2466 if (value->string.charset != NULL)
2467 n = (int)strlen(value->string.charset);
2468 else
2469 n = 0;
2470
2471 *bufptr++ = n >> 8;
2472 *bufptr++ = n;
2473
2474 /* Charset */
2475 if (n > 0)
2476 {
2477 memcpy(bufptr, value->string.charset, n);
2478 bufptr += n;
2479 }
2480
2481 /* Length of text */
2482 if (value->string.text != NULL)
2483 n = (int)strlen(value->string.text);
2484 else
2485 n = 0;
2486
2487 *bufptr++ = n >> 8;
2488 *bufptr++ = n;
2489
2490 /* Text */
2491 if (n > 0)
2492 {
2493 memcpy(bufptr, value->string.text, n);
2494 bufptr += n;
2495 }
2496 }
2497 break;
2498
2499 case IPP_TAG_BEGIN_COLLECTION :
2500 for (i = 0, value = attr->values;
2501 i < attr->num_values;
2502 i ++, value ++)
2503 {
2504 /*
2505 * Collections are written with the begin-collection
2506 * tag first with a value of 0 length, followed by the
2507 * attributes in the collection, then the end-collection
2508 * value...
2509 */
2510
2511 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 5)
2512 {
2513 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2514 {
2515 DEBUG_puts("1ippWriteIO: Could not write IPP "
2516 "attribute...");
2517 ipp_buffer_release(buffer);
2518 return (IPP_ERROR);
2519 }
2520
2521 bufptr = buffer;
2522 }
2523
2524 if (i)
2525 {
2526 /*
2527 * Arrays and sets are done by sending additional
2528 * values with a zero-length name...
2529 */
2530
2531 *bufptr++ = attr->value_tag;
2532 *bufptr++ = 0;
2533 *bufptr++ = 0;
2534 }
2535
2536 /*
2537 * Write a data length of 0 and flush the buffer...
2538 */
2539
2540 *bufptr++ = 0;
2541 *bufptr++ = 0;
2542
2543 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2544 {
2545 DEBUG_puts("1ippWriteIO: Could not write IPP "
2546 "attribute...");
2547 ipp_buffer_release(buffer);
2548 return (IPP_ERROR);
2549 }
2550
2551 bufptr = buffer;
2552
2553 /*
2554 * Then write the collection attribute...
2555 */
2556
2557 value->collection->state = IPP_IDLE;
2558
2559 if (ippWriteIO(dst, cb, 1, ipp,
2560 value->collection) == IPP_ERROR)
2561 {
2562 DEBUG_puts("1ippWriteIO: Unable to write collection value");
2563 ipp_buffer_release(buffer);
2564 return (IPP_ERROR);
2565 }
2566 }
2567 break;
2568
2569 default :
2570 for (i = 0, value = attr->values;
2571 i < attr->num_values;
2572 i ++, value ++)
2573 {
2574 if (i)
2575 {
2576 /*
2577 * Arrays and sets are done by sending additional
2578 * values with a zero-length name...
2579 */
2580
2581 if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
2582 {
2583 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2584 {
2585 DEBUG_puts("1ippWriteIO: Could not write IPP "
2586 "attribute...");
2587 ipp_buffer_release(buffer);
2588 return (IPP_ERROR);
2589 }
2590
2591 bufptr = buffer;
2592 }
2593
2594 *bufptr++ = attr->value_tag;
2595 *bufptr++ = 0;
2596 *bufptr++ = 0;
2597 }
2598
2599 /*
2600 * An unknown value might some new value that a
2601 * vendor has come up with. It consists of a
2602 * 2-byte length and the bytes in the unknown
2603 * value buffer.
2604 */
2605
2606 n = value->unknown.length;
2607
2608 if (n > (IPP_BUF_SIZE - 2))
2609 {
2610 DEBUG_printf(("1ippWriteIO: Data length too long (%d)",
2611 n));
2612 ipp_buffer_release(buffer);
2613 return (IPP_ERROR);
2614 }
2615
2616 if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
2617 {
2618 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2619 {
2620 DEBUG_puts("1ippWriteIO: Could not write IPP "
2621 "attribute...");
2622 ipp_buffer_release(buffer);
2623 return (IPP_ERROR);
2624 }
2625
2626 bufptr = buffer;
2627 }
2628
2629 /* Length of unknown value */
2630 *bufptr++ = n >> 8;
2631 *bufptr++ = n;
2632
2633 /* Value */
2634 if (n > 0)
2635 {
2636 memcpy(bufptr, value->unknown.data, n);
2637 bufptr += n;
2638 }
2639 }
2640 break;
2641 }
2642
2643 /*
2644 * Write the data out...
2645 */
2646
2647 if (bufptr > buffer)
2648 {
2649 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2650 {
2651 DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
2652 ipp_buffer_release(buffer);
2653 return (IPP_ERROR);
2654 }
2655
2656 DEBUG_printf(("2ippWriteIO: wrote %d bytes",
2657 (int)(bufptr - buffer)));
2658 }
2659
2660 /*
2661 * If blocking is disabled, stop here...
2662 */
2663
2664 if (!blocking)
2665 break;
2666 }
2667
2668 if (ipp->current == NULL)
2669 {
2670 /*
2671 * Done with all of the attributes; add the end-of-attributes
2672 * tag or end-collection attribute...
2673 */
2674
2675 if (parent == NULL)
2676 {
2677 buffer[0] = IPP_TAG_END;
2678 n = 1;
2679 }
2680 else
2681 {
2682 buffer[0] = IPP_TAG_END_COLLECTION;
2683 buffer[1] = 0; /* empty name */
2684 buffer[2] = 0;
2685 buffer[3] = 0; /* empty value */
2686 buffer[4] = 0;
2687 n = 5;
2688 }
2689
2690 if ((*cb)(dst, buffer, n) < 0)
2691 {
2692 DEBUG_puts("1ippWriteIO: Could not write IPP end-tag...");
2693 ipp_buffer_release(buffer);
2694 return (IPP_ERROR);
2695 }
2696
2697 ipp->state = IPP_DATA;
2698 }
2699 break;
2700
2701 case IPP_DATA :
2702 break;
2703
2704 default :
2705 break; /* anti-compiler-warning-code */
2706 }
2707
2708 ipp_buffer_release(buffer);
2709
2710 return (ipp->state);
2711 }
2712
2713
2714 /*
2715 * '_ippAddAttr()' - Add a new attribute to the request.
2716 */
2717
2718 ipp_attribute_t * /* O - New attribute */
2719 _ippAddAttr(ipp_t *ipp, /* I - IPP message */
2720 int num_values) /* I - Number of values */
2721 {
2722 ipp_attribute_t *attr; /* New attribute */
2723
2724
2725 DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp, num_values));
2726
2727 if (!ipp || num_values < 0)
2728 return (NULL);
2729
2730 attr = calloc(sizeof(ipp_attribute_t) +
2731 (num_values - 1) * sizeof(ipp_value_t), 1);
2732
2733 if (attr != NULL)
2734 {
2735 attr->num_values = num_values;
2736
2737 if (ipp->last == NULL)
2738 ipp->attrs = attr;
2739 else
2740 ipp->last->next = attr;
2741
2742 ipp->last = attr;
2743 }
2744
2745 DEBUG_printf(("5_ippAddAttr: Returning %p", attr));
2746
2747 return (attr);
2748 }
2749
2750
2751 /*
2752 * '_ippFreeAttr()' - Free an attribute.
2753 */
2754
2755 void
2756 _ippFreeAttr(ipp_attribute_t *attr) /* I - Attribute to free */
2757 {
2758 int i; /* Looping var */
2759 ipp_value_t *value; /* Current value */
2760
2761
2762 DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr));
2763
2764 switch (attr->value_tag)
2765 {
2766 case IPP_TAG_TEXT :
2767 case IPP_TAG_NAME :
2768 case IPP_TAG_RESERVED_STRING :
2769 case IPP_TAG_KEYWORD :
2770 case IPP_TAG_URI :
2771 case IPP_TAG_URISCHEME :
2772 case IPP_TAG_CHARSET :
2773 case IPP_TAG_LANGUAGE :
2774 case IPP_TAG_MIMETYPE :
2775 for (i = 0, value = attr->values;
2776 i < attr->num_values;
2777 i ++, value ++)
2778 _cupsStrFree(value->string.text);
2779 break;
2780
2781 case IPP_TAG_TEXTLANG :
2782 case IPP_TAG_NAMELANG :
2783 for (i = 0, value = attr->values;
2784 i < attr->num_values;
2785 i ++, value ++)
2786 {
2787 if (value->string.charset && i == 0)
2788 _cupsStrFree(value->string.charset);
2789 _cupsStrFree(value->string.text);
2790 }
2791 break;
2792
2793 case IPP_TAG_INTEGER :
2794 case IPP_TAG_ENUM :
2795 case IPP_TAG_BOOLEAN :
2796 case IPP_TAG_DATE :
2797 case IPP_TAG_RESOLUTION :
2798 case IPP_TAG_RANGE :
2799 break;
2800
2801 case IPP_TAG_BEGIN_COLLECTION :
2802 for (i = 0, value = attr->values;
2803 i < attr->num_values;
2804 i ++, value ++)
2805 ippDelete(value->collection);
2806 break;
2807
2808 case IPP_TAG_STRING :
2809 for (i = 0, value = attr->values;
2810 i < attr->num_values;
2811 i ++, value ++)
2812 free(value->unknown.data);
2813 break;
2814
2815 default :
2816 if (!((int)attr->value_tag & IPP_TAG_COPY))
2817 {
2818 for (i = 0, value = attr->values;
2819 i < attr->num_values;
2820 i ++, value ++)
2821 if (value->unknown.data)
2822 free(value->unknown.data);
2823 }
2824 break;
2825 }
2826
2827 if (attr->name)
2828 _cupsStrFree(attr->name);
2829
2830 free(attr);
2831 }
2832
2833
2834 /*
2835 * 'ipp_buffer_get()' - Get a read/write buffer.
2836 */
2837
2838 static unsigned char * /* O - Buffer */
2839 ipp_buffer_get(void)
2840 {
2841 _ipp_buffer_t *buffer; /* Current buffer */
2842 _cups_globals_t *cg = _cupsGlobals();
2843 /* Global data */
2844
2845
2846 for (buffer = cg->ipp_buffers; buffer; buffer = buffer->next)
2847 if (!buffer->used)
2848 {
2849 buffer->used = 1;
2850 return (buffer->d);
2851 }
2852
2853 if ((buffer = malloc(sizeof(_ipp_buffer_t))) == NULL)
2854 return (NULL);
2855
2856 buffer->used = 1;
2857 buffer->next = cg->ipp_buffers;
2858 cg->ipp_buffers = buffer;
2859
2860 return (buffer->d);
2861 }
2862
2863
2864 /*
2865 * 'ipp_buffer_release()' - Release a read/write buffer.
2866 */
2867
2868 static void
2869 ipp_buffer_release(unsigned char *b) /* I - Buffer to release */
2870 {
2871 ((_ipp_buffer_t *)b)->used = 0;
2872 }
2873
2874
2875 /*
2876 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2877 */
2878
2879 static size_t /* O - Size of IPP message */
2880 ipp_length(ipp_t *ipp, /* I - IPP message or collection */
2881 int collection) /* I - 1 if a collection, 0 otherwise */
2882 {
2883 int i; /* Looping var */
2884 int bytes; /* Number of bytes */
2885 ipp_attribute_t *attr; /* Current attribute */
2886 ipp_tag_t group; /* Current group */
2887 ipp_value_t *value; /* Current value */
2888
2889
2890 if (ipp == NULL)
2891 return (0);
2892
2893 /*
2894 * Start with 8 bytes for the IPP message header...
2895 */
2896
2897 bytes = collection ? 0 : 8;
2898
2899 /*
2900 * Then add the lengths of each attribute...
2901 */
2902
2903 group = IPP_TAG_ZERO;
2904
2905 for (attr = ipp->attrs; attr != NULL; attr = attr->next)
2906 {
2907 if (attr->group_tag != group && !collection)
2908 {
2909 group = attr->group_tag;
2910 if (group == IPP_TAG_ZERO)
2911 continue;
2912
2913 bytes ++; /* Group tag */
2914 }
2915
2916 if (!attr->name)
2917 continue;
2918
2919 DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2920 "bytes=%d", attr->name, attr->num_values, bytes));
2921
2922 bytes += (int)strlen(attr->name); /* Name */
2923 bytes += attr->num_values; /* Value tag for each value */
2924 bytes += 2 * attr->num_values; /* Name lengths */
2925 bytes += 2 * attr->num_values; /* Value lengths */
2926
2927 if (collection)
2928 bytes += 5; /* Add membername overhead */
2929
2930 switch (attr->value_tag & ~IPP_TAG_COPY)
2931 {
2932 case IPP_TAG_INTEGER :
2933 case IPP_TAG_ENUM :
2934 bytes += 4 * attr->num_values;
2935 break;
2936
2937 case IPP_TAG_BOOLEAN :
2938 bytes += attr->num_values;
2939 break;
2940
2941 case IPP_TAG_TEXT :
2942 case IPP_TAG_NAME :
2943 case IPP_TAG_KEYWORD :
2944 case IPP_TAG_URI :
2945 case IPP_TAG_URISCHEME :
2946 case IPP_TAG_CHARSET :
2947 case IPP_TAG_LANGUAGE :
2948 case IPP_TAG_MIMETYPE :
2949 for (i = 0, value = attr->values;
2950 i < attr->num_values;
2951 i ++, value ++)
2952 if (value->string.text != NULL)
2953 bytes += (int)strlen(value->string.text);
2954 break;
2955
2956 case IPP_TAG_DATE :
2957 bytes += 11 * attr->num_values;
2958 break;
2959
2960 case IPP_TAG_RESOLUTION :
2961 bytes += 9 * attr->num_values;
2962 break;
2963
2964 case IPP_TAG_RANGE :
2965 bytes += 8 * attr->num_values;
2966 break;
2967
2968 case IPP_TAG_TEXTLANG :
2969 case IPP_TAG_NAMELANG :
2970 bytes += 4 * attr->num_values;/* Charset + text length */
2971
2972 for (i = 0, value = attr->values;
2973 i < attr->num_values;
2974 i ++, value ++)
2975 {
2976 if (value->string.charset != NULL)
2977 bytes += (int)strlen(value->string.charset);
2978
2979 if (value->string.text != NULL)
2980 bytes += (int)strlen(value->string.text);
2981 }
2982 break;
2983
2984 case IPP_TAG_BEGIN_COLLECTION :
2985 for (i = 0, value = attr->values;
2986 i < attr->num_values;
2987 i ++, value ++)
2988 bytes += (int)ipp_length(value->collection, 1);
2989 break;
2990
2991 default :
2992 for (i = 0, value = attr->values;
2993 i < attr->num_values;
2994 i ++, value ++)
2995 bytes += value->unknown.length;
2996 break;
2997 }
2998 }
2999
3000 /*
3001 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
3002 * for the "end of collection" tag and return...
3003 */
3004
3005 if (collection)
3006 bytes += 5;
3007 else
3008 bytes ++;
3009
3010 DEBUG_printf(("8ipp_length: Returning %d bytes", bytes));
3011
3012 return (bytes);
3013 }
3014
3015
3016 /*
3017 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
3018 */
3019
3020 static ssize_t /* O - Number of bytes read */
3021 ipp_read_http(http_t *http, /* I - Client connection */
3022 ipp_uchar_t *buffer, /* O - Buffer for data */
3023 size_t length) /* I - Total length */
3024 {
3025 int tbytes, /* Total bytes read */
3026 bytes; /* Bytes read this pass */
3027 char len[32]; /* Length string */
3028
3029
3030 DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
3031 http, buffer, (int)length));
3032
3033 /*
3034 * Loop until all bytes are read...
3035 */
3036
3037 for (tbytes = 0, bytes = 0;
3038 tbytes < (int)length;
3039 tbytes += bytes, buffer += bytes)
3040 {
3041 DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes,
3042 http->state));
3043
3044 if (http->state == HTTP_WAITING)
3045 break;
3046
3047 if (http->used > 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
3048 {
3049 /*
3050 * Do "fast read" from HTTP buffer directly...
3051 */
3052
3053 if (http->used > (int)(length - tbytes))
3054 bytes = (int)(length - tbytes);
3055 else
3056 bytes = http->used;
3057
3058 if (bytes == 1)
3059 buffer[0] = http->buffer[0];
3060 else
3061 memcpy(buffer, http->buffer, bytes);
3062
3063 http->used -= bytes;
3064 http->data_remaining -= bytes;
3065
3066 if (http->data_remaining <= INT_MAX)
3067 http->_data_remaining = (int)http->data_remaining;
3068 else
3069 http->_data_remaining = INT_MAX;
3070
3071 if (http->used > 0)
3072 memmove(http->buffer, http->buffer + bytes, http->used);
3073
3074 if (http->data_remaining == 0)
3075 {
3076 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
3077 {
3078 /*
3079 * Get the trailing CR LF after the chunk...
3080 */
3081
3082 if (!httpGets(len, sizeof(len), http))
3083 return (-1);
3084 }
3085
3086 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
3087 {
3088 if (http->state == HTTP_POST_RECV)
3089 http->state ++;
3090 else
3091 http->state = HTTP_WAITING;
3092 }
3093 }
3094 }
3095 else
3096 {
3097 /*
3098 * Wait a maximum of 1 second for data...
3099 */
3100
3101 if (!http->blocking)
3102 {
3103 /*
3104 * Wait up to 10 seconds for more data on non-blocking sockets...
3105 */
3106
3107 if (!httpWait(http, 10000))
3108 {
3109 /*
3110 * Signal no data...
3111 */
3112
3113 bytes = -1;
3114 break;
3115 }
3116 }
3117
3118 if ((bytes = httpRead2(http, (char *)buffer, length - tbytes)) < 0)
3119 {
3120 #ifdef WIN32
3121 break;
3122 #else
3123 if (errno != EAGAIN && errno != EINTR)
3124 break;
3125
3126 bytes = 0;
3127 #endif /* WIN32 */
3128 }
3129 else if (bytes == 0)
3130 break;
3131 }
3132 }
3133
3134 /*
3135 * Return the number of bytes read...
3136 */
3137
3138 if (tbytes == 0 && bytes < 0)
3139 tbytes = -1;
3140
3141 DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes));
3142
3143 return (tbytes);
3144 }
3145
3146
3147 /*
3148 * 'ipp_read_file()' - Read IPP data from a file.
3149 */
3150
3151 static ssize_t /* O - Number of bytes read */
3152 ipp_read_file(int *fd, /* I - File descriptor */
3153 ipp_uchar_t *buffer, /* O - Read buffer */
3154 size_t length) /* I - Number of bytes to read */
3155 {
3156 #ifdef WIN32
3157 return ((ssize_t)read(*fd, buffer, (unsigned)length));
3158 #else
3159 return (read(*fd, buffer, length));
3160 #endif /* WIN32 */
3161 }
3162
3163
3164 /*
3165 * 'ipp_write_file()' - Write IPP data to a file.
3166 */
3167
3168 static ssize_t /* O - Number of bytes written */
3169 ipp_write_file(int *fd, /* I - File descriptor */
3170 ipp_uchar_t *buffer, /* I - Data to write */
3171 size_t length) /* I - Number of bytes to write */
3172 {
3173 #ifdef WIN32
3174 return ((ssize_t)write(*fd, buffer, (unsigned)length));
3175 #else
3176 return (write(*fd, buffer, length));
3177 #endif /* WIN32 */
3178 }
3179
3180
3181 #ifdef __linux
3182 /*
3183 * The following symbol definitions are provided only for KDE
3184 * compatibility during the CUPS 1.2 testing period and will be
3185 * removed in a future release of CUPS. These are PRIVATE APIs
3186 * from CUPS 1.1.x that the KDE developers chose to use...
3187 */
3188
3189 ipp_attribute_t * /* O - New attribute */
3190 _ipp_add_attr(ipp_t *ipp, /* I - IPP message */
3191 int num_values) /* I - Number of values */
3192 {
3193 return (_ippAddAttr(ipp, num_values));
3194 }
3195
3196 void
3197 _ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */
3198 {
3199 _ippFreeAttr(attr);
3200 }
3201 #endif /* __linux */
3202
3203
3204 /*
3205 * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".
3206 */