source: trunk/src/core/RpEncode.cc @ 1264

Last change on this file since 1264 was 1264, checked in by dkearney, 14 years ago

fixing rp library's get() function for retrieving encoded data. if the data is encoded there is no need to do xml entity translation. adding a function rappture's encode class for checking to see if a string has a proper header encode header. adding corresponding tcl functions and tests. also adjusting some of the int declarations to size_t.

File size: 6.7 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::encoding
4 *
5 *  The encoding module for rappture used to zip and b64 encode data.
6 * ======================================================================
7 *  AUTHOR:  Derrick Kearney, Purdue University
8 *  Copyright (c) 2004-2007  Purdue Research Foundation
9 *
10 *  See the file "license.terms" for information on usage and
11 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * ======================================================================
13 */
14#include "RpEncode.h"
15#include <cstring>
16
17#ifdef __cplusplus
18extern "C" {
19#endif // ifdef __cplusplus
20
21using namespace Rappture::encoding;
22
23/**********************************************************************/
24// FUNCTION: Rappture::encoding::isbinary()
25/// isbinary checks to see if given string is binary.
26/**
27 * Checks to see if any of size characters in *buf are binary
28 * Full function call:
29 * Rappture::encoding::isbinary(buf,size);
30 *
31 */
32
33int
34isbinary(const char* buf, int size)
35{
36    if (buf == NULL) {
37        return 0;
38    }
39
40    if (size < 0) {
41        size = strlen(buf);
42    }
43
44    for (int index = 0; index < size; index++) {
45        int c = *buf++;
46        if (((c >= '\000') && (c <= '\010')) ||
47            ((c >= '\013') && (c <= '\014')) ||
48            ((c >= '\016') && (c <= '\037')) ||
49            ((c >= '\177') && (c <= '\377')) ) {
50            // data is binary
51            return index+1;
52        }
53    }
54    return 0;
55}
56
57/**********************************************************************/
58// FUNCTION: Rappture::encoding::isencoded()
59/// checks header of given string to determine if it was encoded by rappture.
60/**
61 * Checks to see if the string buf was encoded by rappture
62 * and contains the proper "@@RP-ENC:" header.
63 * rappture encoded strings start with the string "@@RP-ENC:X\n"
64 * where X is one of z, b64, zb64
65 * This function will not work for strings that do not have the header.
66 * Full function call:
67 * Rappture::encoding::isencoded(buf,size);
68 *
69 */
70
71size_t
72isencoded(const char* buf, int size)
73{
74    size_t flags = 0;
75    size_t len = 0;
76
77    if (buf == NULL) {
78        return flags;
79    }
80
81    if (size < 0) {
82        len = strlen(buf);
83    } else {
84        len = size;
85    }
86
87    // check the following for valid rappture encoded string:
88    // all strings encoded by rappture are at least 11 characters
89    // rappture encoded strings start with the '@' character
90    // rappture encoded strings start with the string "@@RP-ENC:X\n"
91    // where X is one of z, b64, zb64
92    if (    (len >= 11)
93        &&  ('@' == *buf)
94        &&  (strncmp("@@RP-ENC:",buf,9) == 0) ) {
95
96        size_t idx = 9;
97
98        // check the string length and if the z flag was specified
99        // add 1 for \n
100        if (    (len >= (idx + 1))
101            &&  (buf[idx] == 'z') ) {
102            flags |= RPENC_Z;
103            ++idx;
104        }
105        // check the string length and if the b64 flag was specified
106        // add 1 for \n
107        if (    (len >= (idx + 2 + 1))
108            &&  (buf[idx]   == 'b')
109            &&  (buf[idx+1] == '6')
110            &&  (buf[idx+2] == '4') ) {
111            flags |= RPENC_B64;
112            idx += 3;
113        }
114        // check for the '\n' at the end of the header
115        if (buf[idx] != '\n') {
116            flags = 0;
117        }
118    }
119
120    return flags;
121}
122
123/**********************************************************************/
124// FUNCTION: Rappture::encoding::encode()
125/// Rappture::encoding::encode function encodes provided string
126/**
127 * Encode a string by compressing it with zlib and then base64 encoding it.
128 *
129 * Full function call:
130 * Rappture::encoding::encode(buf,flags)
131 */
132
133Rappture::Outcome
134encode (Rappture::Buffer& buf, size_t flags)
135{
136
137    int compress              = 0;
138    int base64                = 0;
139    int addHeader             = 0;
140    Rappture::Outcome err;
141    Rappture::Buffer outData;
142
143    if ((flags & RPENC_Z) == RPENC_Z ) {
144        compress = 1;
145    }
146    if ((flags & RPENC_B64) == RPENC_B64 ) {
147        base64 = 1;
148    }
149    if ((flags & RPENC_HDR) == RPENC_HDR ) {
150        addHeader = 1;
151    }
152
153    outData.append(buf.bytes(),buf.size());
154    err = outData.encode(compress,base64);
155    if (!err) {
156        buf.clear();
157        if (addHeader == 1) {
158            if ((compress == 1) && (base64 == 0)) {
159                buf.append("@@RP-ENC:z\n",11);
160            }
161            else if ((compress == 0) && (base64 == 1)) {
162                buf.append("@@RP-ENC:b64\n",13);
163            }
164            else if ((compress == 1) && (base64 == 1)) {
165                buf.append("@@RP-ENC:zb64\n",14);
166            }
167            else {
168                // do nothing
169            }
170        }
171        else {
172            // do nothing
173        }
174        buf.append(outData.bytes(),outData.size());
175    }
176
177    return err;
178}
179
180/**********************************************************************/
181// FUNCTION: Rappture::encoding::decode()
182/// Rappture::encoding::decode function decodes provided string
183/**
184 * Decode a string by uncompressing it with zlib and base64 decoding it.
185 * If binary data is provided, the data is base64 decoded and uncompressed.
186 * Rappture::encoding::isbinary is used to qualify binary data.
187 *
188 * Full function call:
189 * Rappture::encoding::decode (buf,flags)
190 */
191
192Rappture::Outcome
193decode (Rappture::Buffer& buf, size_t flags)
194{
195
196    int decompress            = 0;
197    int base64                = 0;
198    int checkHDR              = 0;
199    Rappture::Outcome err;
200    Rappture::Buffer outData;
201
202    if ((flags & RPENC_Z) == RPENC_Z ) {
203        decompress = 1;
204    }
205    if ((flags & RPENC_B64) == RPENC_B64 ) {
206        base64 = 1;
207    }
208    if ((flags & RPENC_HDR) == RPENC_HDR ) {
209        checkHDR = 1;
210    }
211
212    if ((buf.size() > 11) && (strncmp(buf.bytes(),"@@RP-ENC:z\n",11) == 0)) {
213        outData.append(buf.bytes()+11,buf.size()-11);
214        if ( (checkHDR == 1) || ( (decompress == 0) && (base64 == 0) ) ) {
215            decompress = 1;
216            base64 = 0;
217        }
218    }
219    else if ((buf.size() > 13) && (strncmp(buf.bytes(),"@@RP-ENC:b64\n",13) == 0)) {
220        outData.append(buf.bytes()+13,buf.size()-13);
221        if ( (checkHDR == 1) || ( (decompress == 0) && (base64 == 0) ) ) {
222            decompress = 0;
223            base64 = 1;
224        }
225    }
226    else if ((buf.size() > 14) && (strncmp(buf.bytes(),"@@RP-ENC:zb64\n",14) == 0)) {
227        outData.append(buf.bytes()+14,buf.size()-14);
228        if ( (checkHDR == 1) || ( (decompress == 0) && (base64 == 0) ) ) {
229            decompress = 1;
230            base64 = 1;
231        }
232    }
233    else {
234        // no special recognized tags
235        outData.append(buf.bytes(),buf.size());
236    }
237
238    err = outData.decode(decompress,base64);
239    if (!err) {
240        buf.move(outData);
241    }
242
243    return err;
244}
245
246#ifdef __cplusplus
247}
248#endif // ifdef __cplusplus
Note: See TracBrowser for help on using the repository browser.