Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
371aa14e
Commit
371aa14e
authored
Jun 14, 2011
by
David Symonds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mail: decode RFC 2047 "B" encoding.
R=rsc, r CC=golang-dev
https://golang.org/cl/4584056
parent
c6c8dbd6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
29 deletions
+83
-29
message.go
src/pkg/mail/message.go
+61
-28
message_test.go
src/pkg/mail/message_test.go
+22
-1
No files found.
src/pkg/mail/message.go
View file @
371aa14e
...
...
@@ -18,8 +18,10 @@ package mail
import
(
"bufio"
"bytes"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"log"
"net/textproto"
"os"
...
...
@@ -57,7 +59,7 @@ func ReadMessage(r io.Reader) (msg *Message, err os.Error) {
return
&
Message
{
Header
:
Header
(
hdr
),
Body
:
tp
.
R
,
},
nil
},
nil
}
// Layouts suitable for passing to time.Parse.
...
...
@@ -226,7 +228,7 @@ func (p *addrParser) parseAddress() (addr *Address, err os.Error) {
if
err
==
nil
{
return
&
Address
{
Address
:
spec
,
},
err
},
err
}
debug
.
Printf
(
"parseAddress: not an addr-spec: %v"
,
err
)
debug
.
Printf
(
"parseAddress: state is now %q"
,
*
p
)
...
...
@@ -258,7 +260,7 @@ func (p *addrParser) parseAddress() (addr *Address, err os.Error) {
return
&
Address
{
Name
:
displayName
,
Address
:
spec
,
},
nil
},
nil
}
// consumeAddrSpec parses a single RFC 5322 addr-spec at the start of p.
...
...
@@ -428,37 +430,68 @@ func decodeRFC2047Word(s string) (string, os.Error) {
return
""
,
os
.
ErrorString
(
"mail: address not RFC 2047 encoded"
)
}
charset
,
enc
:=
strings
.
ToLower
(
fields
[
1
]),
strings
.
ToLower
(
fields
[
2
])
// TODO(dsymonds): Support "b" encoding too.
if
enc
!=
"q"
{
return
""
,
fmt
.
Errorf
(
"mail: RFC 2047 encoding not supported: %q"
,
enc
)
}
if
charset
!=
"iso-8859-1"
&&
charset
!=
"utf-8"
{
return
""
,
fmt
.
Errorf
(
"mail: charset not supported: %q"
,
charset
)
}
in
:=
fields
[
3
]
b
:=
new
(
bytes
.
Buffer
)
for
i
:=
0
;
i
<
len
(
in
);
i
++
{
switch
c
:=
in
[
i
];
{
case
c
==
'='
&&
i
+
2
<
len
(
in
)
:
x
,
err
:=
strconv
.
Btoi64
(
in
[
i
+
1
:
i
+
3
],
16
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"mail: invalid RFC 2047 encoding: %q"
,
in
[
i
:
i
+
3
])
}
i
+=
2
switch
charset
{
case
"iso-8859-1"
:
b
.
WriteRune
(
int
(
x
))
case
"utf-8"
:
b
.
WriteByte
(
byte
(
x
))
}
case
c
==
'_'
:
b
.
WriteByte
(
' '
)
default
:
b
.
WriteByte
(
c
)
in
:=
bytes
.
NewBufferString
(
fields
[
3
])
var
r
io
.
Reader
switch
enc
{
case
"b"
:
r
=
base64
.
NewDecoder
(
base64
.
StdEncoding
,
in
)
case
"q"
:
r
=
qDecoder
{
r
:
in
}
default
:
return
""
,
fmt
.
Errorf
(
"mail: RFC 2047 encoding not supported: %q"
,
enc
)
}
dec
,
err
:=
ioutil
.
ReadAll
(
r
)
if
err
!=
nil
{
return
""
,
err
}
switch
charset
{
case
"iso-8859-1"
:
b
:=
new
(
bytes
.
Buffer
)
for
_
,
c
:=
range
dec
{
b
.
WriteRune
(
int
(
c
))
}
return
b
.
String
(),
nil
case
"utf-8"
:
return
string
(
dec
),
nil
}
panic
(
"unreachable"
)
}
type
qDecoder
struct
{
r
io
.
Reader
scratch
[
2
]
byte
}
func
(
qd
qDecoder
)
Read
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
// This method writes at most one byte into p.
if
len
(
p
)
==
0
{
return
0
,
nil
}
if
_
,
err
:=
qd
.
r
.
Read
(
qd
.
scratch
[
:
1
]);
err
!=
nil
{
return
0
,
err
}
switch
c
:=
qd
.
scratch
[
0
];
{
case
c
==
'='
:
if
_
,
err
:=
io
.
ReadFull
(
qd
.
r
,
qd
.
scratch
[
:
2
]);
err
!=
nil
{
return
0
,
err
}
x
,
err
:=
strconv
.
Btoi64
(
string
(
qd
.
scratch
[
:
2
]),
16
)
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"mail: invalid RFC 2047 encoding: %q"
,
qd
.
scratch
[
:
2
])
}
p
[
0
]
=
byte
(
x
)
case
c
==
'_'
:
p
[
0
]
=
' '
default
:
p
[
0
]
=
c
}
return
b
.
String
()
,
nil
return
1
,
nil
}
var
atextChars
=
[]
byte
(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
...
...
src/pkg/mail/message_test.go
View file @
371aa14e
...
...
@@ -217,6 +217,27 @@ func TestAddressParsing(t *testing.T) {
},
},
},
// Custom example of RFC 2047 "B"-encoded ISO-8859-1 address.
{
`=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`
,
[]
*
Address
{
&
Address
{
Name
:
`Jörg`
,
Address
:
"joerg@example.com"
,
},
},
},
// Custom example of RFC 2047 "B"-encoded UTF-8 address.
{
// XXX: a different example
`=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`
,
[]
*
Address
{
&
Address
{
Name
:
`Jörg`
,
Address
:
"joerg@example.com"
,
},
},
},
}
for
_
,
test
:=
range
tests
{
addrs
,
err
:=
newAddrParser
(
test
.
addrsStr
)
.
parseAddressList
()
...
...
@@ -225,7 +246,7 @@ func TestAddressParsing(t *testing.T) {
continue
}
if
!
reflect
.
DeepEqual
(
addrs
,
test
.
exp
)
{
t
.
Errorf
(
"Parse of %q: got %+v, want %+v"
,
test
.
addrsStr
,
addrs
,
test
.
exp
)
t
.
Errorf
(
"Parse of %q: got %+v, want %+v"
,
test
.
addrsStr
,
*
addrs
[
0
],
*
test
.
exp
[
0
]
)
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment