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