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