source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/base64/yencode.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 9.6 KB
Line 
1# yencode.tcl - Copyright (C) 2002 Pat Thoyts <patthoyts@users.sourceforge.net>
2#
3# Provide a Tcl only implementation of yEnc encoding algorithm
4#
5# -------------------------------------------------------------------------
6# See the file "license.terms" for information on usage and redistribution
7# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
8# -------------------------------------------------------------------------
9# @(#)$Id: yencode.tcl,v 1.11 2005/09/28 04:51:19 andreas_kupries Exp $
10
11package require Tcl 8.2;                # tcl minimum version
12catch {package require crc32};          # tcllib 1.1
13catch {package require tcllibc};        # critcl enhancements for tcllib
14
15namespace eval ::yencode {
16    variable version 1.1.1
17    namespace export encode decode yencode ydecode
18}
19
20# -------------------------------------------------------------------------
21
22proc ::yencode::Encode {s} {
23    set r {}
24    binary scan $s c* d
25    foreach {c} $d {
26        set v [expr {($c + 42) % 256}]
27        if {$v == 0x00 || $v == 0x09 || $v == 0x0A
28            || $v == 0x0D || $v == 0x3D} {
29            append r "="
30            set v [expr {($v + 42) % 256}]
31        }
32        append r [format %c $v]
33    }
34    return $r
35}
36
37proc ::yencode::Decode {s} {
38    if {[string length $s] == 0} {return ""}
39    set r {}
40    set esc 0
41    binary scan $s c* d
42    foreach c $d {
43        if {$c == 61 && $esc == 0} {
44            set esc 1
45            continue
46        }
47        set v [expr {($c - 42) % 256}]
48        if {$esc} {
49            set v [expr {($v - 42) % 256}]
50            set esc 0
51        }
52        append r [format %c $v]
53    }
54    return $r
55}
56
57# -------------------------------------------------------------------------
58# C coded versions for critcl built base64c package
59# -------------------------------------------------------------------------
60
61if {[package provide critcl] != {}} {
62    namespace eval ::yencode {
63        critcl::ccode {
64            #include <string.h>
65        }
66        critcl::ccommand CEncode {dummy interp objc objv} {
67            Tcl_Obj *inputPtr, *resultPtr;
68            int len, rlen, xtra;
69            unsigned char *input, *p, *r, v;
70           
71            if (objc !=  2) {
72                Tcl_WrongNumArgs(interp, 1, objv, "data");
73                return TCL_ERROR;
74            }
75           
76            /* fetch the input data */
77            inputPtr = objv[1];
78            input = Tcl_GetByteArrayFromObj(inputPtr, &len);
79
80            /* calculate the length of the encoded result */
81            rlen = len;
82            for (p = input; p < input + len; p++) {
83                v = (*p + 42) % 256;
84                if (v == 0 || v == 9 || v == 0x0A || v == 0x0D || v == 0x3D)
85                   rlen++;
86            }
87           
88            /* allocate the output buffer */
89            resultPtr = Tcl_GetObjResult(interp);
90            if (Tcl_IsShared(resultPtr)) {
91                resultPtr = Tcl_DuplicateObj(resultPtr);
92                Tcl_SetObjResult(interp, resultPtr);
93            }
94            r = Tcl_SetByteArrayLength(resultPtr, rlen);
95           
96            /* encode the input */
97            for (p = input; p < input + len; p++) {
98                v = (*p + 42) % 256;
99                if (v == 0 || v == 9 || v == 0x0A || v == 0x0D || v == 0x3D) {
100                    *r++ = '=';
101                    v = (v + 42) % 256;
102                }
103                *r++ = v;
104            }
105
106            return TCL_OK;
107        }
108
109        critcl::ccommand CDecode {dummy interp objc objv} {
110            Tcl_Obj *inputPtr, *resultPtr;
111            int len, rlen, esc;
112            unsigned char *input, *p, *r, v;
113           
114            if (objc !=  2) {
115                Tcl_WrongNumArgs(interp, 1, objv, "data");
116                return TCL_ERROR;
117            }
118           
119            /* fetch the input data */
120            inputPtr = objv[1];
121            input = Tcl_GetByteArrayFromObj(inputPtr, &len);
122
123            /* allocate the output buffer */
124            resultPtr = Tcl_GetObjResult(interp);
125            if (Tcl_IsShared(resultPtr)) {
126                resultPtr = Tcl_DuplicateObj(resultPtr);
127                Tcl_SetObjResult(interp, resultPtr);
128            }
129            r = Tcl_SetByteArrayLength(resultPtr, len);
130           
131            /* encode the input */
132            for (p = input, esc = 0, rlen = 0; p < input + len; p++) {
133                if (*p == 61 && esc == 0) {
134                    esc = 1;
135                    continue;
136                }
137                v = (*p - 42) % 256;
138                if (esc) {
139                    v = (v - 42) % 256;
140                    esc = 0;
141                }
142                *r++ = v;
143                rlen++;
144            }
145            Tcl_SetByteArrayLength(resultPtr, rlen);
146
147            return TCL_OK;
148        }
149    }
150}
151
152if {[info command ::yencode::CEncode] != {}} {
153    interp alias {} ::yencode::encode {} ::yencode::CEncode
154    interp alias {} ::yencode::decode {} ::yencode::CDecode
155} else {
156    interp alias {} ::yencode::encode {} ::yencode::Encode
157    interp alias {} ::yencode::decode {} ::yencode::Decode
158}
159
160# -------------------------------------------------------------------------
161# Description:
162#  Pop the nth element off a list. Used in options processing.
163#
164proc ::yencode::Pop {varname {nth 0}} {
165    upvar $varname args
166    set r [lindex $args $nth]
167    set args [lreplace $args $nth $nth]
168    return $r
169}
170
171# -------------------------------------------------------------------------
172
173proc ::yencode::yencode {args} {
174    array set opts {mode 0644 filename {} name {} line 128 crc32 1}
175    while {[string match -* [lindex $args 0]]} {
176        switch -glob -- [lindex $args 0] {
177            -f* { set opts(filename) [Pop args 1] }
178            -m* { set opts(mode) [Pop args 1] }
179            -n* { set opts(name) [Pop args 1] }
180            -l* { set opts(line) [Pop args 1] }
181            -c* { set opts(crc32) [Pop args 1] }
182            --  { Pop args ; break }
183            default {
184                set options [join [lsort [array names opts]] ", -"]
185                return -code error "bad option [lindex $args 0]:\
186                      must be -$options"
187            }
188        }
189        Pop args
190    }
191
192    if {$opts(name) == {}} {
193        set opts(name) $opts(filename)
194    }
195    if {$opts(name) == {}} {
196        set opts(name) "data.dat"
197    }
198    if {! [string is boolean $opts(crc32)]} {
199        return -code error "bad option -crc32: argument must be true or false"
200    }
201
202    if {$opts(filename) != {}} {
203        set f [open $opts(filename) r]
204        fconfigure $f -translation binary
205        set data [read $f]
206        close $f
207    } else {
208        if {[llength $args] != 1} {
209            return -code error "wrong \# args: should be\
210                  \"yencode ?options? -file name | data\""
211        }
212        set data [lindex $args 0]
213    }
214   
215    set opts(size) [string length $data]
216   
217    set r {}
218    append r [format "=ybegin line=%d size=%d name=%s" \
219                  $opts(line) $opts(size) $opts(name)] "\n"
220
221    set ndx 0
222    while {$ndx < $opts(size)} {
223        set pln [string range $data $ndx [expr {$ndx + $opts(line) - 1}]]
224        set enc [encode $pln]
225        incr ndx [string length $pln]
226        append r $enc "\r\n"
227    }
228
229    append r [format "=yend size=%d" $ndx]
230    if {$opts(crc32)} {
231        append r " crc32=" [crc::crc32 -format %x $data]
232    }
233    return $r
234}
235
236# -------------------------------------------------------------------------
237# Description:
238#  Perform ydecoding of a file or data. A file may contain more than one
239#  encoded data section so the result is a list where each element is a
240#  three element list of the provided filename, the file size and the
241#  data itself.
242#
243proc ::yencode::ydecode {args} {
244    array set opts {mode 0644 filename {} name default.bin}
245    while {[string match -* [lindex $args 0]]} {
246        switch -glob -- [lindex $args 0] {
247            -f* { set opts(filename) [Pop args 1] }
248            -- { Pop args ; break; }
249            default {
250                set options [join [lsort [array names opts]] ", -"]
251                return -code error "bad option [lindex $args 0]:\
252                      must be -$opts"
253            }
254        }
255        Pop args
256    }
257
258    if {$opts(filename) != {}} {
259        set f [open $opts(filename) r]
260        set data [read $f]
261        close $f
262    } else {
263        if {[llength $args] != 1} {
264            return -code error "wrong \# args: should be\
265                  \"ydecode ?options? -file name | data\""
266        }
267        set data [lindex $args 0]
268    }
269
270    set state false
271    set result {}
272
273    foreach {line} [split $data "\n"] {
274        set line [string trimright $line "\r\n"]
275        switch -exact -- $state {
276            false {
277                if {[string match "=ybegin*" $line]} {
278                    regexp {line=(\d+)} $line -> opts(line)
279                    regexp {size=(\d+)} $line -> opts(size)
280                    regexp {name=(\d+)} $line -> opts(name)
281
282                    if {$opts(name) == {}} {
283                        set opts(name) default.bin
284                    }
285
286                    set state true
287                    set r {}
288                }
289            }
290
291            true {
292                if {[string match "=yend*" $line]} {
293                    set state false
294                    lappend result [list $opts(name) $opts(size) $r]
295                } else {
296                    append r [decode $line]
297                }
298            }
299        }
300    }
301
302    return $result
303}
304
305# -------------------------------------------------------------------------
306
307package provide yencode $::yencode::version
308
309# -------------------------------------------------------------------------
310#
311# Local variables:
312#   mode: tcl
313#   indent-tabs-mode: nil
314# End:
315
Note: See TracBrowser for help on using the repository browser.