source: trunk/lang/tcl/src/RpEncodeTclInterface.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: 12.1 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 <tcl.h>
15#include "RpEncode.h"
16
17extern "C" Tcl_AppInitProc RpEncoding_Init;
18
19static Tcl_ObjCmdProc RpTclEncodingIs;
20static Tcl_ObjCmdProc RpTclEncodingEncode;
21static Tcl_ObjCmdProc RpTclEncodingDecode;
22
23/**********************************************************************/
24// FUNCTION: RpEncoding_Init()
25/// Initializes the Rappture Encoding module and commands defined below
26/**
27 * Called in RapptureGUI_Init() to initialize the Rappture Units module.
28 * Initialized commands include:
29 * ::Rappture::encoding::is
30 * ::Rappture::encoding::encode
31 * ::Rappture::encoding::decode
32 */
33
34int
35RpEncoding_Init(Tcl_Interp *interp)
36{
37
38    Tcl_CreateObjCommand(interp, "::Rappture::encoding::is",
39        RpTclEncodingIs, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
40
41    Tcl_CreateObjCommand(interp, "::Rappture::encoding::encode",
42        RpTclEncodingEncode, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
43
44    Tcl_CreateObjCommand(interp, "::Rappture::encoding::decode",
45        RpTclEncodingDecode, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
46
47    return TCL_OK;
48}
49
50/**********************************************************************/
51// FUNCTION: RpTclEncodingIs()
52/// Rappture::encoding::is checks to see if given string is binary.
53/**
54 * Checks to see <string> is binary
55 * Full function call:
56 * ::Rappture::encoding::is binary <string>
57 *
58 */
59
60static int
61RpTclEncodingIs (ClientData cdata, Tcl_Interp *interp,
62    int objc, Tcl_Obj *const objv[])
63{
64    Tcl_ResetResult(interp);
65
66    // parse through command line options
67    if (objc != 3) {
68        Tcl_AppendResult(interp,
69            "wrong # args: should be \"",
70            Tcl_GetString(objv[0])," binary|encoded <string>\"",
71            (char*)NULL);
72        return TCL_ERROR;
73    }
74
75    const char *type = Tcl_GetString(objv[1]);
76
77    int bufLen;
78    const char *buf = (const char*) Tcl_GetByteArrayFromObj(objv[2],&bufLen);
79
80    if (('b' == *type) && (strcmp(type,"binary") == 0)) {
81        if (Rappture::encoding::isbinary(buf,bufLen) != 0) {
82            // non-ascii character found, return yes
83            Tcl_AppendResult(interp, "yes", (char*)NULL);
84        } else {
85            Tcl_AppendResult(interp, "no",(char*)NULL);
86        }
87        return TCL_OK;
88    } else if (('e' == *type) && (strcmp(type,"encoded") == 0)) {
89        if (Rappture::encoding::isencoded(buf,bufLen) != 0) {
90            // valid "@@RP-ENC:" header found, return yes
91            Tcl_AppendResult(interp, "yes", (char*)NULL);
92        } else {
93            Tcl_AppendResult(interp, "no",(char*)NULL);
94        }
95        return TCL_OK;
96    }
97    Tcl_AppendResult(interp, "bad option \"", type,
98            "\": should be one of binary, encoded",
99            (char*)NULL);
100    return TCL_ERROR;
101}
102
103/**********************************************************************/
104// FUNCTION: RpTclEncodingEncode()
105/// Rappture::encoding::encode function in Tcl, encodes provided string
106/**
107 * Encode a string by compressing it with zlib and then base64 encoding it.
108 * If binary data is provided, the data is compressed and base64 encoded.
109 * RpTclEncodingIs is used to qualify binary data.
110 *
111 * If the -as option is not set, zlib compression and base64 encoding
112 * is performed by default
113 *
114 * Full function call:
115 * ::Rappture::encoding::encode ?-as z|b64|zb64? ?-no-header? <string>
116 */
117
118static int
119RpTclEncodingEncode (   ClientData cdata,
120                        Tcl_Interp *interp,
121                        int objc,
122                        Tcl_Obj *const objv[]  )
123{
124
125    const char* encodeType    = NULL; // name of the units provided by user
126    const char* option        = NULL;
127    const char* cmdName       = NULL;
128    Rappture::Buffer buf; // name of the units provided by user
129    Rappture::Outcome err;
130
131    int optionLen             = 0;
132    int typeLen               = 0;
133    int nextarg               = 0; // start parsing using the '2'th argument
134
135    int compress              = 1;
136    int base64                = 1;
137    int addHeader             = 1;
138    int flags                 = 0;
139
140    Tcl_Obj *result           = NULL;
141
142    Tcl_ResetResult(interp);
143
144    cmdName = Tcl_GetString(objv[nextarg++]);
145
146    // parse through command line options
147    if (objc < 1) {
148        Tcl_AppendResult(interp,
149                "wrong # args: should be \"", cmdName,
150                " ?-as z|b64|zb64? ?-no-header? ?--? <string>\"", (char*)NULL);
151        return TCL_ERROR;
152    }
153
154    while ((objc - nextarg) > 0) {
155        option = Tcl_GetStringFromObj(objv[nextarg], &optionLen);
156        if (*option == '-') {
157            if ( strncmp(option,"-as",optionLen) == 0 ) {
158                nextarg++;
159                typeLen = 0;
160                if (nextarg < objc) {
161                    encodeType = Tcl_GetStringFromObj(objv[nextarg],&typeLen);
162                    nextarg++;
163                }
164                if (        (typeLen == 1) &&
165                            (strncmp(encodeType,"z",typeLen) == 0) ) {
166                    compress = 1;
167                    base64 = 0;
168                }
169                else if (   (typeLen == 3) &&
170                            (strncmp(encodeType,"b64",typeLen) == 0) ) {
171                    compress = 0;
172                    base64 = 1;
173                }
174                else if (   (typeLen == 4) &&
175                            (strncmp(encodeType,"zb64",typeLen) == 0) ) {
176                    compress = 1;
177                    base64 = 1;
178                }
179                else {
180                    // user did not specify recognized wishes for this option,
181                    Tcl_AppendResult(interp, "bad value \"",(char*)NULL);
182                    if (encodeType != NULL) {
183                        Tcl_AppendResult(interp, encodeType,(char*)NULL);
184                    }
185                    Tcl_AppendResult(interp,
186                            "\": should be one of z, b64, zb64",
187                            (char*)NULL);
188                    return TCL_ERROR;
189                }
190            }
191            else if ( strncmp(option,"-no-header",optionLen) == 0 ) {
192                nextarg++;
193                addHeader = 0;
194            }
195            else if ( strcmp(option,"--") == 0 ) {
196                nextarg++;
197                break;
198            }
199            else {
200                Tcl_AppendResult(interp,
201                    "bad option \"", option,
202                    "\": should be -as, -no-header, --", (char*)NULL);
203                return TCL_ERROR;
204            }
205        }
206        else {
207            break;
208        }
209    }
210
211    if ((objc - nextarg) != 1) {
212        Tcl_AppendResult(interp,
213                "wrong # args: should be \"", cmdName,
214                " ?-as z|b64|zb64? ?-no-header? ?--? <string>\"", (char*)NULL);
215        return TCL_ERROR;
216    }
217
218    option = (const char*) Tcl_GetByteArrayFromObj(objv[nextarg++], &optionLen);
219    buf = Rappture::Buffer(option,optionLen);
220
221    if (compress == 1) {
222        flags = flags | RPENC_Z;
223    }
224    if (base64 == 1) {
225        flags = flags | RPENC_B64;
226    }
227    if (addHeader == 1) {
228        flags = flags | RPENC_HDR;
229    }
230
231    err &= Rappture::encoding::encode(buf,flags);
232
233    if (!err) {
234        result = Tcl_NewByteArrayObj(
235            (const unsigned char*)buf.bytes(), buf.size());
236        Tcl_SetObjResult(interp, result);
237    }
238    else {
239        result = Tcl_GetObjResult(interp);
240        Tcl_AppendStringsToObj( result, err.remark().c_str(),
241                                "\n", err.context().c_str(), NULL   );
242    }
243    return TCL_OK;
244}
245
246/**********************************************************************/
247// FUNCTION: RpTclEncodingDecode()
248/// Rappture::encoding::decode function in Tcl, decodes provided string
249/**
250 * Decode a string by uncompressing it with zlib and base64 decoding it.
251 * If binary data is provided, the data is base64 decoded and uncompressed.
252 * RpTclEncodingIs is used to qualify binary data.
253 *
254 * Full function call:
255 * ::Rappture::encoding::decode ?-as z|b64|zb64? <string>
256 */
257
258static int
259RpTclEncodingDecode (   ClientData cdata,
260                        Tcl_Interp *interp,
261                        int objc,
262                        Tcl_Obj *const objv[]  )
263{
264
265    const char* encodeType    = NULL; // name of the units provided by user
266    const char* option        = NULL;
267    const char* cmdName       = NULL;
268    Rappture::Buffer buf      = ""; // name of the units provided by user
269    Rappture::Outcome err;
270
271    int optionLen             = 0;
272    int typeLen               = 0;
273    int nextarg               = 0; // start parsing using the '2'th argument
274
275    int decompress            = 0;
276    int base64                = 0;
277    int flags                 = 0;
278
279    Tcl_Obj *result           = NULL;
280
281    Tcl_ResetResult(interp);
282
283    cmdName = Tcl_GetString(objv[nextarg++]);
284
285    // parse through command line options
286    if (objc < 1) {
287        Tcl_AppendResult(interp,
288                "wrong # args: should be \"", cmdName,
289                " ?-as z|b64|zb64? ?--? <string>\"", (char*)NULL);
290        return TCL_ERROR;
291    }
292
293    while ((objc - nextarg) > 0) {
294        option = Tcl_GetStringFromObj(objv[nextarg], &optionLen);
295        if (*option == '-') {
296            if ( strncmp(option,"-as",optionLen) == 0 ) {
297                nextarg++;
298                typeLen = 0;
299                if (nextarg < objc) {
300                    encodeType = Tcl_GetStringFromObj(objv[nextarg],&typeLen);
301                    nextarg++;
302                }
303                if (        (typeLen == 1) &&
304                            (strncmp(encodeType,"z",typeLen) == 0) ) {
305                    decompress = 1;
306                    base64 = 0;
307                }
308                else if (   (typeLen == 3) &&
309                            (strncmp(encodeType,"b64",typeLen) == 0) ) {
310                    decompress = 0;
311                    base64 = 1;
312                }
313                else if (   (typeLen == 4) &&
314                            (strncmp(encodeType,"zb64",typeLen) == 0) ) {
315                    decompress = 1;
316                    base64 = 1;
317                }
318                else {
319                    // user did not specify recognized wishes for this option,
320                    Tcl_AppendResult(interp, "bad value \"",(char*)NULL);
321                    if (encodeType != NULL) {
322                        Tcl_AppendResult(interp, encodeType,(char*)NULL);
323                    }
324                    Tcl_AppendResult(interp,
325                            "\": should be one of z, b64, zb64",
326                            (char*)NULL);
327                    return TCL_ERROR;
328                }
329            } else if ( strcmp(option,"--") == 0 ) {
330                nextarg++;
331                break;
332            } else {
333                Tcl_AppendResult(interp,
334                    "bad option \"", option,
335                    "\": should be -as, --", (char*)NULL);
336                return TCL_ERROR;
337            }
338        } else {
339            break;
340        }
341    }
342
343    if ((objc - nextarg) != 1) {
344        Tcl_AppendResult(interp,
345                "wrong # args: should be \"", cmdName,
346                " ?-as z|b64|zb64? ?--? <string>\"", (char*)NULL);
347        return TCL_ERROR;
348    }
349
350    option = (const char*) Tcl_GetByteArrayFromObj(objv[nextarg++], &optionLen);
351
352    buf = Rappture::Buffer(option,optionLen);
353
354    if (decompress == 1) {
355        flags = flags | RPENC_Z;
356    }
357    if (base64 == 1) {
358        flags = flags | RPENC_B64;
359    }
360
361    err &= Rappture::encoding::decode(buf,flags);
362
363    if (!err) {
364        result = Tcl_NewByteArrayObj(
365            (const unsigned char*)buf.bytes(), buf.size());
366        Tcl_SetObjResult(interp, result);
367    }
368    else {
369        result = Tcl_GetObjResult(interp);
370        Tcl_AppendStringsToObj( result, err.remark().c_str(),
371                                "\n", err.context().c_str(), NULL   );
372    }
373    return TCL_OK;
374}
Note: See TracBrowser for help on using the repository browser.