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