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