1 /******************************************************************************
2 *
3 * Copyright (C) 2009, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13
14 func uint enbase64( uint u )
15 {
16 if u < 26 : return 'A' + u
17 if u < 52 : return 'a' + ( u-26 )
18 if u < 62 : return '0' + ( u-52 )
19 if u == 62 : return '+'
20
21 return '/'
22 }
23
24 func uint debase64( uint c )
25 {
26 if c >= 'A' && c <= 'Z' : return c - 'A'
27 if c >= 'a' && c <= 'z' : return c - 'a' + 26
28 if c >= '0' && c <= '9' : return c - '0' + 52
29 if c == '+' : return 62
30
31 return 63
32 }
33
34 func uint isbase64( uint c )
35 {
36 if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
37 (c >= '0' && c <= '9') || (c == '+') ||
38 (c == '/') || (c == '=')
39 {
40 return 1
41 }
42 return 0
43 }
44
45 method str str.tobase64( str input )
46 {
47 uint size i
48
49 this.clear()
50
51 size = *input
52
53 this.reserve( size * 4 / 3 + 4 )
54
55 for i=0, i<size, i+=3
56 {
57 uint b1 b2 b3 b4 b5 b6 b7
58
59 b1 = input[i]
60
61 if i+1 < size : b2 = input[i+1]
62
63 if i+2 < size : b3 = input[i+2]
64
65 b4 = b1>>2
66 b5 = ((b1&0x3)<<4)|(b2>>4)
67 b6 = ((b2&0xf)<<2)|(b3>>6)
68 b7 = b3&0x3f
69
70 this.appendch( enbase64( b4 ))
71 this.appendch( enbase64( b5 ))
72
73 if i+1 < size : this.appendch( enbase64( b6 ))
74 else : this.appendch( '=' )
75
76 if i+2 < size : this.appendch( enbase64( b7 ))
77 else : this.appendch( '=' )
78 }
79 return this
80 }
81
82 method str str.frombase64( str input )
83 {
84 str stemp
85 uint k l
86
87 this.clear()
88
89 if !*input : return this
90
91 this.reserve( *input + 4 )
92 stemp.reserve( *input + 1 )
93 fornum k, *input
94 {
95 if isbase64( input[k] ) : stemp[l++] = input[k]
96 }
97 stemp.setlen( l )
98
99 for k=0, k<l, k+=4
100 {
101 uint c1='A', c2='A', c3='A', c4='A'
102 uint b1 b2 b3 b4
103
104 c1 = stemp[ k ]
105
106 if k+1 < l : c2 = stemp[ k+1 ]
107 if k+2 < l : c3 = stemp[ k+2 ]
108 if k+3 < l : c4 = stemp[ k+3 ]
109 b1= debase64(c1)
110 b2= debase64(c2)
111 b3= debase64(c3)
112 b4= debase64(c4)
113
114 this.appendch( (b1<<2)|(b2>>4) )
115
116 if c3 != '=' : this.appendch( ((b2&0xf)<<4)|(b3>>2) )
117 if c4 != '=' : this.appendch( ((b3&0x3)<<6)|b4 )
118 }
119 return this
120 }
121