]>
git.ipfire.org Git - thirdparty/cups.git/blob - examples/ppdx.c
4 * Example code for encoding and decoding large amounts of data in a PPD file.
5 * This would typically be used in a driver to save configuration/state
6 * information that could be used by an application.
8 * Copyright 2012 by Apple Inc.
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
16 * This file is subject to the Apple OS-Developed Software exception.
20 * ppdxReadData() - Read encoded data from a ppd_file_t *.
21 * ppdxWriteData() - Writes encoded data to stderr using PPD: messages.
25 * Include necessary headers...
32 #include <zlib.h> /* For compression of the data */
39 #define PPDX_MAX_VALUE (PPD_MAX_LINE - PPD_MAX_NAME - 4)
40 /* Max value length with delimiters + nul */
41 #define PPDX_MAX_CHUNK (PPDX_MAX_VALUE * 3 / 4)
42 /* Max length of each chunk when Base64-encoded */
46 * 'ppdxReadData()' - Read encoded data from a ppd_file_t *.
48 * Reads chunked data in the PPD file "ppd" using the prefix "name". Returns
49 * an allocated pointer to the data (which is nul-terminated for convenience)
50 * along with the length of the data in the variable pointed to by "datasize",
51 * which can be NULL to indicate the caller doesn't need the length.
53 * Returns NULL if no data is present in the PPD with the prefix.
56 void * /* O - Data or NULL */
57 ppdxReadData(ppd_file_t
*ppd
, /* I - PPD file */
58 const char *name
, /* I - Keyword prefix */
59 size_t *datasize
) /* O - Size of data or NULL for don't care */
61 char keyword
[PPD_MAX_NAME
], /* Keyword name */
62 decoded
[PPDX_MAX_CHUNK
+ 1];
64 unsigned chunk
= 0; /* Current chunk number */
65 int len
; /* Length of current chunk */
66 ppd_attr_t
*attr
; /* Keyword/value from PPD file */
67 Bytef
*data
; /* Pointer to data */
68 size_t alloc_size
; /* Allocated size of data buffer */
69 z_stream decomp
; /* Decompressor stream */
70 int error
; /* Error/status from inflate() */
74 * Range check input...
84 * First see if there are any instances of the named keyword in the PPD...
87 snprintf(keyword
, sizeof(keyword
), "%s%04x", name
, chunk
);
88 if ((attr
= ppdFindAttr(ppd
, keyword
, NULL
)) == NULL
)
92 * Allocate some memory and start decoding...
98 memset(&decomp
, 0, sizeof(decomp
));
99 decomp
.next_out
= data
;
100 decomp
.avail_out
= 256;
102 inflateInit(&decomp
);
107 * Grab the data from the current attribute and decode it...
110 len
= sizeof(decoded
);
111 if (!httpDecode64_2(decoded
, &len
, attr
->value
) || len
== 0)
114 // printf("chunk %04x has length %d\n", chunk, len);
117 * Decompress this chunk...
120 decomp
.next_in
= decoded
;
121 decomp
.avail_in
= len
;
125 Bytef
*temp
; /* Temporary pointer */
126 size_t temp_size
; /* Temporary allocation size */
128 // printf("Before inflate: avail_in=%d, avail_out=%d\n", decomp.avail_in,
129 // decomp.avail_out);
131 if ((error
= inflate(&decomp
, Z_NO_FLUSH
)) < Z_OK
)
133 fprintf(stderr
, "ERROR: inflate returned %d (%s)\n", error
, decomp
.msg
);
137 // printf("After inflate: avail_in=%d, avail_out=%d, error=%d\n",
138 // decomp.avail_in, decomp.avail_out, error);
140 if (decomp
.avail_out
== 0)
142 if (alloc_size
< 2048)
143 temp_size
= alloc_size
* 2;
144 else if (alloc_size
< PPDX_MAX_DATA
)
145 temp_size
= alloc_size
+ 2048;
149 if ((temp
= realloc(data
, temp_size
+ 1)) == NULL
)
155 decomp
.next_out
= temp
+ (decomp
.next_out
- data
);
156 decomp
.avail_out
= temp_size
- alloc_size
;
158 alloc_size
= temp_size
;
161 while (decomp
.avail_in
> 0);
164 snprintf(keyword
, sizeof(keyword
), "%s%04x", name
, chunk
);
166 while ((attr
= ppdFindAttr(ppd
, keyword
, NULL
)) != NULL
);
171 * Nul-terminate the data (usually a string)...
174 *(decomp
.next_out
) = '\0';
177 *datasize
= decomp
.next_out
- data
;
184 * 'ppdxWriteData()' - Writes encoded data to stderr using PPD: messages.
186 * Writes chunked data to the PPD file using PPD: messages sent to stderr for
187 * cupsd. "name" must be a valid PPD keyword string whose length is less than
188 * 37 characters to allow for chunk numbering. "data" provides a pointer to the
189 * data to be written, and "datasize" provides the length.
193 ppdxWriteData(const char *name
, /* I - Base name of keyword */
194 const void *data
, /* I - Data to write */
195 size_t datasize
) /* I - Number of bytes in data */
197 char buffer
[PPDX_MAX_CHUNK
], /* Chunk buffer */
198 encoded
[PPDX_MAX_VALUE
+ 1],
200 pair
[PPD_MAX_LINE
], /* name=value pair */
201 line
[PPDX_MAX_STATUS
], /* Line buffer */
202 *lineptr
, /* Current position in line buffer */
203 *lineend
; /* End of line buffer */
204 unsigned chunk
= 0; /* Current chunk number */
205 int len
; /* Length of current chunk */
206 z_stream comp
; /* Compressor stream */
207 int error
; /* Error/status from deflate() */
211 * Range check input...
214 if (!name
|| (!data
&& datasize
> 0) || datasize
> PPDX_MAX_DATA
)
217 strlcpy(line
, "PPD:", sizeof(line
));
219 lineend
= line
+ sizeof(line
) - 2;
224 * Compress and encode output...
227 memset(&comp
, 0, sizeof(comp
));
228 comp
.next_in
= (Bytef
*)data
;
229 comp
.avail_in
= datasize
;
231 deflateInit(&comp
, 9);
236 * Compress a chunk...
239 comp
.next_out
= buffer
;
240 comp
.avail_out
= sizeof(buffer
);
242 if ((error
= deflate(&comp
, Z_FINISH
)) < Z_OK
)
244 fprintf(stderr
, "ERROR: deflate returned %d (%s)\n", error
, comp
.msg
);
252 len
= sizeof(buffer
) - comp
.avail_out
;
253 httpEncode64_2(encoded
, sizeof(encoded
), buffer
, len
);
255 len
= (int)snprintf(pair
, sizeof(pair
), " %s%04x=%s", name
, chunk
,
258 fprintf(stderr
, "DEBUG: *%s%04x: \"%s\"\n", name
, chunk
, encoded
);
261 if ((lineptr
+ len
) >= lineend
)
270 strlcpy(lineptr
, pair
, lineend
- lineptr
);
274 * Setup for the next one...
279 while (comp
.avail_out
== 0);
285 * Write a trailing empty chunk to signal EOD...
288 len
= (int)snprintf(pair
, sizeof(pair
), " %s%04x=\"\"", name
, chunk
);
290 fprintf(stderr
, "DEBUG: *%s%04x: \"\"\n", name
, chunk
);
293 if ((lineptr
+ len
) >= lineend
)
302 strlcpy(lineptr
, pair
, lineend
- lineptr
);