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