~ubuntu-branches/ubuntu/gutsy/amsn/gutsy

« back to all changes in this revision

Viewing changes to utils/base64/uuencode.tcl

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Karkoulis
  • Date: 2006-01-04 15:26:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104152602-ipe1yg00rl3nlklv
Tags: 0.95-1
New Upstream Release (closes: #345052, #278575).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# uuencode - Copyright (C) 2002 Pat Thoyts <patthoyts@users.sourceforge.net>
 
2
#
 
3
# Provide a Tcl only implementation of uuencode and uudecode.
 
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: uuencode.tcl,v 1.1 2004/12/03 15:51:40 germinator2000 Exp $
 
10
 
 
11
package require Tcl 8.2;                # tcl minimum version
 
12
package require log;                    # tcllib 1.0
 
13
 
 
14
namespace eval ::uuencode {
 
15
    variable version 1.0.2
 
16
 
 
17
    namespace export encode decode uuencode uudecode
 
18
}
 
19
 
 
20
proc ::uuencode::Enc {c} {
 
21
    return [format %c [expr {($c != 0) ? (($c & 0x3f) + 0x20) : 0x60}]]
 
22
}
 
23
 
 
24
proc ::uuencode::Encode {s} {
 
25
    set r {}
 
26
    binary scan $s c* d
 
27
    foreach {c1 c2 c3} $d {
 
28
        if {$c1 == {}} {set c1 0}
 
29
        if {$c2 == {}} {set c2 0}
 
30
        if {$c3 == {}} {set c3 0}
 
31
        append r [Enc [expr {$c1 >> 2}]]
 
32
        append r [Enc [expr {(($c1 << 4) & 060) | (($c2 >> 4) & 017)}]]
 
33
        append r [Enc [expr {(($c2 << 2) & 074) | (($c3 >> 6) & 003)}]]
 
34
        append r [Enc [expr {($c3 & 077)}]]
 
35
    }
 
36
    return $r
 
37
}
 
38
 
 
39
proc ::uuencode::Decode {s} {
 
40
    if {[string length $s] == 0} {return ""}
 
41
    set r {}
 
42
    binary scan [pad $s] c* d
 
43
        
 
44
    foreach {c0 c1 c2 c3} $d {
 
45
        append r [format %c [expr {((($c0-0x20)&0x3F) << 2) & 0xFF
 
46
                                   | ((($c1-0x20)&0x3F) >> 4) & 0xFF}]]
 
47
        append r [format %c [expr {((($c1-0x20)&0x3F) << 4) & 0xFF
 
48
                                   | ((($c2-0x20)&0x3F) >> 2) & 0xFF}]]
 
49
        append r [format %c [expr {((($c2-0x20)&0x3F) << 6) & 0xFF
 
50
                                   | (($c3-0x20)&0x3F) & 0xFF}]]
 
51
    }
 
52
    return $r
 
53
}
 
54
 
 
55
# -------------------------------------------------------------------------
 
56
 
 
57
# Description:
 
58
#  Permit more tolerant decoding of invalid input strings by padding to
 
59
#  a multiple of 4 bytes with nulls.
 
60
# Result:
 
61
#  Returns the input string - possibly padded with uuencoded null chars.
 
62
#
 
63
proc ::uuencode::pad {s} {
 
64
    if {[set mod [expr {[string length $s] % 4}]] != 0} {
 
65
        log::log notice "invalid uuencoded string: padding string to a\
 
66
              multiple of 4."
 
67
        append s [string repeat "`" [expr {4 - $mod}]]
 
68
    }
 
69
    return $s
 
70
}
 
71
 
 
72
# -------------------------------------------------------------------------
 
73
 
 
74
# If the Trf package is available then we shall use this by default but the
 
75
# Tcllib implementations are always visible if needed (ie: for testing)
 
76
if {[catch {package require Trf 2.0}]} {
 
77
    interp alias {} ::uuencode::encode {} ::uuencode::Encode
 
78
    interp alias {} ::uuencode::decode {} ::uuencode::Decode
 
79
} else {
 
80
    proc ::uuencode::encode {s} {
 
81
        return [::uuencode -mode encode -- $s]
 
82
    }
 
83
    proc ::uuencode::decode {s} {
 
84
        return [::uuencode -mode decode -- [pad $s]]
 
85
    }
 
86
}
 
87
 
 
88
# -------------------------------------------------------------------------
 
89
 
 
90
proc ::uuencode::uuencode {args} {
 
91
    array set opts {mode 0644 filename {} name {}}
 
92
    while {[string match -* [lindex $args 0]]} {
 
93
        switch -glob -- [lindex $args 0] {
 
94
            -f* {
 
95
                set opts(filename) [lindex $args 1]
 
96
                set args [lreplace $args 0 0]
 
97
            }
 
98
            -m* {
 
99
                set opts(mode) [lindex $args 1]
 
100
                set args [lreplace $args 0 0]
 
101
            }
 
102
            -n* {
 
103
                set opts(name) [lindex $args 1]
 
104
                set args [lreplace $args 0 0]
 
105
            }
 
106
            -- {
 
107
                set args [lreplace $args 0 0]
 
108
                break
 
109
            }
 
110
            default {
 
111
                return -code error "bad option [lindex $args 0]:\
 
112
                      must be -filename or -mode"
 
113
            }
 
114
        }
 
115
        set args [lreplace $args 0 0]
 
116
    }
 
117
 
 
118
    if {$opts(name) == {}} {
 
119
        set opts(name) $opts(filename)
 
120
    }
 
121
    if {$opts(name) == {}} {
 
122
        set opts(name) "data.dat"
 
123
    }
 
124
 
 
125
    if {$opts(filename) != {}} {
 
126
        set f [open $opts(filename) r]
 
127
        fconfigure $f -translation binary
 
128
        set data [read $f]
 
129
        close $f
 
130
    } else {
 
131
        if {[llength $args] != 1} {
 
132
            return -code error "wrong \# args: should be\
 
133
                  \"uuencode ?-mode oct? -file name | data\""
 
134
        }
 
135
        set data [lindex $args 0]
 
136
    }
 
137
 
 
138
    set r {}
 
139
    append r [format "begin %o %s" $opts(mode) $opts(name)] "\n"
 
140
    for {set n 0} {$n < [string length $data]} {incr n 45} {
 
141
        set s [string range $data $n [expr {$n + 44}]]
 
142
        append r [Enc [string length $s]]
 
143
        append r [encode $s] "\n"
 
144
    }
 
145
    append r "`\nend"
 
146
    return $r
 
147
}
 
148
 
 
149
# -------------------------------------------------------------------------
 
150
# Description:
 
151
#  Perform uudecoding of a file or data. A file may contain more than one
 
152
#  encoded data section so the result is a list where each element is a 
 
153
#  three element list of the provided filename, the suggested mode and the 
 
154
#  data itself.
 
155
#
 
156
proc ::uuencode::uudecode {args} {
 
157
    array set opts {mode 0644 filename {}}
 
158
    while {[string match -* [lindex $args 0]]} {
 
159
        switch -glob -- [lindex $args 0] {
 
160
            -f* {
 
161
                set opts(filename) [lindex $args 1]
 
162
                set args [lreplace $args 0 0]
 
163
            }
 
164
            -- {
 
165
                set args [lreplace $args 0 0]
 
166
                break
 
167
            }
 
168
            default {
 
169
                return -code error "bad option [lindex $args 0]:\
 
170
                      must be -filename or -mode"
 
171
            }
 
172
        }
 
173
        set args [lreplace $args 0 0]
 
174
    }
 
175
 
 
176
    if {$opts(filename) != {}} {
 
177
        set f [open $opts(filename) r]
 
178
        set data [read $f]
 
179
        close $f
 
180
    } else {
 
181
        if {[llength $args] != 1} {
 
182
            return -code error "wrong \# args: should be\
 
183
                  \"uudecode -file name | data\""
 
184
        }
 
185
        set data [lindex $args 0]
 
186
    }
 
187
 
 
188
    set state false
 
189
    set result {}
 
190
 
 
191
    foreach {line} [split $data "\n"] {
 
192
        switch -exact -- $state {
 
193
            false {
 
194
                if {[regexp {^begin ([0-7]+) ([^\s]*)} $line \
 
195
                         -> opts(mode) opts(name)]} {
 
196
                    set state true
 
197
                    set r {}
 
198
                }
 
199
            }
 
200
 
 
201
            true {
 
202
                if {[string match "end" $line]} {
 
203
                    set state false
 
204
                    lappend result [list $opts(name) $opts(mode) $r]
 
205
                } else {
 
206
                    scan $line %c c
 
207
                    set n [expr {($c - 0x21)}]
 
208
                    append r [string range \
 
209
                                  [decode [string range $line 1 end]] 0 $n]
 
210
                }
 
211
            }
 
212
        }
 
213
    }
 
214
 
 
215
    return $result
 
216
}
 
217
 
 
218
# -------------------------------------------------------------------------
 
219
 
 
220
package provide uuencode $::uuencode::version
 
221
 
 
222
# -------------------------------------------------------------------------
 
223
#
 
224
# Local variables:
 
225
#   mode: tcl
 
226
#   indent-tabs-mode: nil
 
227
# End:
 
228