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