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