]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp.c
Merge changes from CUPS 1.4svn-r7715.
[thirdparty/cups.git] / cups / ipp.c
1 /*
2 * "$Id: ipp.c 7463 2008-04-17 00:24:25Z 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(("ippRead: http->state=%d, http->used=%d\n", http->state,
986 http->used));
987
988 return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
989 ipp));
990 }
991
992
993 /*
994 * 'ippReadFile()' - Read data for an IPP message from a file.
995 *
996 * @since CUPS 1.1.19@
997 */
998
999 ipp_state_t /* O - Current state */
1000 ippReadFile(int fd, /* I - HTTP data */
1001 ipp_t *ipp) /* I - IPP data */
1002 {
1003 DEBUG_printf(("ippReadFile(%d, %p)\n", fd, ipp));
1004
1005 return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
1006 }
1007
1008
1009 /*
1010 * 'ippReadIO()' - Read data for an IPP message.
1011 *
1012 * @since CUPS 1.2@
1013 */
1014
1015 ipp_state_t /* O - Current state */
1016 ippReadIO(void *src, /* I - Data source */
1017 ipp_iocb_t cb, /* I - Read callback function */
1018 int blocking, /* I - Use blocking IO? */
1019 ipp_t *parent, /* I - Parent request, if any */
1020 ipp_t *ipp) /* I - IPP data */
1021 {
1022 int n; /* Length of data */
1023 unsigned char buffer[IPP_MAX_LENGTH + 1],
1024 /* Data buffer */
1025 string[IPP_MAX_NAME],
1026 /* Small string buffer */
1027 *bufptr; /* Pointer into buffer */
1028 ipp_attribute_t *attr; /* Current attribute */
1029 ipp_tag_t tag; /* Current tag */
1030 ipp_tag_t value_tag; /* Current value tag */
1031 ipp_value_t *value; /* Current value */
1032
1033
1034 DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)\n",
1035 src, cb, blocking, parent, ipp));
1036 DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp->state));
1037
1038 if (src == NULL || ipp == NULL)
1039 return (IPP_ERROR);
1040
1041 switch (ipp->state)
1042 {
1043 case IPP_IDLE :
1044 ipp->state ++; /* Avoid common problem... */
1045
1046 case IPP_HEADER :
1047 if (parent == NULL)
1048 {
1049 /*
1050 * Get the request header...
1051 */
1052
1053 if ((*cb)(src, buffer, 8) < 8)
1054 {
1055 DEBUG_puts("ippReadIO: Unable to read header!");
1056 return (IPP_ERROR);
1057 }
1058
1059 /*
1060 * Verify the major version number...
1061 */
1062
1063 if (buffer[0] != 1)
1064 {
1065 DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer[0],
1066 buffer[1]));
1067 return (IPP_ERROR);
1068 }
1069
1070 /*
1071 * Then copy the request header over...
1072 */
1073
1074 ipp->request.any.version[0] = buffer[0];
1075 ipp->request.any.version[1] = buffer[1];
1076 ipp->request.any.op_status = (buffer[2] << 8) | buffer[3];
1077 ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) |
1078 buffer[6]) << 8) | buffer[7];
1079
1080 DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer[0], buffer[1]));
1081 DEBUG_printf(("ippReadIO: op_status=%04x\n",
1082 ipp->request.any.op_status));
1083 DEBUG_printf(("ippReadIO: request_id=%d\n",
1084 ipp->request.any.request_id));
1085 }
1086
1087 ipp->state = IPP_ATTRIBUTE;
1088 ipp->current = NULL;
1089 ipp->curtag = IPP_TAG_ZERO;
1090 ipp->prev = ipp->last;
1091
1092 /*
1093 * If blocking is disabled, stop here...
1094 */
1095
1096 if (!blocking)
1097 break;
1098
1099 case IPP_ATTRIBUTE :
1100 for (;;)
1101 {
1102 if ((*cb)(src, buffer, 1) < 1)
1103 return (IPP_ERROR);
1104
1105 DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
1106 ipp->current, ipp->prev));
1107
1108 /*
1109 * Read this attribute...
1110 */
1111
1112 tag = (ipp_tag_t)buffer[0];
1113
1114 if (tag == IPP_TAG_END)
1115 {
1116 /*
1117 * No more attributes left...
1118 */
1119
1120 DEBUG_puts("ippReadIO: IPP_TAG_END!");
1121
1122 ipp->state = IPP_DATA;
1123 break;
1124 }
1125 else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
1126 {
1127 /*
1128 * Group tag... Set the current group and continue...
1129 */
1130
1131 if (ipp->curtag == tag)
1132 ipp->prev = ippAddSeparator(ipp);
1133 else if (ipp->current)
1134 ipp->prev = ipp->current;
1135
1136 ipp->curtag = tag;
1137 ipp->current = NULL;
1138 DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag,
1139 ipp->prev));
1140 continue;
1141 }
1142
1143 DEBUG_printf(("ippReadIO: value tag = %x\n", tag));
1144
1145 /*
1146 * Get the name...
1147 */
1148
1149 if ((*cb)(src, buffer, 2) < 2)
1150 {
1151 DEBUG_puts("ippReadIO: unable to read name length!");
1152 return (IPP_ERROR);
1153 }
1154
1155 n = (buffer[0] << 8) | buffer[1];
1156
1157 if (n > (sizeof(buffer) - 1))
1158 {
1159 DEBUG_printf(("ippReadIO: bad name length %d!\n", n));
1160 return (IPP_ERROR);
1161 }
1162
1163 DEBUG_printf(("ippReadIO: name length = %d\n", n));
1164
1165 if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
1166 tag != IPP_TAG_END_COLLECTION)
1167 {
1168 /*
1169 * More values for current attribute...
1170 */
1171
1172 if (ipp->current == NULL)
1173 return (IPP_ERROR);
1174
1175 attr = ipp->current;
1176 value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
1177
1178 /*
1179 * Make sure we aren't adding a new value of a different
1180 * type...
1181 */
1182
1183 if (value_tag == IPP_TAG_ZERO)
1184 {
1185 /*
1186 * Setting the value of a collection member...
1187 */
1188
1189 attr->value_tag = tag;
1190 }
1191 else if (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_TEXTLANG || tag > IPP_TAG_MIMETYPE)
1200 return (IPP_ERROR);
1201 }
1202 else if (value_tag != tag)
1203 return (IPP_ERROR);
1204
1205 /*
1206 * Finally, reallocate the attribute array as needed...
1207 */
1208
1209 if (attr->num_values == 1 ||
1210 (attr->num_values > 0 &&
1211 (attr->num_values & (IPP_MAX_VALUES - 1)) == 0))
1212 {
1213 ipp_attribute_t *temp; /* Pointer to new buffer */
1214
1215
1216 DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
1217 attr->num_values + IPP_MAX_VALUES));
1218
1219 /*
1220 * Reallocate memory...
1221 */
1222
1223 if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
1224 (attr->num_values + IPP_MAX_VALUES - 1) *
1225 sizeof(ipp_value_t))) == NULL)
1226 return (IPP_ERROR);
1227
1228 if (temp != attr)
1229 {
1230 /*
1231 * Reset pointers in the list...
1232 */
1233
1234 if (ipp->prev)
1235 ipp->prev->next = temp;
1236 else
1237 ipp->attrs = temp;
1238
1239 attr = ipp->current = ipp->last = temp;
1240 }
1241 }
1242 }
1243 else if (tag == IPP_TAG_MEMBERNAME)
1244 {
1245 /*
1246 * Name must be length 0!
1247 */
1248
1249 if (n)
1250 {
1251 DEBUG_puts("ippReadIO: member name not empty!");
1252 return (IPP_ERROR);
1253 }
1254
1255 if (ipp->current)
1256 ipp->prev = ipp->current;
1257
1258 attr = ipp->current = _ippAddAttr(ipp, 1);
1259
1260 DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
1261 ipp->current, ipp->prev));
1262
1263 attr->group_tag = ipp->curtag;
1264 attr->value_tag = IPP_TAG_ZERO;
1265 attr->num_values = 0;
1266 }
1267 else if (tag != IPP_TAG_END_COLLECTION)
1268 {
1269 /*
1270 * New attribute; read the name and add it...
1271 */
1272
1273 if ((*cb)(src, buffer, n) < n)
1274 {
1275 DEBUG_puts("ippReadIO: unable to read name!");
1276 return (IPP_ERROR);
1277 }
1278
1279 buffer[n] = '\0';
1280
1281 if (ipp->current)
1282 ipp->prev = ipp->current;
1283
1284 if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
1285 {
1286 DEBUG_puts("ippReadIO: unable to allocate attribute!");
1287 return (IPP_ERROR);
1288 }
1289
1290 DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n",
1291 buffer, ipp->current, ipp->prev));
1292
1293 attr->group_tag = ipp->curtag;
1294 attr->value_tag = tag;
1295 attr->name = _cupsStrAlloc((char *)buffer);
1296 attr->num_values = 0;
1297 }
1298 else
1299 attr = NULL;
1300
1301 if (tag != IPP_TAG_END_COLLECTION)
1302 value = attr->values + attr->num_values;
1303 else
1304 value = NULL;
1305
1306 if ((*cb)(src, buffer, 2) < 2)
1307 {
1308 DEBUG_puts("ippReadIO: unable to read value length!");
1309 return (IPP_ERROR);
1310 }
1311
1312 n = (buffer[0] << 8) | buffer[1];
1313 DEBUG_printf(("ippReadIO: value length = %d\n", n));
1314
1315 switch (tag)
1316 {
1317 case IPP_TAG_INTEGER :
1318 case IPP_TAG_ENUM :
1319 if (n != 4)
1320 {
1321 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1322 return (IPP_ERROR);
1323 }
1324
1325 if ((*cb)(src, buffer, 4) < 4)
1326 {
1327 DEBUG_puts("ippReadIO: Unable to read integer value!");
1328 return (IPP_ERROR);
1329 }
1330
1331 n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1332 buffer[3];
1333
1334 value->integer = n;
1335 break;
1336
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
1353 case IPP_TAG_TEXT :
1354 case IPP_TAG_NAME :
1355 case IPP_TAG_KEYWORD :
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
1379 case IPP_TAG_DATE :
1380 if (n != 11)
1381 {
1382 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1383 return (IPP_ERROR);
1384 }
1385
1386 if ((*cb)(src, value->date, 11) < 11)
1387 {
1388 DEBUG_puts("ippReadIO: Unable to date integer value!");
1389 return (IPP_ERROR);
1390 }
1391 break;
1392
1393 case IPP_TAG_RESOLUTION :
1394 if (n != 9)
1395 {
1396 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1397 return (IPP_ERROR);
1398 }
1399
1400 if ((*cb)(src, buffer, 9) < 9)
1401 {
1402 DEBUG_puts("ippReadIO: Unable to read resolution value!");
1403 return (IPP_ERROR);
1404 }
1405
1406 value->resolution.xres =
1407 (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1408 buffer[3];
1409 value->resolution.yres =
1410 (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
1411 buffer[7];
1412 value->resolution.units =
1413 (ipp_res_t)buffer[8];
1414 break;
1415
1416 case IPP_TAG_RANGE :
1417 if (n != 8)
1418 {
1419 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1420 return (IPP_ERROR);
1421 }
1422
1423 if ((*cb)(src, buffer, 8) < 8)
1424 {
1425 DEBUG_puts("ippReadIO: Unable to read range value!");
1426 return (IPP_ERROR);
1427 }
1428
1429 value->range.lower =
1430 (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
1431 buffer[3];
1432 value->range.upper =
1433 (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
1434 buffer[7];
1435 break;
1436
1437 case IPP_TAG_TEXTLANG :
1438 case IPP_TAG_NAMELANG :
1439 if (n >= sizeof(buffer) || n < 4)
1440 {
1441 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1442 return (IPP_ERROR);
1443 }
1444
1445 if ((*cb)(src, buffer, n) < n)
1446 {
1447 DEBUG_puts("ippReadIO: Unable to read string w/language value!");
1448 return (IPP_ERROR);
1449 }
1450
1451 bufptr = buffer;
1452
1453 /*
1454 * text-with-language and name-with-language are composite
1455 * values:
1456 *
1457 * charset-length
1458 * charset
1459 * text-length
1460 * text
1461 */
1462
1463 n = (bufptr[0] << 8) | bufptr[1];
1464
1465 if ((bufptr + 2 + n) >= (buffer + sizeof(buffer)) ||
1466 n >= sizeof(string))
1467 {
1468 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1469 return (IPP_ERROR);
1470 }
1471
1472 memcpy(string, bufptr + 2, n);
1473 string[n] = '\0';
1474
1475 value->string.charset = _cupsStrAlloc((char *)string);
1476
1477 bufptr += 2 + n;
1478 n = (bufptr[0] << 8) | bufptr[1];
1479
1480 if ((bufptr + 2 + n) >= (buffer + sizeof(buffer)))
1481 {
1482 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1483 return (IPP_ERROR);
1484 }
1485
1486 bufptr[2 + n] = '\0';
1487 value->string.text = _cupsStrAlloc((char *)bufptr + 2);
1488 break;
1489
1490 case IPP_TAG_BEGIN_COLLECTION :
1491 /*
1492 * Oh, boy, here comes a collection value, so read it...
1493 */
1494
1495 value->collection = ippNew();
1496
1497 if (n > 0)
1498 {
1499 DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
1500 return (IPP_ERROR);
1501 }
1502
1503 if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
1504 {
1505 DEBUG_puts("ippReadIO: Unable to read collection value!");
1506 return (IPP_ERROR);
1507 }
1508 break;
1509
1510 case IPP_TAG_END_COLLECTION :
1511 if (n > 0)
1512 {
1513 DEBUG_puts("ippReadIO: endCollection tag with value length > 0!");
1514 return (IPP_ERROR);
1515 }
1516
1517 DEBUG_puts("ippReadIO: endCollection tag...");
1518
1519 return (ipp->state = IPP_DATA);
1520
1521 case IPP_TAG_MEMBERNAME :
1522 /*
1523 * The value the name of the member in the collection, which
1524 * we need to carry over...
1525 */
1526
1527 if (n >= sizeof(buffer))
1528 {
1529 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1530 return (IPP_ERROR);
1531 }
1532
1533 if ((*cb)(src, buffer, n) < n)
1534 {
1535 DEBUG_puts("ippReadIO: Unable to read member name value!");
1536 return (IPP_ERROR);
1537 }
1538
1539 buffer[n] = '\0';
1540 attr->name = _cupsStrAlloc((char *)buffer);
1541
1542 /*
1543 * Since collection members are encoded differently than
1544 * regular attributes, make sure we don't start with an
1545 * empty value...
1546 */
1547
1548 attr->num_values --;
1549
1550 DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr->name));
1551 break;
1552
1553 default : /* Other unsupported values */
1554 if (n > IPP_MAX_LENGTH)
1555 {
1556 DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
1557 return (IPP_ERROR);
1558 }
1559
1560 if (!value)
1561 {
1562 DEBUG_puts("ippReadIO: NULL value!");
1563 return (IPP_ERROR);
1564 }
1565
1566 value->unknown.length = n;
1567 if (n > 0)
1568 {
1569 if ((value->unknown.data = malloc(n)) == NULL)
1570 {
1571 DEBUG_puts("ippReadIO: Unable to allocate value");
1572 return (IPP_ERROR);
1573 }
1574
1575 if ((*cb)(src, value->unknown.data, n) < n)
1576 {
1577 DEBUG_puts("ippReadIO: Unable to read unsupported value!");
1578 return (IPP_ERROR);
1579 }
1580 }
1581 else
1582 value->unknown.data = NULL;
1583 break;
1584 }
1585
1586 attr->num_values ++;
1587
1588 /*
1589 * If blocking is disabled, stop here...
1590 */
1591
1592 if (!blocking)
1593 break;
1594 }
1595 break;
1596
1597 case IPP_DATA :
1598 break;
1599
1600 default :
1601 break; /* anti-compiler-warning-code */
1602 }
1603
1604 DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp->state));
1605
1606 return (ipp->state);
1607 }
1608
1609
1610 /*
1611 * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
1612 */
1613
1614 const ipp_uchar_t * /* O - RFC-1903 date/time data */
1615 ippTimeToDate(time_t t) /* I - UNIX time value */
1616 {
1617 struct tm *unixdate; /* UNIX unixdate/time info */
1618 ipp_uchar_t *date = _cupsGlobals()->ipp_date;
1619 /* RFC-1903 date/time data */
1620
1621
1622 /*
1623 * RFC-1903 date/time format is:
1624 *
1625 * Byte(s) Description
1626 * ------- -----------
1627 * 0-1 Year (0 to 65535)
1628 * 2 Month (1 to 12)
1629 * 3 Day (1 to 31)
1630 * 4 Hours (0 to 23)
1631 * 5 Minutes (0 to 59)
1632 * 6 Seconds (0 to 60, 60 = "leap second")
1633 * 7 Deciseconds (0 to 9)
1634 * 8 +/- UTC
1635 * 9 UTC hours (0 to 11)
1636 * 10 UTC minutes (0 to 59)
1637 */
1638
1639 unixdate = gmtime(&t);
1640 unixdate->tm_year += 1900;
1641
1642 date[0] = unixdate->tm_year >> 8;
1643 date[1] = unixdate->tm_year;
1644 date[2] = unixdate->tm_mon + 1;
1645 date[3] = unixdate->tm_mday;
1646 date[4] = unixdate->tm_hour;
1647 date[5] = unixdate->tm_min;
1648 date[6] = unixdate->tm_sec;
1649 date[7] = 0;
1650 date[8] = '+';
1651 date[9] = 0;
1652 date[10] = 0;
1653
1654 return (date);
1655 }
1656
1657
1658 /*
1659 * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
1660 */
1661
1662 ipp_state_t /* O - Current state */
1663 ippWrite(http_t *http, /* I - HTTP connection */
1664 ipp_t *ipp) /* I - IPP data */
1665 {
1666 DEBUG_printf(("ippWrite(%p, %p)\n", http, ipp));
1667
1668 if (http == NULL)
1669 return (IPP_ERROR);
1670
1671 return (ippWriteIO(http, (ipp_iocb_t)httpWrite2,
1672 http->blocking, NULL, ipp));
1673 }
1674
1675
1676 /*
1677 * 'ippWriteFile()' - Write data for an IPP message to a file.
1678 *
1679 * @since CUPS 1.1.19@
1680 */
1681
1682 ipp_state_t /* O - Current state */
1683 ippWriteFile(int fd, /* I - HTTP data */
1684 ipp_t *ipp) /* I - IPP data */
1685 {
1686 DEBUG_printf(("ippWriteFile(%d, %p)\n", fd, ipp));
1687
1688 ipp->state = IPP_IDLE;
1689
1690 return (ippWriteIO(&fd, (ipp_iocb_t)ipp_write_file, 1, NULL, ipp));
1691 }
1692
1693
1694 /*
1695 * 'ippWriteIO()' - Write data for an IPP message.
1696 *
1697 * @since CUPS 1.2@
1698 */
1699
1700 ipp_state_t /* O - Current state */
1701 ippWriteIO(void *dst, /* I - Destination */
1702 ipp_iocb_t cb, /* I - Write callback function */
1703 int blocking, /* I - Use blocking IO? */
1704 ipp_t *parent, /* I - Parent IPP message */
1705 ipp_t *ipp) /* I - IPP data */
1706 {
1707 int i; /* Looping var */
1708 int n; /* Length of data */
1709 unsigned char buffer[IPP_MAX_LENGTH + 2],
1710 /* Data buffer + length bytes */
1711 *bufptr; /* Pointer into buffer */
1712 ipp_attribute_t *attr; /* Current attribute */
1713 ipp_value_t *value; /* Current value */
1714
1715
1716 DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst, cb, blocking,
1717 parent, ipp));
1718
1719 if (dst == NULL || ipp == NULL)
1720 return (IPP_ERROR);
1721
1722 switch (ipp->state)
1723 {
1724 case IPP_IDLE :
1725 ipp->state ++; /* Avoid common problem... */
1726
1727 case IPP_HEADER :
1728 if (parent == NULL)
1729 {
1730 /*
1731 * Send the request header:
1732 *
1733 * Version = 2 bytes
1734 * Operation/Status Code = 2 bytes
1735 * Request ID = 4 bytes
1736 * Total = 8 bytes
1737 */
1738
1739 bufptr = buffer;
1740
1741 *bufptr++ = ipp->request.any.version[0];
1742 *bufptr++ = ipp->request.any.version[1];
1743 *bufptr++ = ipp->request.any.op_status >> 8;
1744 *bufptr++ = ipp->request.any.op_status;
1745 *bufptr++ = ipp->request.any.request_id >> 24;
1746 *bufptr++ = ipp->request.any.request_id >> 16;
1747 *bufptr++ = ipp->request.any.request_id >> 8;
1748 *bufptr++ = ipp->request.any.request_id;
1749
1750 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
1751 {
1752 DEBUG_puts("ippWriteIO: Could not write IPP header...");
1753 return (IPP_ERROR);
1754 }
1755 }
1756
1757 /*
1758 * Reset the state engine to point to the first attribute
1759 * in the request/response, with no current group.
1760 */
1761
1762 ipp->state = IPP_ATTRIBUTE;
1763 ipp->current = ipp->attrs;
1764 ipp->curtag = IPP_TAG_ZERO;
1765
1766 DEBUG_printf(("ippWriteIO: version=%d.%d\n", buffer[0], buffer[1]));
1767 DEBUG_printf(("ippWriteIO: op_status=%04x\n", ipp->request.any.op_status));
1768 DEBUG_printf(("ippWriteIO: request_id=%d\n", ipp->request.any.request_id));
1769
1770 /*
1771 * If blocking is disabled, stop here...
1772 */
1773
1774 if (!blocking)
1775 break;
1776
1777 case IPP_ATTRIBUTE :
1778 while (ipp->current != NULL)
1779 {
1780 /*
1781 * Write this attribute...
1782 */
1783
1784 bufptr = buffer;
1785 attr = ipp->current;
1786
1787 ipp->current = ipp->current->next;
1788
1789 if (ipp->curtag != attr->group_tag && parent == NULL)
1790 {
1791 /*
1792 * Send a group tag byte...
1793 */
1794
1795 ipp->curtag = attr->group_tag;
1796
1797 if (attr->group_tag == IPP_TAG_ZERO)
1798 continue;
1799
1800 DEBUG_printf(("ippWriteIO: wrote group tag = %x\n", attr->group_tag));
1801 *bufptr++ = attr->group_tag;
1802 }
1803 else if (attr->group_tag == IPP_TAG_ZERO)
1804 continue;
1805
1806 /*
1807 * Write the attribute tag and name. The current implementation
1808 * does not support the extension value tags above 0x7f, so all
1809 * value tags are 1 byte.
1810 *
1811 * The attribute name length does not include the trailing nul
1812 * character in the source string.
1813 *
1814 * Collection values (parent != NULL) are written differently...
1815 */
1816
1817 if (parent == NULL)
1818 {
1819 /*
1820 * Get the length of the attribute name, and make sure it won't
1821 * overflow the buffer...
1822 */
1823
1824 if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 4))
1825 return (IPP_ERROR);
1826
1827 /*
1828 * Write the value tag, name length, and name string...
1829 */
1830
1831 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr->value_tag));
1832 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n, attr->name));
1833
1834 *bufptr++ = attr->value_tag;
1835 *bufptr++ = n >> 8;
1836 *bufptr++ = n;
1837 memcpy(bufptr, attr->name, n);
1838 bufptr += n;
1839 }
1840 else
1841 {
1842 /*
1843 * Get the length of the attribute name, and make sure it won't
1844 * overflow the buffer...
1845 */
1846
1847 if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 7))
1848 return (IPP_ERROR);
1849
1850 /*
1851 * Write the member name tag, name length, name string, value tag,
1852 * and empty name for the collection member attribute...
1853 */
1854
1855 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1856 IPP_TAG_MEMBERNAME));
1857 DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n, attr->name));
1858 DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr->value_tag));
1859 DEBUG_puts("ippWriteIO: writing name = 0, \'\'\n");
1860
1861 *bufptr++ = IPP_TAG_MEMBERNAME;
1862 *bufptr++ = 0;
1863 *bufptr++ = 0;
1864 *bufptr++ = n >> 8;
1865 *bufptr++ = n;
1866 memcpy(bufptr, attr->name, n);
1867 bufptr += n;
1868
1869 *bufptr++ = attr->value_tag;
1870 *bufptr++ = 0;
1871 *bufptr++ = 0;
1872 }
1873
1874 /*
1875 * Now write the attribute value(s)...
1876 */
1877
1878 switch (attr->value_tag & ~IPP_TAG_COPY)
1879 {
1880 case IPP_TAG_INTEGER :
1881 case IPP_TAG_ENUM :
1882 for (i = 0, value = attr->values;
1883 i < attr->num_values;
1884 i ++, value ++)
1885 {
1886 if ((sizeof(buffer) - (bufptr - buffer)) < 9)
1887 {
1888 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
1889 {
1890 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1891 return (IPP_ERROR);
1892 }
1893
1894 bufptr = buffer;
1895 }
1896
1897 if (i)
1898 {
1899 /*
1900 * Arrays and sets are done by sending additional
1901 * values with a zero-length name...
1902 */
1903
1904 *bufptr++ = attr->value_tag;
1905 *bufptr++ = 0;
1906 *bufptr++ = 0;
1907 }
1908
1909 /*
1910 * Integers and enumerations are both 4-byte signed
1911 * (twos-complement) values.
1912 *
1913 * Put the 2-byte length and 4-byte value into the buffer...
1914 */
1915
1916 *bufptr++ = 0;
1917 *bufptr++ = 4;
1918 *bufptr++ = value->integer >> 24;
1919 *bufptr++ = value->integer >> 16;
1920 *bufptr++ = value->integer >> 8;
1921 *bufptr++ = value->integer;
1922 }
1923 break;
1924
1925 case IPP_TAG_BOOLEAN :
1926 for (i = 0, value = attr->values;
1927 i < attr->num_values;
1928 i ++, value ++)
1929 {
1930 if ((sizeof(buffer) - (bufptr - buffer)) < 6)
1931 {
1932 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
1933 {
1934 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1935 return (IPP_ERROR);
1936 }
1937
1938 bufptr = buffer;
1939 }
1940
1941 if (i)
1942 {
1943 /*
1944 * Arrays and sets are done by sending additional
1945 * values with a zero-length name...
1946 */
1947
1948 *bufptr++ = attr->value_tag;
1949 *bufptr++ = 0;
1950 *bufptr++ = 0;
1951 }
1952
1953 /*
1954 * Boolean values are 1-byte; 0 = false, 1 = true.
1955 *
1956 * Put the 2-byte length and 1-byte value into the buffer...
1957 */
1958
1959 *bufptr++ = 0;
1960 *bufptr++ = 1;
1961 *bufptr++ = value->boolean;
1962 }
1963 break;
1964
1965 case IPP_TAG_TEXT :
1966 case IPP_TAG_NAME :
1967 case IPP_TAG_KEYWORD :
1968 case IPP_TAG_URI :
1969 case IPP_TAG_URISCHEME :
1970 case IPP_TAG_CHARSET :
1971 case IPP_TAG_LANGUAGE :
1972 case IPP_TAG_MIMETYPE :
1973 for (i = 0, value = attr->values;
1974 i < attr->num_values;
1975 i ++, value ++)
1976 {
1977 if (i)
1978 {
1979 /*
1980 * Arrays and sets are done by sending additional
1981 * values with a zero-length name...
1982 */
1983
1984 DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
1985 attr->value_tag));
1986 DEBUG_printf(("ippWriteIO: writing name = 0, \'\'\n"));
1987
1988 if ((sizeof(buffer) - (bufptr - buffer)) < 3)
1989 {
1990 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
1991 {
1992 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
1993 return (IPP_ERROR);
1994 }
1995
1996 bufptr = buffer;
1997 }
1998
1999 *bufptr++ = attr->value_tag;
2000 *bufptr++ = 0;
2001 *bufptr++ = 0;
2002 }
2003
2004 if (value->string.text != NULL)
2005 n = (int)strlen(value->string.text);
2006 else
2007 n = 0;
2008
2009 if (n > (sizeof(buffer) - 2))
2010 return (IPP_ERROR);
2011
2012 DEBUG_printf(("ippWriteIO: writing string = %d, \'%s\'\n", n,
2013 value->string.text));
2014
2015 if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
2016 {
2017 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2018 {
2019 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2020 return (IPP_ERROR);
2021 }
2022
2023 bufptr = buffer;
2024 }
2025
2026 /*
2027 * All simple strings consist of the 2-byte length and
2028 * character data without the trailing nul normally found
2029 * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
2030 * bytes since the 2-byte length is a signed (twos-complement)
2031 * value.
2032 *
2033 * Put the 2-byte length and string characters in the buffer.
2034 */
2035
2036 *bufptr++ = n >> 8;
2037 *bufptr++ = n;
2038
2039 if (n > 0)
2040 {
2041 memcpy(bufptr, value->string.text, n);
2042 bufptr += n;
2043 }
2044 }
2045 break;
2046
2047 case IPP_TAG_DATE :
2048 for (i = 0, value = attr->values;
2049 i < attr->num_values;
2050 i ++, value ++)
2051 {
2052 if ((sizeof(buffer) - (bufptr - buffer)) < 16)
2053 {
2054 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2055 {
2056 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2057 return (IPP_ERROR);
2058 }
2059
2060 bufptr = buffer;
2061 }
2062
2063 if (i)
2064 {
2065 /*
2066 * Arrays and sets are done by sending additional
2067 * values with a zero-length name...
2068 */
2069
2070 *bufptr++ = attr->value_tag;
2071 *bufptr++ = 0;
2072 *bufptr++ = 0;
2073 }
2074
2075 /*
2076 * Date values consist of a 2-byte length and an
2077 * 11-byte date/time structure defined by RFC 1903.
2078 *
2079 * Put the 2-byte length and 11-byte date/time
2080 * structure in the buffer.
2081 */
2082
2083 *bufptr++ = 0;
2084 *bufptr++ = 11;
2085 memcpy(bufptr, value->date, 11);
2086 bufptr += 11;
2087 }
2088 break;
2089
2090 case IPP_TAG_RESOLUTION :
2091 for (i = 0, value = attr->values;
2092 i < attr->num_values;
2093 i ++, value ++)
2094 {
2095 if ((sizeof(buffer) - (bufptr - buffer)) < 14)
2096 {
2097 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2098 {
2099 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2100 return (IPP_ERROR);
2101 }
2102
2103 bufptr = buffer;
2104 }
2105
2106 if (i)
2107 {
2108 /*
2109 * Arrays and sets are done by sending additional
2110 * values with a zero-length name...
2111 */
2112
2113 *bufptr++ = attr->value_tag;
2114 *bufptr++ = 0;
2115 *bufptr++ = 0;
2116 }
2117
2118 /*
2119 * Resolution values consist of a 2-byte length,
2120 * 4-byte horizontal resolution value, 4-byte vertical
2121 * resolution value, and a 1-byte units value.
2122 *
2123 * Put the 2-byte length and resolution value data
2124 * into the buffer.
2125 */
2126
2127 *bufptr++ = 0;
2128 *bufptr++ = 9;
2129 *bufptr++ = value->resolution.xres >> 24;
2130 *bufptr++ = value->resolution.xres >> 16;
2131 *bufptr++ = value->resolution.xres >> 8;
2132 *bufptr++ = value->resolution.xres;
2133 *bufptr++ = value->resolution.yres >> 24;
2134 *bufptr++ = value->resolution.yres >> 16;
2135 *bufptr++ = value->resolution.yres >> 8;
2136 *bufptr++ = value->resolution.yres;
2137 *bufptr++ = value->resolution.units;
2138 }
2139 break;
2140
2141 case IPP_TAG_RANGE :
2142 for (i = 0, value = attr->values;
2143 i < attr->num_values;
2144 i ++, value ++)
2145 {
2146 if ((sizeof(buffer) - (bufptr - buffer)) < 13)
2147 {
2148 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2149 {
2150 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2151 return (IPP_ERROR);
2152 }
2153
2154 bufptr = buffer;
2155 }
2156
2157 if (i)
2158 {
2159 /*
2160 * Arrays and sets are done by sending additional
2161 * values with a zero-length name...
2162 */
2163
2164 *bufptr++ = attr->value_tag;
2165 *bufptr++ = 0;
2166 *bufptr++ = 0;
2167 }
2168
2169 /*
2170 * Range values consist of a 2-byte length,
2171 * 4-byte lower value, and 4-byte upper value.
2172 *
2173 * Put the 2-byte length and range value data
2174 * into the buffer.
2175 */
2176
2177 *bufptr++ = 0;
2178 *bufptr++ = 8;
2179 *bufptr++ = value->range.lower >> 24;
2180 *bufptr++ = value->range.lower >> 16;
2181 *bufptr++ = value->range.lower >> 8;
2182 *bufptr++ = value->range.lower;
2183 *bufptr++ = value->range.upper >> 24;
2184 *bufptr++ = value->range.upper >> 16;
2185 *bufptr++ = value->range.upper >> 8;
2186 *bufptr++ = value->range.upper;
2187 }
2188 break;
2189
2190 case IPP_TAG_TEXTLANG :
2191 case IPP_TAG_NAMELANG :
2192 for (i = 0, value = attr->values;
2193 i < attr->num_values;
2194 i ++, value ++)
2195 {
2196 if (i)
2197 {
2198 /*
2199 * Arrays and sets are done by sending additional
2200 * values with a zero-length name...
2201 */
2202
2203 if ((sizeof(buffer) - (bufptr - buffer)) < 3)
2204 {
2205 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2206 {
2207 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2208 return (IPP_ERROR);
2209 }
2210
2211 bufptr = buffer;
2212 }
2213
2214 *bufptr++ = attr->value_tag;
2215 *bufptr++ = 0;
2216 *bufptr++ = 0;
2217 }
2218
2219 /*
2220 * textWithLanguage and nameWithLanguage values consist
2221 * of a 2-byte length for both strings and their
2222 * individual lengths, a 2-byte length for the
2223 * character string, the character string without the
2224 * trailing nul, a 2-byte length for the character
2225 * set string, and the character set string without
2226 * the trailing nul.
2227 */
2228
2229 n = 4;
2230
2231 if (value->string.charset != NULL)
2232 n += (int)strlen(value->string.charset);
2233
2234 if (value->string.text != NULL)
2235 n += (int)strlen(value->string.text);
2236
2237 if (n > (sizeof(buffer) - 2))
2238 return (IPP_ERROR);
2239
2240 if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
2241 {
2242 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2243 {
2244 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2245 return (IPP_ERROR);
2246 }
2247
2248 bufptr = buffer;
2249 }
2250
2251 /* Length of entire value */
2252 *bufptr++ = n >> 8;
2253 *bufptr++ = n;
2254
2255 /* Length of charset */
2256 if (value->string.charset != NULL)
2257 n = (int)strlen(value->string.charset);
2258 else
2259 n = 0;
2260
2261 *bufptr++ = n >> 8;
2262 *bufptr++ = n;
2263
2264 /* Charset */
2265 if (n > 0)
2266 {
2267 memcpy(bufptr, value->string.charset, n);
2268 bufptr += n;
2269 }
2270
2271 /* Length of text */
2272 if (value->string.text != NULL)
2273 n = (int)strlen(value->string.text);
2274 else
2275 n = 0;
2276
2277 *bufptr++ = n >> 8;
2278 *bufptr++ = n;
2279
2280 /* Text */
2281 if (n > 0)
2282 {
2283 memcpy(bufptr, value->string.text, n);
2284 bufptr += n;
2285 }
2286 }
2287 break;
2288
2289 case IPP_TAG_BEGIN_COLLECTION :
2290 for (i = 0, value = attr->values;
2291 i < attr->num_values;
2292 i ++, value ++)
2293 {
2294 /*
2295 * Collections are written with the begin-collection
2296 * tag first with a value of 0 length, followed by the
2297 * attributes in the collection, then the end-collection
2298 * value...
2299 */
2300
2301 if ((sizeof(buffer) - (bufptr - buffer)) < 5)
2302 {
2303 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2304 {
2305 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2306 return (IPP_ERROR);
2307 }
2308
2309 bufptr = buffer;
2310 }
2311
2312 if (i)
2313 {
2314 /*
2315 * Arrays and sets are done by sending additional
2316 * values with a zero-length name...
2317 */
2318
2319 *bufptr++ = attr->value_tag;
2320 *bufptr++ = 0;
2321 *bufptr++ = 0;
2322 }
2323
2324 /*
2325 * Write a data length of 0 and flush the buffer...
2326 */
2327
2328 *bufptr++ = 0;
2329 *bufptr++ = 0;
2330
2331 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2332 {
2333 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2334 return (IPP_ERROR);
2335 }
2336
2337 bufptr = buffer;
2338
2339 /*
2340 * Then write the collection attribute...
2341 */
2342
2343 value->collection->state = IPP_IDLE;
2344
2345 if (ippWriteIO(dst, cb, 1, ipp, value->collection) == IPP_ERROR)
2346 return (IPP_ERROR);
2347 }
2348 break;
2349
2350 default :
2351 for (i = 0, value = attr->values;
2352 i < attr->num_values;
2353 i ++, value ++)
2354 {
2355 if (i)
2356 {
2357 /*
2358 * Arrays and sets are done by sending additional
2359 * values with a zero-length name...
2360 */
2361
2362 if ((sizeof(buffer) - (bufptr - buffer)) < 3)
2363 {
2364 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2365 {
2366 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2367 return (IPP_ERROR);
2368 }
2369
2370 bufptr = buffer;
2371 }
2372
2373 *bufptr++ = attr->value_tag;
2374 *bufptr++ = 0;
2375 *bufptr++ = 0;
2376 }
2377
2378 /*
2379 * An unknown value might some new value that a
2380 * vendor has come up with. It consists of a
2381 * 2-byte length and the bytes in the unknown
2382 * value buffer.
2383 */
2384
2385 n = value->unknown.length;
2386
2387 if (n > (sizeof(buffer) - 2))
2388 return (IPP_ERROR);
2389
2390 if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
2391 {
2392 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2393 {
2394 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2395 return (IPP_ERROR);
2396 }
2397
2398 bufptr = buffer;
2399 }
2400
2401 /* Length of unknown value */
2402 *bufptr++ = n >> 8;
2403 *bufptr++ = n;
2404
2405 /* Value */
2406 if (n > 0)
2407 {
2408 memcpy(bufptr, value->unknown.data, n);
2409 bufptr += n;
2410 }
2411 }
2412 break;
2413 }
2414
2415 /*
2416 * Write the data out...
2417 */
2418
2419 if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
2420 {
2421 DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
2422 return (IPP_ERROR);
2423 }
2424
2425 DEBUG_printf(("ippWriteIO: wrote %d bytes\n",
2426 (int)(bufptr - buffer)));
2427
2428 /*
2429 * If blocking is disabled, stop here...
2430 */
2431
2432 if (!blocking)
2433 break;
2434 }
2435
2436 if (ipp->current == NULL)
2437 {
2438 /*
2439 * Done with all of the attributes; add the end-of-attributes
2440 * tag or end-collection attribute...
2441 */
2442
2443 if (parent == NULL)
2444 {
2445 buffer[0] = IPP_TAG_END;
2446 n = 1;
2447 }
2448 else
2449 {
2450 buffer[0] = IPP_TAG_END_COLLECTION;
2451 buffer[1] = 0; /* empty name */
2452 buffer[2] = 0;
2453 buffer[3] = 0; /* empty value */
2454 buffer[4] = 0;
2455 n = 5;
2456 }
2457
2458 if ((*cb)(dst, buffer, n) < 0)
2459 {
2460 DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
2461 return (IPP_ERROR);
2462 }
2463
2464 ipp->state = IPP_DATA;
2465 }
2466 break;
2467
2468 case IPP_DATA :
2469 break;
2470
2471 default :
2472 break; /* anti-compiler-warning-code */
2473 }
2474
2475 return (ipp->state);
2476 }
2477
2478
2479 /*
2480 * '_ippAddAttr()' - Add a new attribute to the request.
2481 */
2482
2483 ipp_attribute_t * /* O - New attribute */
2484 _ippAddAttr(ipp_t *ipp, /* I - IPP message */
2485 int num_values) /* I - Number of values */
2486 {
2487 ipp_attribute_t *attr; /* New attribute */
2488
2489
2490 DEBUG_printf(("_ippAddAttr(%p, %d)\n", ipp, num_values));
2491
2492 if (ipp == NULL || num_values < 0)
2493 return (NULL);
2494
2495 attr = calloc(sizeof(ipp_attribute_t) +
2496 (num_values - 1) * sizeof(ipp_value_t), 1);
2497
2498 if (attr != NULL)
2499 {
2500 attr->num_values = num_values;
2501
2502 if (ipp->last == NULL)
2503 ipp->attrs = attr;
2504 else
2505 ipp->last->next = attr;
2506
2507 ipp->last = attr;
2508 }
2509
2510 DEBUG_printf(("_ippAddAttr(): %p\n", attr));
2511
2512 return (attr);
2513 }
2514
2515
2516 /*
2517 * '_ippFreeAttr()' - Free an attribute.
2518 */
2519
2520 void
2521 _ippFreeAttr(ipp_attribute_t *attr) /* I - Attribute to free */
2522 {
2523 int i; /* Looping var */
2524 ipp_value_t *value; /* Current value */
2525
2526
2527 DEBUG_printf(("_ippFreeAttr(): %p\n", attr));
2528
2529 switch (attr->value_tag)
2530 {
2531 case IPP_TAG_TEXT :
2532 case IPP_TAG_NAME :
2533 case IPP_TAG_KEYWORD :
2534 case IPP_TAG_URI :
2535 case IPP_TAG_URISCHEME :
2536 case IPP_TAG_CHARSET :
2537 case IPP_TAG_LANGUAGE :
2538 case IPP_TAG_MIMETYPE :
2539 for (i = 0, value = attr->values;
2540 i < attr->num_values;
2541 i ++, value ++)
2542 _cupsStrFree(value->string.text);
2543 break;
2544
2545 case IPP_TAG_TEXTLANG :
2546 case IPP_TAG_NAMELANG :
2547 for (i = 0, value = attr->values;
2548 i < attr->num_values;
2549 i ++, value ++)
2550 {
2551 if (value->string.charset && i == 0)
2552 _cupsStrFree(value->string.charset);
2553 _cupsStrFree(value->string.text);
2554 }
2555 break;
2556
2557 case IPP_TAG_INTEGER :
2558 case IPP_TAG_ENUM :
2559 case IPP_TAG_BOOLEAN :
2560 case IPP_TAG_DATE :
2561 case IPP_TAG_RESOLUTION :
2562 case IPP_TAG_RANGE :
2563 break;
2564
2565 case IPP_TAG_BEGIN_COLLECTION :
2566 for (i = 0, value = attr->values;
2567 i < attr->num_values;
2568 i ++, value ++)
2569 ippDelete(value->collection);
2570 break;
2571
2572 case IPP_TAG_STRING :
2573 for (i = 0, value = attr->values;
2574 i < attr->num_values;
2575 i ++, value ++)
2576 free(value->unknown.data);
2577 break;
2578
2579 default :
2580 if (!((int)attr->value_tag & IPP_TAG_COPY))
2581 {
2582 for (i = 0, value = attr->values;
2583 i < attr->num_values;
2584 i ++, value ++)
2585 if (value->unknown.data)
2586 free(value->unknown.data);
2587 }
2588 break;
2589 }
2590
2591 if (attr->name)
2592 _cupsStrFree(attr->name);
2593
2594 free(attr);
2595 }
2596
2597
2598 /*
2599 * 'ipp_length()' - Compute the length of an IPP message or collection value.
2600 */
2601
2602 static size_t /* O - Size of IPP message */
2603 ipp_length(ipp_t *ipp, /* I - IPP message or collection */
2604 int collection) /* I - 1 if a collection, 0 otherwise */
2605 {
2606 int i; /* Looping var */
2607 int bytes; /* Number of bytes */
2608 ipp_attribute_t *attr; /* Current attribute */
2609 ipp_tag_t group; /* Current group */
2610 ipp_value_t *value; /* Current value */
2611
2612
2613 if (ipp == NULL)
2614 return (0);
2615
2616 /*
2617 * Start with 8 bytes for the IPP message header...
2618 */
2619
2620 bytes = collection ? 0 : 8;
2621
2622 /*
2623 * Then add the lengths of each attribute...
2624 */
2625
2626 group = IPP_TAG_ZERO;
2627
2628 for (attr = ipp->attrs; attr != NULL; attr = attr->next)
2629 {
2630 if (attr->group_tag != group && !collection)
2631 {
2632 group = attr->group_tag;
2633 if (group == IPP_TAG_ZERO)
2634 continue;
2635
2636 bytes ++; /* Group tag */
2637 }
2638
2639 if (!attr->name)
2640 continue;
2641
2642 DEBUG_printf(("ipp_length: attr->name=\"%s\", attr->num_values=%d, "
2643 "bytes=%d\n", attr->name, attr->num_values, bytes));
2644
2645 bytes += (int)strlen(attr->name); /* Name */
2646 bytes += attr->num_values; /* Value tag for each value */
2647 bytes += 2 * attr->num_values; /* Name lengths */
2648 bytes += 2 * attr->num_values; /* Value lengths */
2649
2650 if (collection)
2651 bytes += 5; /* Add membername overhead */
2652
2653 switch (attr->value_tag & ~IPP_TAG_COPY)
2654 {
2655 case IPP_TAG_INTEGER :
2656 case IPP_TAG_ENUM :
2657 bytes += 4 * attr->num_values;
2658 break;
2659
2660 case IPP_TAG_BOOLEAN :
2661 bytes += attr->num_values;
2662 break;
2663
2664 case IPP_TAG_TEXT :
2665 case IPP_TAG_NAME :
2666 case IPP_TAG_KEYWORD :
2667 case IPP_TAG_URI :
2668 case IPP_TAG_URISCHEME :
2669 case IPP_TAG_CHARSET :
2670 case IPP_TAG_LANGUAGE :
2671 case IPP_TAG_MIMETYPE :
2672 for (i = 0, value = attr->values;
2673 i < attr->num_values;
2674 i ++, value ++)
2675 if (value->string.text != NULL)
2676 bytes += (int)strlen(value->string.text);
2677 break;
2678
2679 case IPP_TAG_DATE :
2680 bytes += 11 * attr->num_values;
2681 break;
2682
2683 case IPP_TAG_RESOLUTION :
2684 bytes += 9 * attr->num_values;
2685 break;
2686
2687 case IPP_TAG_RANGE :
2688 bytes += 8 * attr->num_values;
2689 break;
2690
2691 case IPP_TAG_TEXTLANG :
2692 case IPP_TAG_NAMELANG :
2693 bytes += 4 * attr->num_values;/* Charset + text length */
2694
2695 for (i = 0, value = attr->values;
2696 i < attr->num_values;
2697 i ++, value ++)
2698 {
2699 if (value->string.charset != NULL)
2700 bytes += (int)strlen(value->string.charset);
2701
2702 if (value->string.text != NULL)
2703 bytes += (int)strlen(value->string.text);
2704 }
2705 break;
2706
2707 case IPP_TAG_BEGIN_COLLECTION :
2708 for (i = 0, value = attr->values;
2709 i < attr->num_values;
2710 i ++, value ++)
2711 bytes += (int)ipp_length(value->collection, 1);
2712 break;
2713
2714 default :
2715 for (i = 0, value = attr->values;
2716 i < attr->num_values;
2717 i ++, value ++)
2718 bytes += value->unknown.length;
2719 break;
2720 }
2721 }
2722
2723 /*
2724 * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
2725 * for the "end of collection" tag and return...
2726 */
2727
2728 if (collection)
2729 bytes += 5;
2730 else
2731 bytes ++;
2732
2733 DEBUG_printf(("ipp_length: bytes=%d\n", bytes));
2734
2735 return (bytes);
2736 }
2737
2738
2739 /*
2740 * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
2741 */
2742
2743 static ssize_t /* O - Number of bytes read */
2744 ipp_read_http(http_t *http, /* I - Client connection */
2745 ipp_uchar_t *buffer, /* O - Buffer for data */
2746 size_t length) /* I - Total length */
2747 {
2748 int tbytes, /* Total bytes read */
2749 bytes; /* Bytes read this pass */
2750 char len[32]; /* Length string */
2751
2752
2753 DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
2754 http, buffer, (int)length));
2755
2756 /*
2757 * Loop until all bytes are read...
2758 */
2759
2760 for (tbytes = 0, bytes = 0;
2761 tbytes < (int)length;
2762 tbytes += bytes, buffer += bytes)
2763 {
2764 DEBUG_printf(("ipp_read_http: tbytes=%d, http->state=%d\n", tbytes,
2765 http->state));
2766
2767 if (http->state == HTTP_WAITING)
2768 break;
2769
2770 if (http->used > 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
2771 {
2772 /*
2773 * Do "fast read" from HTTP buffer directly...
2774 */
2775
2776 if (http->used > (int)(length - tbytes))
2777 bytes = (int)(length - tbytes);
2778 else
2779 bytes = http->used;
2780
2781 if (bytes == 1)
2782 buffer[0] = http->buffer[0];
2783 else
2784 memcpy(buffer, http->buffer, bytes);
2785
2786 http->used -= bytes;
2787 http->data_remaining -= bytes;
2788
2789 if (http->data_remaining <= INT_MAX)
2790 http->_data_remaining = (int)http->data_remaining;
2791 else
2792 http->_data_remaining = INT_MAX;
2793
2794 if (http->used > 0)
2795 memmove(http->buffer, http->buffer + bytes, http->used);
2796
2797 if (http->data_remaining == 0)
2798 {
2799 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2800 {
2801 /*
2802 * Get the trailing CR LF after the chunk...
2803 */
2804
2805 if (!httpGets(len, sizeof(len), http))
2806 return (-1);
2807 }
2808
2809 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
2810 {
2811 if (http->state == HTTP_POST_RECV)
2812 http->state ++;
2813 else
2814 http->state = HTTP_WAITING;
2815 }
2816 }
2817 }
2818 else
2819 {
2820 /*
2821 * Wait a maximum of 1 second for data...
2822 */
2823
2824 if (!http->blocking)
2825 {
2826 /*
2827 * Wait up to 10 seconds for more data on non-blocking sockets...
2828 */
2829
2830 if (!httpWait(http, 10000))
2831 {
2832 /*
2833 * Signal no data...
2834 */
2835
2836 bytes = -1;
2837 break;
2838 }
2839 }
2840
2841 if ((bytes = httpRead2(http, (char *)buffer, length - tbytes)) <= 0)
2842 break;
2843 }
2844 }
2845
2846 /*
2847 * Return the number of bytes read...
2848 */
2849
2850 if (tbytes == 0 && bytes < 0)
2851 tbytes = -1;
2852
2853 DEBUG_printf(("ipp_read_http: returning %d bytes...\n", tbytes));
2854
2855 return (tbytes);
2856 }
2857
2858
2859 /*
2860 * 'ipp_read_file()' - Read IPP data from a file.
2861 */
2862
2863 static ssize_t /* O - Number of bytes read */
2864 ipp_read_file(int *fd, /* I - File descriptor */
2865 ipp_uchar_t *buffer, /* O - Read buffer */
2866 size_t length) /* I - Number of bytes to read */
2867 {
2868 #ifdef WIN32
2869 return ((ssize_t)read(*fd, buffer, (unsigned)length));
2870 #else
2871 return (read(*fd, buffer, length));
2872 #endif /* WIN32 */
2873 }
2874
2875
2876 /*
2877 * 'ipp_write_file()' - Write IPP data to a file.
2878 */
2879
2880 static ssize_t /* O - Number of bytes written */
2881 ipp_write_file(int *fd, /* I - File descriptor */
2882 ipp_uchar_t *buffer, /* I - Data to write */
2883 size_t length) /* I - Number of bytes to write */
2884 {
2885 #ifdef WIN32
2886 return ((ssize_t)write(*fd, buffer, (unsigned)length));
2887 #else
2888 return (write(*fd, buffer, length));
2889 #endif /* WIN32 */
2890 }
2891
2892
2893 #ifdef __linux
2894 /*
2895 * The following symbol definitions are provided only for KDE
2896 * compatibility during the CUPS 1.2 testing period and will be
2897 * removed in a future release of CUPS. These are PRIVATE APIs
2898 * from CUPS 1.1.x that the KDE developers chose to use...
2899 */
2900
2901 ipp_attribute_t * /* O - New attribute */
2902 _ipp_add_attr(ipp_t *ipp, /* I - IPP message */
2903 int num_values) /* I - Number of values */
2904 {
2905 return (_ippAddAttr(ipp, num_values));
2906 }
2907
2908 void
2909 _ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */
2910 {
2911 _ippFreeAttr(attr);
2912 }
2913 #endif /* __linux */
2914
2915
2916 /*
2917 * End of "$Id: ipp.c 7463 2008-04-17 00:24:25Z mike $".
2918 */