diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2012-05-23 22:51:18 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2012-05-23 22:51:18 +0000 |
commit | a29fd7ddb5d63688a4d44d08e4ab16428921c321 (patch) | |
tree | d8e716c51da91f08d468e90262417f9a6d6fd5b0 /examples | |
parent | f3c17241a42a0845eae2099e6970b5aca9bbd836 (diff) | |
download | cups-a29fd7ddb5d63688a4d44d08e4ab16428921c321.tar.gz |
Merge changes from CUPS 1.6svn-r10510.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3833 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'examples')
-rw-r--r-- | examples/ppdx.c | 314 | ||||
-rw-r--r-- | examples/ppdx.h | 82 | ||||
-rw-r--r-- | examples/testppdx.c | 117 | ||||
-rw-r--r-- | examples/testppdx.ppd | 121 |
4 files changed, 634 insertions, 0 deletions
diff --git a/examples/ppdx.c b/examples/ppdx.c new file mode 100644 index 000000000..61588cad1 --- /dev/null +++ b/examples/ppdx.c @@ -0,0 +1,314 @@ +/* + * "$Id$" + * + * Example code for encoding and decoding large amounts of data in a PPD file. + * This would typically be used in a driver to save configuration/state + * information that could be used by an application. + * + * Copyright 2012 by Apple Inc. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * ppdxReadData() - Read encoded data from a ppd_file_t *. + * ppdxWriteData() - Writes encoded data to stderr using PPD: messages. + */ + +/* + * Include necessary headers... + */ + +#include "ppdx.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <zlib.h> /* For compression of the data */ + + +/* + * Constants... + */ + +#define PPDX_MAX_VALUE (PPD_MAX_LINE - PPD_MAX_NAME - 4) + /* Max value length with delimiters + nul */ +#define PPDX_MAX_CHUNK (PPDX_MAX_VALUE * 3 / 4) + /* Max length of each chunk when Base64-encoded */ + + +/* + * 'ppdxReadData()' - Read encoded data from a ppd_file_t *. + * + * Reads chunked data in the PPD file "ppd" using the prefix "name". Returns + * an allocated pointer to the data (which is nul-terminated for convenience) + * along with the length of the data in the variable pointed to by "datasize", + * which can be NULL to indicate the caller doesn't need the length. + * + * Returns NULL if no data is present in the PPD with the prefix. + */ + +void * /* O - Data or NULL */ +ppdxReadData(ppd_file_t *ppd, /* I - PPD file */ + const char *name, /* I - Keyword prefix */ + size_t *datasize) /* O - Size of data or NULL for don't care */ +{ + char keyword[PPD_MAX_NAME], /* Keyword name */ + decoded[PPDX_MAX_CHUNK + 1]; + /* Decoded string */ + unsigned chunk = 0; /* Current chunk number */ + int len; /* Length of current chunk */ + ppd_attr_t *attr; /* Keyword/value from PPD file */ + Bytef *data; /* Pointer to data */ + size_t alloc_size; /* Allocated size of data buffer */ + z_stream decomp; /* Decompressor stream */ + int error; /* Error/status from inflate() */ + + + /* + * Range check input... + */ + + if (datasize) + *datasize = 0; + + if (!ppd || !name) + return (NULL); + + /* + * First see if there are any instances of the named keyword in the PPD... + */ + + snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk); + if ((attr = ppdFindAttr(ppd, keyword, NULL)) == NULL) + return (NULL); + + /* + * Allocate some memory and start decoding... + */ + + data = malloc(257); + alloc_size = 256; + + memset(&decomp, 0, sizeof(decomp)); + decomp.next_out = data; + decomp.avail_out = 256; + + inflateInit(&decomp); + + do + { + /* + * Grab the data from the current attribute and decode it... + */ + + len = sizeof(decoded); + if (!httpDecode64_2(decoded, &len, attr->value) || len == 0) + break; + +// printf("chunk %04x has length %d\n", chunk, len); + + /* + * Decompress this chunk... + */ + + decomp.next_in = decoded; + decomp.avail_in = len; + + do + { + Bytef *temp; /* Temporary pointer */ + size_t temp_size; /* Temporary allocation size */ + +// printf("Before inflate: avail_in=%d, avail_out=%d\n", decomp.avail_in, +// decomp.avail_out); + + if ((error = inflate(&decomp, Z_NO_FLUSH)) < Z_OK) + { + fprintf(stderr, "ERROR: inflate returned %d (%s)\n", error, decomp.msg); + break; + } + +// printf("After inflate: avail_in=%d, avail_out=%d, error=%d\n", +// decomp.avail_in, decomp.avail_out, error); + + if (decomp.avail_out == 0) + { + if (alloc_size < 2048) + temp_size = alloc_size * 2; + else if (alloc_size < PPDX_MAX_DATA) + temp_size = alloc_size + 2048; + else + break; + + if ((temp = realloc(data, temp_size + 1)) == NULL) + { + free(data); + return (NULL); + } + + decomp.next_out = temp + (decomp.next_out - data); + decomp.avail_out = temp_size - alloc_size; + data = temp; + alloc_size = temp_size; + } + } + while (decomp.avail_in > 0); + + chunk ++; + snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk); + } + while ((attr = ppdFindAttr(ppd, keyword, NULL)) != NULL); + + inflateEnd(&decomp); + + /* + * Nul-terminate the data (usually a string)... + */ + + *(decomp.next_out) = '\0'; + + if (datasize) + *datasize = decomp.next_out - data; + + return (data); +} + + +/* + * 'ppdxWriteData()' - Writes encoded data to stderr using PPD: messages. + * + * Writes chunked data to the PPD file using PPD: messages sent to stderr for + * cupsd. "name" must be a valid PPD keyword string whose length is less than + * 37 characters to allow for chunk numbering. "data" provides a pointer to the + * data to be written, and "datasize" provides the length. + */ + +extern void +ppdxWriteData(const char *name, /* I - Base name of keyword */ + const void *data, /* I - Data to write */ + size_t datasize) /* I - Number of bytes in data */ +{ + char buffer[PPDX_MAX_CHUNK], /* Chunk buffer */ + encoded[PPDX_MAX_VALUE + 1], + /* Encoded data */ + pair[PPD_MAX_LINE], /* name=value pair */ + line[PPDX_MAX_STATUS], /* Line buffer */ + *lineptr, /* Current position in line buffer */ + *lineend; /* End of line buffer */ + unsigned chunk = 0; /* Current chunk number */ + int len; /* Length of current chunk */ + z_stream comp; /* Compressor stream */ + int error; /* Error/status from deflate() */ + + + /* + * Range check input... + */ + + if (!name || (!data && datasize > 0) || datasize > PPDX_MAX_DATA) + return; + + strlcpy(line, "PPD:", sizeof(line)); + lineptr = line + 4; + lineend = line + sizeof(line) - 2; + + if (datasize > 0) + { + /* + * Compress and encode output... + */ + + memset(&comp, 0, sizeof(comp)); + comp.next_in = (Bytef *)data; + comp.avail_in = datasize; + + deflateInit(&comp, 9); + + do + { + /* + * Compress a chunk... + */ + + comp.next_out = buffer; + comp.avail_out = sizeof(buffer); + + if ((error = deflate(&comp, Z_FINISH)) < Z_OK) + { + fprintf(stderr, "ERROR: deflate returned %d (%s)\n", error, comp.msg); + break; + } + + /* + * Write a chunk... + */ + + len = sizeof(buffer) - comp.avail_out; + httpEncode64_2(encoded, sizeof(encoded), buffer, len); + + len = (int)snprintf(pair, sizeof(pair), " %s%04x=%s", name, chunk, + encoded); +#ifdef DEBUG + fprintf(stderr, "DEBUG: *%s%04x: \"%s\"\n", name, chunk, encoded); +#endif /* DEBUG */ + + if ((lineptr + len) >= lineend) + { + *lineptr++ = '\n'; + *lineptr = '\0'; + + fputs(line, stderr); + lineptr = line + 4; + } + + strlcpy(lineptr, pair, lineend - lineptr); + lineptr += len; + + /* + * Setup for the next one... + */ + + chunk ++; + } + while (comp.avail_out == 0); + } + + deflateEnd(&comp); + + /* + * Write a trailing empty chunk to signal EOD... + */ + + len = (int)snprintf(pair, sizeof(pair), " %s%04x=\"\"", name, chunk); +#ifdef DEBUG + fprintf(stderr, "DEBUG: *%s%04x: \"\"\n", name, chunk); +#endif /* DEBUG */ + + if ((lineptr + len) >= lineend) + { + *lineptr++ = '\n'; + *lineptr = '\0'; + + fputs(line, stderr); + lineptr = line + 4; + } + + strlcpy(lineptr, pair, lineend - lineptr); + lineptr += len; + + *lineptr++ = '\n'; + *lineptr = '\0'; + + fputs(line, stderr); +} + + +/* + * End of "$Id$". + */ diff --git a/examples/ppdx.h b/examples/ppdx.h new file mode 100644 index 000000000..1be6928da --- /dev/null +++ b/examples/ppdx.h @@ -0,0 +1,82 @@ +/* + * "$Id$" + * + * Header for PPD data encoding example code. + * + * Copyright 2012 by Apple Inc. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + */ + +#ifndef _PPDX_H_ +# define _PPDX_H_ + + +/* + * Include necessary headers... + */ + +# include <cups/ppd.h> + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Maximum amount of data to encode/decode... + */ + +# define PPDX_MAX_STATUS 1024 /* Limit on log messages in 10.6 */ +# define PPDX_MAX_DATA 16777216/* 16MiB */ + + +/* + * 'ppdxReadData()' - Read encoded data from a ppd_file_t *. + * + * Reads chunked data in the PPD file "ppd" using the prefix "name". Returns + * an allocated pointer to the data (which is nul-terminated for convenience) + * along with the length of the data in the variable pointed to by "datasize", + * which can be NULL to indicate the caller doesn't need the length. + * + * Returns NULL if no data is present in the PPD with the prefix. + */ + +extern void *ppdxReadData(ppd_file_t *ppd, const char *name, + size_t *datasize); + + +/* + * 'ppdxWriteData()' - Writes encoded data to stderr using PPD: messages. + * + * Writes chunked data to the PPD file using PPD: messages sent to stderr for + * cupsd. "name" must be a valid PPD keyword string whose length is less than + * 37 characters to allow for chunk numbering. "data" provides a pointer to the + * data to be written, and "datasize" provides the length. + */ + +extern void ppdxWriteData(const char *name, const void *data, + size_t datasize); + + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_PPDX_H */ + +/* + * End of "$Id$". + */ diff --git a/examples/testppdx.c b/examples/testppdx.c new file mode 100644 index 000000000..f1c168688 --- /dev/null +++ b/examples/testppdx.c @@ -0,0 +1,117 @@ +/* + * "$Id$" + * + * Test program for PPD data encoding example code. + * + * Compile with: + * + * gcc -o testppdx -D_PPD_DEPRECATED="" -g testppdx.c ppdx.c -lcups -lz + * + * Copyright 2012 by Apple Inc. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Read data from a test PPD file and write out new chunks. + */ + +/* + * Include necessary headers... + */ + +#include <stdio.h> +#include <string.h> +#include "ppdx.h" + + +/* + * 'main()' - Read data from a test PPD file and write out new chunks. + */ + +int /* O - Exit status */ +main(void) +{ + int status = 0; /* Exit status */ + FILE *fp; /* File to read */ + char contents[8193], /* Contents of file */ + *data; /* Data from PPD */ + size_t contsize, /* File size */ + datasize; /* Data size */ + ppd_file_t *ppd; /* Test PPD */ + + + /* + * Open the PPD and get the data from it... + */ + + ppd = ppdOpenFile("testppdx.ppd"); + data = ppdxReadData(ppd, "EXData", &datasize); + + /* + * Open this source file and read it... + */ + + fp = fopen("testppdx.c", "r"); + if (fp) + { + contsize = fread(contents, 1, sizeof(contents) - 1, fp); + fclose(fp); + contents[contsize] = '\0'; + } + else + { + contents[0] = '\0'; + contsize = 0; + } + + /* + * Compare data... + */ + + if (data) + { + if (contsize != datasize) + { + fprintf(stderr, "ERROR: PPD has %ld bytes, test file is %ld bytes.\n", + (long)datasize, (long)contsize); + status = 1; + } + else if (strcmp(contents, data)) + { + fputs("ERROR: PPD and test file are not the same.\n", stderr); + status = 1; + } + + if (status) + { + if ((fp = fopen("testppdx.dat", "wb")) != NULL) + { + fwrite(data, 1, datasize, fp); + fclose(fp); + fputs("ERROR: See testppdx.dat for data from PPD.\n", stderr); + } + else + perror("Unable to open 'testppdx.dat'"); + } + + free(data); + } + + printf("Encoding %ld bytes for PPD...\n", (long)contsize); + + ppdxWriteData("EXData", contents, contsize); + + return (1); +} + + +/* + * End of "$Id$". + */ diff --git a/examples/testppdx.ppd b/examples/testppdx.ppd new file mode 100644 index 000000000..179b1ec6c --- /dev/null +++ b/examples/testppdx.ppd @@ -0,0 +1,121 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id$" +*% +*% Test PPD file for data encoding example. +*% +*% This file cannot be used with any known printers. +*% +*% Copyright 2007-2012 by Apple Inc. +*% Copyright 2002-2006 by Easy Software Products. +*% +*% These coded instructions, statements, and computer programs are the +*% property of Apple Inc. and are protected by Federal copyright +*% law. Distribution and use rights are outlined in the file "LICENSE.txt" +*% which should have been included with this file. If this file is +*% file is missing or damaged, see the license at "http://www.cups.org/". +*FormatVersion: "4.3" +*FileVersion: "1.3" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "TESTPPDX.PPD" +*Manufacturer: "Apple" +*Product: "(Test PPDX)" +*cupsVersion: 1.6 +*ModelName: "Test PPDX" +*ShortNickName: "Test PPDX" +*NickName: "Test PPDX for CUPS" +*PSVersion: "(3010.000) 0" +*LanguageLevel: "3" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*TTRasterizer: Type42 +*cupsFilter: "application/vnd.cups-raster 0 -" +*RequiresPageRegion All: True + +*% For PageSize, we have put all of the translations in-line... +*OpenUI *PageSize/Page Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter/US Letter: "PageSize=Letter" +*PageSize Letter.Banner/US Letter Banner: "PageSize=Letter.Banner" +*PageSize Letter.Fullbleed/US Letter Borderless: "PageSize=Letter.Fullbleed" +*PageSize A4/A4: "PageSize=A4" +*PageSize Env10/#10 Envelope: "PageSize=Env10" +*CloseUI: *PageSize + +*% For PageRegion, we have separated the translations... +*OpenUI *PageRegion/Page Region: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter/US Letter: "PageRegion=Letter" +*PageRegion Letter.Banner/US Letter Banner: "PageRegion=Letter.Fullbleed" +*PageRegion Letter.Fullbleed/US Letter Borderless: "PageRegion=Letter.Fullbleed" +*PageRegion A4/A4: "PageRegion=A4" +*PageRegion Env10/#10 Envelope: "PageRegion=Env10" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter: "18 36 594 756" +*ImageableArea Letter.Banner: "18 0 594 792" +*ImageableArea Letter.Fullbleed: "0 0 612 792" +*ImageableArea A4: "18 36 577 806" +*ImageableArea Env10: "18 36 279 648" + +*DefaultPaperDimension: Letter +*PaperDimension Letter: "612 792" +*PaperDimension Letter.Banner: "612 792" +*PaperDimension Letter.Fullbleed: "612 792" +*PaperDimension A4: "595 842" +*PaperDimension Env10: "297 684" + +*DefaultFont: Courier +*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM +*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM +*Font Bookman-Demi: Standard "(001.004S)" Standard ROM +*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM +*Font Bookman-Light: Standard "(001.004S)" Standard ROM +*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM +*Font Courier: Standard "(002.004S)" Standard ROM +*Font Courier-Bold: Standard "(002.004S)" Standard ROM +*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM +*Font Courier-Oblique: Standard "(002.004S)" Standard ROM +*Font Helvetica: Standard "(001.006S)" Standard ROM +*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM +*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM +*Font Palatino-Bold: Standard "(001.005S)" Standard ROM +*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM +*Font Palatino-Italic: Standard "(001.005S)" Standard ROM +*Font Palatino-Roman: Standard "(001.005S)" Standard ROM +*Font Symbol: Special "(001.007S)" Special ROM +*Font Times-Bold: Standard "(001.007S)" Standard ROM +*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM +*Font Times-Italic: Standard "(001.007S)" Standard ROM +*Font Times-Roman: Standard "(001.007S)" Standard ROM +*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM +*% +*% End of "$Id$". +*% +*EXData0000: "eNqlVm1v2zYQ/hz/ipvWznLgl6T7siXrgCJ2AANBEyQpNmAtAlqiLG4SKZBU7LTIf9/dUW9Og32ZAFsieffcc88dKS2OR3AM0Zt1+ibCJxoA3EvnobJma0UJmbFwc7OEVHgBUicmVXoLci/KqpCAQznvHC9MWSmc3Smfn3WzdG2TBGYGPCJXVbqH2fIBQR+Wq5vb1cWH+9XyfRTBbNs" +*EXData0001: "GcwTaG6zIqkrh7evgzDVk1Xb3MO7k9N3sHmCDxWRWeuk53KfSxf4paC087ZOvDLaTcF54WUptcdnoVO0KavaS9um7EBYCT6XAQhnK2n9E5hsEIc9yQ6XvUw8RkEelzKVVhQI2TAMEIXYzQGWClmoTU002L1GgmwVIpraF0ozXYoOGUkZXa0vVh/vVnO/91FA2+UqycHlpi5SyMWjhI0" +*EXData0002: "lBq9kqKmbEl9BFCOETDwOuuHoFxAaQZQKueooljmVJRiK1NUSHL+UKhEaiQpPES599XZYrHb7eZUkLmx20U0lLsPAK7e/I2agDcME1S7vpst5aMsUM0U7kzmd5S03CeyIkVaqAujPdWm759SKB1PYAa3UqShDzNrShDcLdycHJgk3VnlWUnQcgdJXut/HCEvRqMFw62DSricSOeEfYI" +*EXData0003: "HFGldfN5Y/djIyT85nyqzDz//WDKolgHcxE3ah6N2hDjQHj8vxkr7Y/oWhzDNYKt9spz89aOljnKo1HpZPRtBMDGzep7ODlntxcuAJfrq9XR0XFWnQfcS6KBZbJElC2SXNijo6Spwl+/nP7685cp27aVoY3A9NEesSi9Bm3ZZUopMpxTX+WDZzx6nPZRaRggCIFG5z1Iuwh0DDxQNAQ" +*EXData0004: "OcbnJtJ9qyPpNAISHpW/rmTYOrRC4m6l53FfAuW50OzH4IBq4Y1ciVYcdUcQ/kWTc7Rib7baU0GJYIyDKUSrP2kQTeGnNgd0eEmHNoSpbSL7orPch1SyCkNkuDn0gEKC0JENLFQGcVZN8InKjYVqJCU3wovbmk3hdMoCmqybo+2Ds+h/zs5ZUhgn427c1btF/YKw488nY1p+xp8snDw" +*EXData0005: "CM3WJ0OzASUA7kH27eSgtwNteZJqmDklRnN9ajTTYf3wHjpxeTXYkGK4F30W4zaV1lI1bm+vb8+4+Llw8LagMxm1nIZt155O3fz8s46mDVh7xYXR20kbcNqMWzKNWgDdRjsNM8/8TyIxeTwmkrIaVITze0m/9i4ekqbO6JmSVNqE/nWilMwWQrL/waMTMCwdxqT5+NVOQ4LUa7tNNJk" +*EXData0006: "kOQfP11dTRqvb51GGZ9WXC3usl6nrpNe667v072jN8wgNn9mpMPj49V0n5t7043hwrezNTaOPmmxCacZ5QbjIf44mhwIhDsmpDFpmxSabopW7TdO1yftNxA2LZP6rifCSbL/g8Th06E/GPoWOLS30tdWQ3yKw+fu1bHCDsDTNXyPhbfAvwxF0gE=" +*EXData0007: "" |