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