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