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