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