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

Last change on this file since 1382 was 1382, checked in by gah, 15 years ago

fixed encoding problems

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